0001
0002
0003
0004
0005
0006
0007 #include <linux/hdreg.h>
0008 #include <linux/blkdev.h>
0009 #include <linux/completion.h>
0010 #include <linux/delay.h>
0011 #include <linux/slab.h>
0012 #include <linux/mutex.h>
0013 #include <linux/skbuff.h>
0014 #include <linux/export.h>
0015 #include "aoe.h"
0016
0017 enum {
0018
0019 MINOR_ERR = 2,
0020 MINOR_DISCOVER,
0021 MINOR_INTERFACES,
0022 MINOR_REVALIDATE,
0023 MINOR_FLUSH,
0024 MSGSZ = 2048,
0025 NMSG = 100,
0026 };
0027
0028 struct aoe_chardev {
0029 ulong minor;
0030 char name[32];
0031 };
0032
0033 enum { EMFL_VALID = 1 };
0034
0035 struct ErrMsg {
0036 short flags;
0037 short len;
0038 char *msg;
0039 };
0040
0041 static DEFINE_MUTEX(aoechr_mutex);
0042
0043
0044
0045
0046
0047 static struct ErrMsg emsgs[NMSG];
0048 static int emsgs_head_idx, emsgs_tail_idx;
0049 static struct completion emsgs_comp;
0050 static spinlock_t emsgs_lock;
0051 static int nblocked_emsgs_readers;
0052 static struct class *aoe_class;
0053 static struct aoe_chardev chardevs[] = {
0054 { MINOR_ERR, "err" },
0055 { MINOR_DISCOVER, "discover" },
0056 { MINOR_INTERFACES, "interfaces" },
0057 { MINOR_REVALIDATE, "revalidate" },
0058 { MINOR_FLUSH, "flush" },
0059 };
0060
0061 static int
0062 discover(void)
0063 {
0064 aoecmd_cfg(0xffff, 0xff);
0065 return 0;
0066 }
0067
0068 static int
0069 interfaces(const char __user *str, size_t size)
0070 {
0071 if (set_aoe_iflist(str, size)) {
0072 printk(KERN_ERR
0073 "aoe: could not set interface list: too many interfaces\n");
0074 return -EINVAL;
0075 }
0076 return 0;
0077 }
0078
0079 static int
0080 revalidate(const char __user *str, size_t size)
0081 {
0082 int major, minor, n;
0083 ulong flags;
0084 struct aoedev *d;
0085 struct sk_buff *skb;
0086 char buf[16];
0087
0088 if (size >= sizeof buf)
0089 return -EINVAL;
0090 buf[sizeof buf - 1] = '\0';
0091 if (copy_from_user(buf, str, size))
0092 return -EFAULT;
0093
0094 n = sscanf(buf, "e%d.%d", &major, &minor);
0095 if (n != 2) {
0096 pr_err("aoe: invalid device specification %s\n", buf);
0097 return -EINVAL;
0098 }
0099 d = aoedev_by_aoeaddr(major, minor, 0);
0100 if (!d)
0101 return -EINVAL;
0102 spin_lock_irqsave(&d->lock, flags);
0103 aoecmd_cleanslate(d);
0104 aoecmd_cfg(major, minor);
0105 loop:
0106 skb = aoecmd_ata_id(d);
0107 spin_unlock_irqrestore(&d->lock, flags);
0108
0109
0110
0111 if (!skb && !msleep_interruptible(250)) {
0112 spin_lock_irqsave(&d->lock, flags);
0113 goto loop;
0114 }
0115 aoedev_put(d);
0116 if (skb) {
0117 struct sk_buff_head queue;
0118 __skb_queue_head_init(&queue);
0119 __skb_queue_tail(&queue, skb);
0120 aoenet_xmit(&queue);
0121 }
0122 return 0;
0123 }
0124
0125 void
0126 aoechr_error(char *msg)
0127 {
0128 struct ErrMsg *em;
0129 char *mp;
0130 ulong flags, n;
0131
0132 n = strlen(msg);
0133
0134 spin_lock_irqsave(&emsgs_lock, flags);
0135
0136 em = emsgs + emsgs_tail_idx;
0137 if ((em->flags & EMFL_VALID)) {
0138 bail: spin_unlock_irqrestore(&emsgs_lock, flags);
0139 return;
0140 }
0141
0142 mp = kmemdup(msg, n, GFP_ATOMIC);
0143 if (!mp)
0144 goto bail;
0145
0146 em->msg = mp;
0147 em->flags |= EMFL_VALID;
0148 em->len = n;
0149
0150 emsgs_tail_idx++;
0151 emsgs_tail_idx %= ARRAY_SIZE(emsgs);
0152
0153 spin_unlock_irqrestore(&emsgs_lock, flags);
0154
0155 if (nblocked_emsgs_readers)
0156 complete(&emsgs_comp);
0157 }
0158
0159 static ssize_t
0160 aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp)
0161 {
0162 int ret = -EINVAL;
0163
0164 switch ((unsigned long) filp->private_data) {
0165 default:
0166 printk(KERN_INFO "aoe: can't write to that file.\n");
0167 break;
0168 case MINOR_DISCOVER:
0169 ret = discover();
0170 break;
0171 case MINOR_INTERFACES:
0172 ret = interfaces(buf, cnt);
0173 break;
0174 case MINOR_REVALIDATE:
0175 ret = revalidate(buf, cnt);
0176 break;
0177 case MINOR_FLUSH:
0178 ret = aoedev_flush(buf, cnt);
0179 break;
0180 }
0181 if (ret == 0)
0182 ret = cnt;
0183 return ret;
0184 }
0185
0186 static int
0187 aoechr_open(struct inode *inode, struct file *filp)
0188 {
0189 int n, i;
0190
0191 mutex_lock(&aoechr_mutex);
0192 n = iminor(inode);
0193 filp->private_data = (void *) (unsigned long) n;
0194
0195 for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
0196 if (chardevs[i].minor == n) {
0197 mutex_unlock(&aoechr_mutex);
0198 return 0;
0199 }
0200 mutex_unlock(&aoechr_mutex);
0201 return -EINVAL;
0202 }
0203
0204 static int
0205 aoechr_rel(struct inode *inode, struct file *filp)
0206 {
0207 return 0;
0208 }
0209
0210 static ssize_t
0211 aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
0212 {
0213 unsigned long n;
0214 char *mp;
0215 struct ErrMsg *em;
0216 ssize_t len;
0217 ulong flags;
0218
0219 n = (unsigned long) filp->private_data;
0220 if (n != MINOR_ERR)
0221 return -EFAULT;
0222
0223 spin_lock_irqsave(&emsgs_lock, flags);
0224
0225 for (;;) {
0226 em = emsgs + emsgs_head_idx;
0227 if ((em->flags & EMFL_VALID) != 0)
0228 break;
0229 if (filp->f_flags & O_NDELAY) {
0230 spin_unlock_irqrestore(&emsgs_lock, flags);
0231 return -EAGAIN;
0232 }
0233 nblocked_emsgs_readers++;
0234
0235 spin_unlock_irqrestore(&emsgs_lock, flags);
0236
0237 n = wait_for_completion_interruptible(&emsgs_comp);
0238
0239 spin_lock_irqsave(&emsgs_lock, flags);
0240
0241 nblocked_emsgs_readers--;
0242
0243 if (n) {
0244 spin_unlock_irqrestore(&emsgs_lock, flags);
0245 return -ERESTARTSYS;
0246 }
0247 }
0248 if (em->len > cnt) {
0249 spin_unlock_irqrestore(&emsgs_lock, flags);
0250 return -EAGAIN;
0251 }
0252 mp = em->msg;
0253 len = em->len;
0254 em->msg = NULL;
0255 em->flags &= ~EMFL_VALID;
0256
0257 emsgs_head_idx++;
0258 emsgs_head_idx %= ARRAY_SIZE(emsgs);
0259
0260 spin_unlock_irqrestore(&emsgs_lock, flags);
0261
0262 n = copy_to_user(buf, mp, len);
0263 kfree(mp);
0264 return n == 0 ? len : -EFAULT;
0265 }
0266
0267 static const struct file_operations aoe_fops = {
0268 .write = aoechr_write,
0269 .read = aoechr_read,
0270 .open = aoechr_open,
0271 .release = aoechr_rel,
0272 .owner = THIS_MODULE,
0273 .llseek = noop_llseek,
0274 };
0275
0276 static char *aoe_devnode(struct device *dev, umode_t *mode)
0277 {
0278 return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev));
0279 }
0280
0281 int __init
0282 aoechr_init(void)
0283 {
0284 int n, i;
0285
0286 n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
0287 if (n < 0) {
0288 printk(KERN_ERR "aoe: can't register char device\n");
0289 return n;
0290 }
0291 init_completion(&emsgs_comp);
0292 spin_lock_init(&emsgs_lock);
0293 aoe_class = class_create(THIS_MODULE, "aoe");
0294 if (IS_ERR(aoe_class)) {
0295 unregister_chrdev(AOE_MAJOR, "aoechr");
0296 return PTR_ERR(aoe_class);
0297 }
0298 aoe_class->devnode = aoe_devnode;
0299
0300 for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
0301 device_create(aoe_class, NULL,
0302 MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
0303 chardevs[i].name);
0304
0305 return 0;
0306 }
0307
0308 void
0309 aoechr_exit(void)
0310 {
0311 int i;
0312
0313 for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
0314 device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
0315 class_destroy(aoe_class);
0316 unregister_chrdev(AOE_MAJOR, "aoechr");
0317 }
0318