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