1 /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ 2 /* 3 * aoechr.c 4 * AoE character device driver 5 */ 6 7 #include <linux/hdreg.h> 8 #include <linux/blkdev.h> 9 #include <linux/completion.h> 10 #include <linux/delay.h> 11 #include <linux/slab.h> 12 #include <linux/mutex.h> 13 #include <linux/skbuff.h> 14 #include <linux/export.h> 15 #include "aoe.h" 16 17 enum { 18 //MINOR_STAT = 1, (moved to sysfs) 19 MINOR_ERR = 2, 20 MINOR_DISCOVER, 21 MINOR_INTERFACES, 22 MINOR_REVALIDATE, 23 MINOR_FLUSH, 24 MSGSZ = 2048, 25 NMSG = 100, /* message backlog to retain */ 26 }; 27 28 struct aoe_chardev { 29 ulong minor; 30 char name[32]; 31 }; 32 33 enum { EMFL_VALID = 1 }; 34 35 struct ErrMsg { 36 short flags; 37 short len; 38 char *msg; 39 }; 40 41 static DEFINE_MUTEX(aoechr_mutex); 42 static struct ErrMsg emsgs[NMSG]; 43 static int emsgs_head_idx, emsgs_tail_idx; 44 static struct completion emsgs_comp; 45 static spinlock_t emsgs_lock; 46 static int nblocked_emsgs_readers; 47 static struct class *aoe_class; 48 static struct aoe_chardev chardevs[] = { 49 { MINOR_ERR, "err" }, 50 { MINOR_DISCOVER, "discover" }, 51 { MINOR_INTERFACES, "interfaces" }, 52 { MINOR_REVALIDATE, "revalidate" }, 53 { MINOR_FLUSH, "flush" }, 54 }; 55 56 static int 57 discover(void) 58 { 59 aoecmd_cfg(0xffff, 0xff); 60 return 0; 61 } 62 63 static int 64 interfaces(const char __user *str, size_t size) 65 { 66 if (set_aoe_iflist(str, size)) { 67 printk(KERN_ERR 68 "aoe: could not set interface list: too many interfaces\n"); 69 return -EINVAL; 70 } 71 return 0; 72 } 73 74 static int 75 revalidate(const char __user *str, size_t size) 76 { 77 int major, minor, n; 78 ulong flags; 79 struct aoedev *d; 80 struct sk_buff *skb; 81 char buf[16]; 82 83 if (size >= sizeof buf) 84 return -EINVAL; 85 buf[sizeof buf - 1] = '\0'; 86 if (copy_from_user(buf, str, size)) 87 return -EFAULT; 88 89 n = sscanf(buf, "e%d.%d", &major, &minor); 90 if (n != 2) { 91 pr_err("aoe: invalid device specification %s\n", buf); 92 return -EINVAL; 93 } 94 d = aoedev_by_aoeaddr(major, minor, 0); 95 if (!d) 96 return -EINVAL; 97 spin_lock_irqsave(&d->lock, flags); 98 aoecmd_cleanslate(d); 99 aoecmd_cfg(major, minor); 100 loop: 101 skb = aoecmd_ata_id(d); 102 spin_unlock_irqrestore(&d->lock, flags); 103 /* try again if we are able to sleep a bit, 104 * otherwise give up this revalidation 105 */ 106 if (!skb && !msleep_interruptible(250)) { 107 spin_lock_irqsave(&d->lock, flags); 108 goto loop; 109 } 110 aoedev_put(d); 111 if (skb) { 112 struct sk_buff_head queue; 113 __skb_queue_head_init(&queue); 114 __skb_queue_tail(&queue, skb); 115 aoenet_xmit(&queue); 116 } 117 return 0; 118 } 119 120 void 121 aoechr_error(char *msg) 122 { 123 struct ErrMsg *em; 124 char *mp; 125 ulong flags, n; 126 127 n = strlen(msg); 128 129 spin_lock_irqsave(&emsgs_lock, flags); 130 131 em = emsgs + emsgs_tail_idx; 132 if ((em->flags & EMFL_VALID)) { 133 bail: spin_unlock_irqrestore(&emsgs_lock, flags); 134 return; 135 } 136 137 mp = kmalloc(n, GFP_ATOMIC); 138 if (mp == NULL) { 139 printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n); 140 goto bail; 141 } 142 143 memcpy(mp, msg, n); 144 em->msg = mp; 145 em->flags |= EMFL_VALID; 146 em->len = n; 147 148 emsgs_tail_idx++; 149 emsgs_tail_idx %= ARRAY_SIZE(emsgs); 150 151 spin_unlock_irqrestore(&emsgs_lock, flags); 152 153 if (nblocked_emsgs_readers) 154 complete(&emsgs_comp); 155 } 156 157 static ssize_t 158 aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp) 159 { 160 int ret = -EINVAL; 161 162 switch ((unsigned long) filp->private_data) { 163 default: 164 printk(KERN_INFO "aoe: can't write to that file.\n"); 165 break; 166 case MINOR_DISCOVER: 167 ret = discover(); 168 break; 169 case MINOR_INTERFACES: 170 ret = interfaces(buf, cnt); 171 break; 172 case MINOR_REVALIDATE: 173 ret = revalidate(buf, cnt); 174 break; 175 case MINOR_FLUSH: 176 ret = aoedev_flush(buf, cnt); 177 break; 178 } 179 if (ret == 0) 180 ret = cnt; 181 return ret; 182 } 183 184 static int 185 aoechr_open(struct inode *inode, struct file *filp) 186 { 187 int n, i; 188 189 mutex_lock(&aoechr_mutex); 190 n = iminor(inode); 191 filp->private_data = (void *) (unsigned long) n; 192 193 for (i = 0; i < ARRAY_SIZE(chardevs); ++i) 194 if (chardevs[i].minor == n) { 195 mutex_unlock(&aoechr_mutex); 196 return 0; 197 } 198 mutex_unlock(&aoechr_mutex); 199 return -EINVAL; 200 } 201 202 static int 203 aoechr_rel(struct inode *inode, struct file *filp) 204 { 205 return 0; 206 } 207 208 static ssize_t 209 aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off) 210 { 211 unsigned long n; 212 char *mp; 213 struct ErrMsg *em; 214 ssize_t len; 215 ulong flags; 216 217 n = (unsigned long) filp->private_data; 218 if (n != MINOR_ERR) 219 return -EFAULT; 220 221 spin_lock_irqsave(&emsgs_lock, flags); 222 223 for (;;) { 224 em = emsgs + emsgs_head_idx; 225 if ((em->flags & EMFL_VALID) != 0) 226 break; 227 if (filp->f_flags & O_NDELAY) { 228 spin_unlock_irqrestore(&emsgs_lock, flags); 229 return -EAGAIN; 230 } 231 nblocked_emsgs_readers++; 232 233 spin_unlock_irqrestore(&emsgs_lock, flags); 234 235 n = wait_for_completion_interruptible(&emsgs_comp); 236 237 spin_lock_irqsave(&emsgs_lock, flags); 238 239 nblocked_emsgs_readers--; 240 241 if (n) { 242 spin_unlock_irqrestore(&emsgs_lock, flags); 243 return -ERESTARTSYS; 244 } 245 } 246 if (em->len > cnt) { 247 spin_unlock_irqrestore(&emsgs_lock, flags); 248 return -EAGAIN; 249 } 250 mp = em->msg; 251 len = em->len; 252 em->msg = NULL; 253 em->flags &= ~EMFL_VALID; 254 255 emsgs_head_idx++; 256 emsgs_head_idx %= ARRAY_SIZE(emsgs); 257 258 spin_unlock_irqrestore(&emsgs_lock, flags); 259 260 n = copy_to_user(buf, mp, len); 261 kfree(mp); 262 return n == 0 ? len : -EFAULT; 263 } 264 265 static const struct file_operations aoe_fops = { 266 .write = aoechr_write, 267 .read = aoechr_read, 268 .open = aoechr_open, 269 .release = aoechr_rel, 270 .owner = THIS_MODULE, 271 .llseek = noop_llseek, 272 }; 273 274 static char *aoe_devnode(struct device *dev, umode_t *mode) 275 { 276 return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); 277 } 278 279 int __init 280 aoechr_init(void) 281 { 282 int n, i; 283 284 n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); 285 if (n < 0) { 286 printk(KERN_ERR "aoe: can't register char device\n"); 287 return n; 288 } 289 init_completion(&emsgs_comp); 290 spin_lock_init(&emsgs_lock); 291 aoe_class = class_create(THIS_MODULE, "aoe"); 292 if (IS_ERR(aoe_class)) { 293 unregister_chrdev(AOE_MAJOR, "aoechr"); 294 return PTR_ERR(aoe_class); 295 } 296 aoe_class->devnode = aoe_devnode; 297 298 for (i = 0; i < ARRAY_SIZE(chardevs); ++i) 299 device_create(aoe_class, NULL, 300 MKDEV(AOE_MAJOR, chardevs[i].minor), NULL, 301 chardevs[i].name); 302 303 return 0; 304 } 305 306 void 307 aoechr_exit(void) 308 { 309 int i; 310 311 for (i = 0; i < ARRAY_SIZE(chardevs); ++i) 312 device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor)); 313 class_destroy(aoe_class); 314 unregister_chrdev(AOE_MAJOR, "aoechr"); 315 } 316 317