diff options
-rw-r--r-- | drivers/block/aoe/aoe.h | 57 | ||||
-rw-r--r-- | drivers/block/aoe/aoeblk.c | 62 | ||||
-rw-r--r-- | drivers/block/aoe/aoechr.c | 17 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 675 | ||||
-rw-r--r-- | drivers/block/aoe/aoedev.c | 168 | ||||
-rw-r--r-- | drivers/block/aoe/aoenet.c | 9 |
6 files changed, 653 insertions, 335 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 4d0543a145df..87df18bf4dea 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -76,10 +76,8 @@ enum { | |||
76 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ | 76 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ |
77 | DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */ | 77 | DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */ |
78 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ | 78 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ |
79 | DEVFL_PAUSE = (1<<5), | 79 | DEVFL_KICKME = (1<<5), /* slow polling network card catch */ |
80 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ | 80 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ |
81 | DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */ | ||
82 | DEVFL_KICKME = (1<<8), | ||
83 | 81 | ||
84 | BUFFL_FAIL = 1, | 82 | BUFFL_FAIL = 1, |
85 | }; | 83 | }; |
@@ -88,17 +86,24 @@ enum { | |||
88 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ | 86 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ |
89 | NPERSHELF = 16, /* number of slots per shelf address */ | 87 | NPERSHELF = 16, /* number of slots per shelf address */ |
90 | FREETAG = -1, | 88 | FREETAG = -1, |
91 | MIN_BUFS = 8, | 89 | MIN_BUFS = 16, |
90 | NTARGETS = 8, | ||
91 | NAOEIFS = 8, | ||
92 | |||
93 | TIMERTICK = HZ / 10, | ||
94 | MINTIMER = HZ >> 2, | ||
95 | MAXTIMER = HZ << 1, | ||
96 | HELPWAIT = 20, | ||
92 | }; | 97 | }; |
93 | 98 | ||
94 | struct buf { | 99 | struct buf { |
95 | struct list_head bufs; | 100 | struct list_head bufs; |
96 | ulong start_time; /* for disk stats */ | 101 | ulong stime; /* for disk stats */ |
97 | ulong flags; | 102 | ulong flags; |
98 | ulong nframesout; | 103 | ulong nframesout; |
99 | char *bufaddr; | ||
100 | ulong resid; | 104 | ulong resid; |
101 | ulong bv_resid; | 105 | ulong bv_resid; |
106 | ulong bv_off; | ||
102 | sector_t sector; | 107 | sector_t sector; |
103 | struct bio *bio; | 108 | struct bio *bio; |
104 | struct bio_vec *bv; | 109 | struct bio_vec *bv; |
@@ -114,19 +119,37 @@ struct frame { | |||
114 | struct sk_buff *skb; | 119 | struct sk_buff *skb; |
115 | }; | 120 | }; |
116 | 121 | ||
122 | struct aoeif { | ||
123 | struct net_device *nd; | ||
124 | unsigned char lost; | ||
125 | unsigned char lostjumbo; | ||
126 | ushort maxbcnt; | ||
127 | }; | ||
128 | |||
129 | struct aoetgt { | ||
130 | unsigned char addr[6]; | ||
131 | ushort nframes; | ||
132 | struct frame *frames; | ||
133 | struct aoeif ifs[NAOEIFS]; | ||
134 | struct aoeif *ifp; /* current aoeif in use */ | ||
135 | ushort nout; | ||
136 | ushort maxout; | ||
137 | u16 lasttag; /* last tag sent */ | ||
138 | u16 useme; | ||
139 | ulong lastwadj; /* last window adjustment */ | ||
140 | int wpkts, rpkts; | ||
141 | }; | ||
142 | |||
117 | struct aoedev { | 143 | struct aoedev { |
118 | struct aoedev *next; | 144 | struct aoedev *next; |
119 | unsigned char addr[6]; /* remote mac addr */ | ||
120 | ushort flags; | ||
121 | ulong sysminor; | 145 | ulong sysminor; |
122 | ulong aoemajor; | 146 | ulong aoemajor; |
123 | ulong aoeminor; | 147 | u16 aoeminor; |
148 | u16 flags; | ||
124 | u16 nopen; /* (bd_openers isn't available without sleeping) */ | 149 | u16 nopen; /* (bd_openers isn't available without sleeping) */ |
125 | u16 lasttag; /* last tag sent */ | ||
126 | u16 rttavg; /* round trip average of requests/responses */ | 150 | u16 rttavg; /* round trip average of requests/responses */ |
127 | u16 mintimer; | 151 | u16 mintimer; |
128 | u16 fw_ver; /* version of blade's firmware */ | 152 | u16 fw_ver; /* version of blade's firmware */ |
129 | u16 maxbcnt; | ||
130 | struct work_struct work;/* disk create work struct */ | 153 | struct work_struct work;/* disk create work struct */ |
131 | struct gendisk *gd; | 154 | struct gendisk *gd; |
132 | struct request_queue blkq; | 155 | struct request_queue blkq; |
@@ -134,15 +157,14 @@ struct aoedev { | |||
134 | sector_t ssize; | 157 | sector_t ssize; |
135 | struct timer_list timer; | 158 | struct timer_list timer; |
136 | spinlock_t lock; | 159 | spinlock_t lock; |
137 | struct net_device *ifp; /* interface ed is attached to */ | ||
138 | struct sk_buff *sendq_hd; /* packets needing to be sent, list head */ | 160 | struct sk_buff *sendq_hd; /* packets needing to be sent, list head */ |
139 | struct sk_buff *sendq_tl; | 161 | struct sk_buff *sendq_tl; |
140 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ | 162 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ |
141 | struct list_head bufq; /* queue of bios to work on */ | 163 | struct list_head bufq; /* queue of bios to work on */ |
142 | struct buf *inprocess; /* the one we're currently working on */ | 164 | struct buf *inprocess; /* the one we're currently working on */ |
143 | ushort lostjumbo; | 165 | struct aoetgt *targets[NTARGETS]; |
144 | ushort nframes; /* number of frames below */ | 166 | struct aoetgt **tgt; /* target in use when working */ |
145 | struct frame *frames; | 167 | struct aoetgt **htgt; /* target needing rexmit assistance */ |
146 | }; | 168 | }; |
147 | 169 | ||
148 | 170 | ||
@@ -160,12 +182,13 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | |||
160 | void aoecmd_ata_rsp(struct sk_buff *); | 182 | void aoecmd_ata_rsp(struct sk_buff *); |
161 | void aoecmd_cfg_rsp(struct sk_buff *); | 183 | void aoecmd_cfg_rsp(struct sk_buff *); |
162 | void aoecmd_sleepwork(struct work_struct *); | 184 | void aoecmd_sleepwork(struct work_struct *); |
163 | struct sk_buff *new_skb(ulong); | 185 | void aoecmd_cleanslate(struct aoedev *); |
186 | struct sk_buff *aoecmd_ata_id(struct aoedev *); | ||
164 | 187 | ||
165 | int aoedev_init(void); | 188 | int aoedev_init(void); |
166 | void aoedev_exit(void); | 189 | void aoedev_exit(void); |
167 | struct aoedev *aoedev_by_aoeaddr(int maj, int min); | 190 | struct aoedev *aoedev_by_aoeaddr(int maj, int min); |
168 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt); | 191 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); |
169 | void aoedev_downdev(struct aoedev *d); | 192 | void aoedev_downdev(struct aoedev *d); |
170 | int aoedev_isbusy(struct aoedev *d); | 193 | int aoedev_isbusy(struct aoedev *d); |
171 | 194 | ||
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 826d12381e21..c2649c954278 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -24,7 +24,7 @@ static ssize_t aoedisk_show_state(struct device *dev, | |||
24 | return snprintf(page, PAGE_SIZE, | 24 | return snprintf(page, PAGE_SIZE, |
25 | "%s%s\n", | 25 | "%s%s\n", |
26 | (d->flags & DEVFL_UP) ? "up" : "down", | 26 | (d->flags & DEVFL_UP) ? "up" : "down", |
27 | (d->flags & DEVFL_PAUSE) ? ",paused" : | 27 | (d->flags & DEVFL_KICKME) ? ",kickme" : |
28 | (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); | 28 | (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); |
29 | /* I'd rather see nopen exported so we can ditch closewait */ | 29 | /* I'd rather see nopen exported so we can ditch closewait */ |
30 | } | 30 | } |
@@ -33,17 +33,49 @@ static ssize_t aoedisk_show_mac(struct device *dev, | |||
33 | { | 33 | { |
34 | struct gendisk *disk = dev_to_disk(dev); | 34 | struct gendisk *disk = dev_to_disk(dev); |
35 | struct aoedev *d = disk->private_data; | 35 | struct aoedev *d = disk->private_data; |
36 | struct aoetgt *t = d->targets[0]; | ||
36 | 37 | ||
38 | if (t == NULL) | ||
39 | return snprintf(page, PAGE_SIZE, "none\n"); | ||
37 | return snprintf(page, PAGE_SIZE, "%012llx\n", | 40 | return snprintf(page, PAGE_SIZE, "%012llx\n", |
38 | (unsigned long long)mac_addr(d->addr)); | 41 | (unsigned long long)mac_addr(t->addr)); |
39 | } | 42 | } |
40 | static ssize_t aoedisk_show_netif(struct device *dev, | 43 | static ssize_t aoedisk_show_netif(struct device *dev, |
41 | struct device_attribute *attr, char *page) | 44 | struct device_attribute *attr, char *page) |
42 | { | 45 | { |
43 | struct gendisk *disk = dev_to_disk(dev); | 46 | struct gendisk *disk = dev_to_disk(dev); |
44 | struct aoedev *d = disk->private_data; | 47 | struct aoedev *d = disk->private_data; |
48 | struct net_device *nds[8], **nd, **nnd, **ne; | ||
49 | struct aoetgt **t, **te; | ||
50 | struct aoeif *ifp, *e; | ||
51 | char *p; | ||
52 | |||
53 | memset(nds, 0, sizeof nds); | ||
54 | nd = nds; | ||
55 | ne = nd + ARRAY_SIZE(nds); | ||
56 | t = d->targets; | ||
57 | te = t + NTARGETS; | ||
58 | for (; t < te && *t; t++) { | ||
59 | ifp = (*t)->ifs; | ||
60 | e = ifp + NAOEIFS; | ||
61 | for (; ifp < e && ifp->nd; ifp++) { | ||
62 | for (nnd = nds; nnd < nd; nnd++) | ||
63 | if (*nnd == ifp->nd) | ||
64 | break; | ||
65 | if (nnd == nd && nd != ne) | ||
66 | *nd++ = ifp->nd; | ||
67 | } | ||
68 | } | ||
45 | 69 | ||
46 | return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name); | 70 | ne = nd; |
71 | nd = nds; | ||
72 | if (*nd == NULL) | ||
73 | return snprintf(page, PAGE_SIZE, "none\n"); | ||
74 | for (p = page; nd < ne; nd++) | ||
75 | p += snprintf(p, PAGE_SIZE - (p-page), "%s%s", | ||
76 | p == page ? "" : ",", (*nd)->name); | ||
77 | p += snprintf(p, PAGE_SIZE - (p-page), "\n"); | ||
78 | return p-page; | ||
47 | } | 79 | } |
48 | /* firmware version */ | 80 | /* firmware version */ |
49 | static ssize_t aoedisk_show_fwver(struct device *dev, | 81 | static ssize_t aoedisk_show_fwver(struct device *dev, |
@@ -134,7 +166,23 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) | |||
134 | 166 | ||
135 | blk_queue_bounce(q, &bio); | 167 | blk_queue_bounce(q, &bio); |
136 | 168 | ||
169 | if (bio == NULL) { | ||
170 | printk(KERN_ERR "aoe: bio is NULL\n"); | ||
171 | BUG(); | ||
172 | return 0; | ||
173 | } | ||
137 | d = bio->bi_bdev->bd_disk->private_data; | 174 | d = bio->bi_bdev->bd_disk->private_data; |
175 | if (d == NULL) { | ||
176 | printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n"); | ||
177 | BUG(); | ||
178 | bio_endio(bio, -ENXIO); | ||
179 | return 0; | ||
180 | } else if (bio->bi_io_vec == NULL) { | ||
181 | printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); | ||
182 | BUG(); | ||
183 | bio_endio(bio, -ENXIO); | ||
184 | return 0; | ||
185 | } | ||
138 | buf = mempool_alloc(d->bufpool, GFP_NOIO); | 186 | buf = mempool_alloc(d->bufpool, GFP_NOIO); |
139 | if (buf == NULL) { | 187 | if (buf == NULL) { |
140 | printk(KERN_INFO "aoe: buf allocation failure\n"); | 188 | printk(KERN_INFO "aoe: buf allocation failure\n"); |
@@ -143,14 +191,14 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) | |||
143 | } | 191 | } |
144 | memset(buf, 0, sizeof(*buf)); | 192 | memset(buf, 0, sizeof(*buf)); |
145 | INIT_LIST_HEAD(&buf->bufs); | 193 | INIT_LIST_HEAD(&buf->bufs); |
146 | buf->start_time = jiffies; | 194 | buf->stime = jiffies; |
147 | buf->bio = bio; | 195 | buf->bio = bio; |
148 | buf->resid = bio->bi_size; | 196 | buf->resid = bio->bi_size; |
149 | buf->sector = bio->bi_sector; | 197 | buf->sector = bio->bi_sector; |
150 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; | 198 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; |
151 | WARN_ON(buf->bv->bv_len == 0); | ||
152 | buf->bv_resid = buf->bv->bv_len; | 199 | buf->bv_resid = buf->bv->bv_len; |
153 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 200 | WARN_ON(buf->bv_resid == 0); |
201 | buf->bv_off = buf->bv->bv_offset; | ||
154 | 202 | ||
155 | spin_lock_irqsave(&d->lock, flags); | 203 | spin_lock_irqsave(&d->lock, flags); |
156 | 204 | ||
@@ -229,7 +277,7 @@ aoeblk_gdalloc(void *vp) | |||
229 | gd->fops = &aoe_bdops; | 277 | gd->fops = &aoe_bdops; |
230 | gd->private_data = d; | 278 | gd->private_data = d; |
231 | gd->capacity = d->ssize; | 279 | gd->capacity = d->ssize; |
232 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%ld", | 280 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", |
233 | d->aoemajor, d->aoeminor); | 281 | d->aoemajor, d->aoeminor); |
234 | 282 | ||
235 | gd->queue = &d->blkq; | 283 | gd->queue = &d->blkq; |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index d5480e34cb22..03c7f4ab5624 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/hdreg.h> | 7 | #include <linux/hdreg.h> |
8 | #include <linux/blkdev.h> | 8 | #include <linux/blkdev.h> |
9 | #include <linux/delay.h> | ||
9 | #include "aoe.h" | 10 | #include "aoe.h" |
10 | 11 | ||
11 | enum { | 12 | enum { |
@@ -68,6 +69,7 @@ revalidate(const char __user *str, size_t size) | |||
68 | int major, minor, n; | 69 | int major, minor, n; |
69 | ulong flags; | 70 | ulong flags; |
70 | struct aoedev *d; | 71 | struct aoedev *d; |
72 | struct sk_buff *skb; | ||
71 | char buf[16]; | 73 | char buf[16]; |
72 | 74 | ||
73 | if (size >= sizeof buf) | 75 | if (size >= sizeof buf) |
@@ -85,13 +87,20 @@ revalidate(const char __user *str, size_t size) | |||
85 | d = aoedev_by_aoeaddr(major, minor); | 87 | d = aoedev_by_aoeaddr(major, minor); |
86 | if (!d) | 88 | if (!d) |
87 | return -EINVAL; | 89 | return -EINVAL; |
88 | |||
89 | spin_lock_irqsave(&d->lock, flags); | 90 | spin_lock_irqsave(&d->lock, flags); |
90 | d->flags &= ~DEVFL_MAXBCNT; | 91 | aoecmd_cleanslate(d); |
91 | d->flags |= DEVFL_PAUSE; | 92 | loop: |
93 | skb = aoecmd_ata_id(d); | ||
92 | spin_unlock_irqrestore(&d->lock, flags); | 94 | spin_unlock_irqrestore(&d->lock, flags); |
95 | /* try again if we are able to sleep a bit, | ||
96 | * otherwise give up this revalidation | ||
97 | */ | ||
98 | if (!skb && !msleep_interruptible(200)) { | ||
99 | spin_lock_irqsave(&d->lock, flags); | ||
100 | goto loop; | ||
101 | } | ||
102 | aoenet_xmit(skb); | ||
93 | aoecmd_cfg(major, minor); | 103 | aoecmd_cfg(major, minor); |
94 | |||
95 | return 0; | 104 | return 0; |
96 | } | 105 | } |
97 | 106 | ||
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 4d59d5057734..5e7daa1ff6f6 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -9,19 +9,16 @@ | |||
9 | #include <linux/skbuff.h> | 9 | #include <linux/skbuff.h> |
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/genhd.h> | 11 | #include <linux/genhd.h> |
12 | #include <linux/moduleparam.h> | ||
12 | #include <net/net_namespace.h> | 13 | #include <net/net_namespace.h> |
13 | #include <asm/unaligned.h> | 14 | #include <asm/unaligned.h> |
14 | #include "aoe.h" | 15 | #include "aoe.h" |
15 | 16 | ||
16 | #define TIMERTICK (HZ / 10) | ||
17 | #define MINTIMER (2 * TIMERTICK) | ||
18 | #define MAXTIMER (HZ << 1) | ||
19 | |||
20 | static int aoe_deadsecs = 60 * 3; | 17 | static int aoe_deadsecs = 60 * 3; |
21 | module_param(aoe_deadsecs, int, 0644); | 18 | module_param(aoe_deadsecs, int, 0644); |
22 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | 19 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); |
23 | 20 | ||
24 | struct sk_buff * | 21 | static struct sk_buff * |
25 | new_skb(ulong len) | 22 | new_skb(ulong len) |
26 | { | 23 | { |
27 | struct sk_buff *skb; | 24 | struct sk_buff *skb; |
@@ -43,12 +40,12 @@ new_skb(ulong len) | |||
43 | } | 40 | } |
44 | 41 | ||
45 | static struct frame * | 42 | static struct frame * |
46 | getframe(struct aoedev *d, int tag) | 43 | getframe(struct aoetgt *t, int tag) |
47 | { | 44 | { |
48 | struct frame *f, *e; | 45 | struct frame *f, *e; |
49 | 46 | ||
50 | f = d->frames; | 47 | f = t->frames; |
51 | e = f + d->nframes; | 48 | e = f + t->nframes; |
52 | for (; f<e; f++) | 49 | for (; f<e; f++) |
53 | if (f->tag == tag) | 50 | if (f->tag == tag) |
54 | return f; | 51 | return f; |
@@ -61,21 +58,21 @@ getframe(struct aoedev *d, int tag) | |||
61 | * This driver reserves tag -1 to mean "unused frame." | 58 | * This driver reserves tag -1 to mean "unused frame." |
62 | */ | 59 | */ |
63 | static int | 60 | static int |
64 | newtag(struct aoedev *d) | 61 | newtag(struct aoetgt *t) |
65 | { | 62 | { |
66 | register ulong n; | 63 | register ulong n; |
67 | 64 | ||
68 | n = jiffies & 0xffff; | 65 | n = jiffies & 0xffff; |
69 | return n |= (++d->lasttag & 0x7fff) << 16; | 66 | return n |= (++t->lasttag & 0x7fff) << 16; |
70 | } | 67 | } |
71 | 68 | ||
72 | static int | 69 | static int |
73 | aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) | 70 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) |
74 | { | 71 | { |
75 | u32 host_tag = newtag(d); | 72 | u32 host_tag = newtag(t); |
76 | 73 | ||
77 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 74 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
78 | memcpy(h->dst, d->addr, sizeof h->dst); | 75 | memcpy(h->dst, t->addr, sizeof h->dst); |
79 | h->type = __constant_cpu_to_be16(ETH_P_AOE); | 76 | h->type = __constant_cpu_to_be16(ETH_P_AOE); |
80 | h->verfl = AOE_HVER; | 77 | h->verfl = AOE_HVER; |
81 | h->major = cpu_to_be16(d->aoemajor); | 78 | h->major = cpu_to_be16(d->aoemajor); |
@@ -98,42 +95,103 @@ put_lba(struct aoe_atahdr *ah, sector_t lba) | |||
98 | } | 95 | } |
99 | 96 | ||
100 | static void | 97 | static void |
101 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 98 | ifrotate(struct aoetgt *t) |
99 | { | ||
100 | t->ifp++; | ||
101 | if (t->ifp >= &t->ifs[NAOEIFS] || t->ifp->nd == NULL) | ||
102 | t->ifp = t->ifs; | ||
103 | if (t->ifp->nd == NULL) { | ||
104 | printk(KERN_INFO "aoe: no interface to rotate to\n"); | ||
105 | BUG(); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static struct frame * | ||
110 | freeframe(struct aoedev *d) | ||
102 | { | 111 | { |
112 | struct frame *f, *e; | ||
113 | struct aoetgt **t; | ||
114 | ulong n; | ||
115 | |||
116 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ | ||
117 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); | ||
118 | return NULL; | ||
119 | } | ||
120 | t = d->targets; | ||
121 | do { | ||
122 | if (t != d->htgt | ||
123 | && (*t)->ifp->nd | ||
124 | && (*t)->nout < (*t)->maxout) { | ||
125 | n = (*t)->nframes; | ||
126 | f = (*t)->frames; | ||
127 | e = f + n; | ||
128 | for (; f < e; f++) { | ||
129 | if (f->tag != FREETAG) | ||
130 | continue; | ||
131 | if (atomic_read(&skb_shinfo(f->skb)->dataref) | ||
132 | != 1) { | ||
133 | n--; | ||
134 | continue; | ||
135 | } | ||
136 | skb_shinfo(f->skb)->nr_frags = 0; | ||
137 | f->skb->data_len = 0; | ||
138 | skb_trim(f->skb, 0); | ||
139 | d->tgt = t; | ||
140 | ifrotate(*t); | ||
141 | return f; | ||
142 | } | ||
143 | if (n == 0) /* slow polling network card */ | ||
144 | d->flags |= DEVFL_KICKME; | ||
145 | } | ||
146 | t++; | ||
147 | } while (t < &d->targets[NTARGETS] && *t); | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | static int | ||
152 | aoecmd_ata_rw(struct aoedev *d) | ||
153 | { | ||
154 | struct frame *f; | ||
103 | struct aoe_hdr *h; | 155 | struct aoe_hdr *h; |
104 | struct aoe_atahdr *ah; | 156 | struct aoe_atahdr *ah; |
105 | struct buf *buf; | 157 | struct buf *buf; |
158 | struct bio_vec *bv; | ||
159 | struct aoetgt *t; | ||
106 | struct sk_buff *skb; | 160 | struct sk_buff *skb; |
107 | ulong bcnt; | 161 | ulong bcnt; |
108 | register sector_t sector; | ||
109 | char writebit, extbit; | 162 | char writebit, extbit; |
110 | 163 | ||
111 | writebit = 0x10; | 164 | writebit = 0x10; |
112 | extbit = 0x4; | 165 | extbit = 0x4; |
113 | 166 | ||
167 | f = freeframe(d); | ||
168 | if (f == NULL) | ||
169 | return 0; | ||
170 | t = *d->tgt; | ||
114 | buf = d->inprocess; | 171 | buf = d->inprocess; |
115 | 172 | bv = buf->bv; | |
116 | sector = buf->sector; | 173 | bcnt = t->ifp->maxbcnt; |
117 | bcnt = buf->bv_resid; | 174 | if (bcnt == 0) |
118 | if (bcnt > d->maxbcnt) | 175 | bcnt = DEFAULTBCNT; |
119 | bcnt = d->maxbcnt; | 176 | if (bcnt > buf->bv_resid) |
120 | 177 | bcnt = buf->bv_resid; | |
121 | /* initialize the headers & frame */ | 178 | /* initialize the headers & frame */ |
122 | skb = f->skb; | 179 | skb = f->skb; |
123 | h = (struct aoe_hdr *) skb_mac_header(skb); | 180 | h = (struct aoe_hdr *) skb_mac_header(skb); |
124 | ah = (struct aoe_atahdr *) (h+1); | 181 | ah = (struct aoe_atahdr *) (h+1); |
125 | skb_put(skb, sizeof *h + sizeof *ah); | 182 | skb_put(skb, sizeof *h + sizeof *ah); |
126 | memset(h, 0, skb->len); | 183 | memset(h, 0, skb->len); |
127 | f->tag = aoehdr_atainit(d, h); | 184 | f->tag = aoehdr_atainit(d, t, h); |
185 | t->nout++; | ||
128 | f->waited = 0; | 186 | f->waited = 0; |
129 | f->buf = buf; | 187 | f->buf = buf; |
130 | f->bufaddr = buf->bufaddr; | 188 | f->bufaddr = page_address(bv->bv_page) + buf->bv_off; |
131 | f->bcnt = bcnt; | 189 | f->bcnt = bcnt; |
132 | f->lba = sector; | 190 | f->lba = buf->sector; |
133 | 191 | ||
134 | /* set up ata header */ | 192 | /* set up ata header */ |
135 | ah->scnt = bcnt >> 9; | 193 | ah->scnt = bcnt >> 9; |
136 | put_lba(ah, sector); | 194 | put_lba(ah, buf->sector); |
137 | if (d->flags & DEVFL_EXT) { | 195 | if (d->flags & DEVFL_EXT) { |
138 | ah->aflags |= AOEAFL_EXT; | 196 | ah->aflags |= AOEAFL_EXT; |
139 | } else { | 197 | } else { |
@@ -141,14 +199,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
141 | ah->lba3 &= 0x0f; | 199 | ah->lba3 &= 0x0f; |
142 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ | 200 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ |
143 | } | 201 | } |
144 | |||
145 | if (bio_data_dir(buf->bio) == WRITE) { | 202 | if (bio_data_dir(buf->bio) == WRITE) { |
146 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | 203 | skb_fill_page_desc(skb, 0, bv->bv_page, buf->bv_off, bcnt); |
147 | offset_in_page(f->bufaddr), bcnt); | ||
148 | ah->aflags |= AOEAFL_WRITE; | 204 | ah->aflags |= AOEAFL_WRITE; |
149 | skb->len += bcnt; | 205 | skb->len += bcnt; |
150 | skb->data_len = bcnt; | 206 | skb->data_len = bcnt; |
207 | t->wpkts++; | ||
151 | } else { | 208 | } else { |
209 | t->rpkts++; | ||
152 | writebit = 0; | 210 | writebit = 0; |
153 | } | 211 | } |
154 | 212 | ||
@@ -156,29 +214,29 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
156 | 214 | ||
157 | /* mark all tracking fields and load out */ | 215 | /* mark all tracking fields and load out */ |
158 | buf->nframesout += 1; | 216 | buf->nframesout += 1; |
159 | buf->bufaddr += bcnt; | 217 | buf->bv_off += bcnt; |
160 | buf->bv_resid -= bcnt; | 218 | buf->bv_resid -= bcnt; |
161 | /* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ | ||
162 | buf->resid -= bcnt; | 219 | buf->resid -= bcnt; |
163 | buf->sector += bcnt >> 9; | 220 | buf->sector += bcnt >> 9; |
164 | if (buf->resid == 0) { | 221 | if (buf->resid == 0) { |
165 | d->inprocess = NULL; | 222 | d->inprocess = NULL; |
166 | } else if (buf->bv_resid == 0) { | 223 | } else if (buf->bv_resid == 0) { |
167 | buf->bv++; | 224 | buf->bv = ++bv; |
168 | WARN_ON(buf->bv->bv_len == 0); | 225 | buf->bv_resid = bv->bv_len; |
169 | buf->bv_resid = buf->bv->bv_len; | 226 | WARN_ON(buf->bv_resid == 0); |
170 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 227 | buf->bv_off = bv->bv_offset; |
171 | } | 228 | } |
172 | 229 | ||
173 | skb->dev = d->ifp; | 230 | skb->dev = t->ifp->nd; |
174 | skb = skb_clone(skb, GFP_ATOMIC); | 231 | skb = skb_clone(skb, GFP_ATOMIC); |
175 | if (skb == NULL) | 232 | if (skb) { |
176 | return; | 233 | if (d->sendq_hd) |
177 | if (d->sendq_hd) | 234 | d->sendq_tl->next = skb; |
178 | d->sendq_tl->next = skb; | 235 | else |
179 | else | 236 | d->sendq_hd = skb; |
180 | d->sendq_hd = skb; | 237 | d->sendq_tl = skb; |
181 | d->sendq_tl = skb; | 238 | } |
239 | return 1; | ||
182 | } | 240 | } |
183 | 241 | ||
184 | /* some callers cannot sleep, and they can call this function, | 242 | /* some callers cannot sleep, and they can call this function, |
@@ -232,62 +290,8 @@ cont: | |||
232 | return sl; | 290 | return sl; |
233 | } | 291 | } |
234 | 292 | ||
235 | static struct frame * | ||
236 | freeframe(struct aoedev *d) | ||
237 | { | ||
238 | struct frame *f, *e; | ||
239 | int n = 0; | ||
240 | |||
241 | f = d->frames; | ||
242 | e = f + d->nframes; | ||
243 | for (; f<e; f++) { | ||
244 | if (f->tag != FREETAG) | ||
245 | continue; | ||
246 | if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) { | ||
247 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
248 | skb_trim(f->skb, 0); | ||
249 | return f; | ||
250 | } | ||
251 | n++; | ||
252 | } | ||
253 | if (n == d->nframes) /* wait for network layer */ | ||
254 | d->flags |= DEVFL_KICKME; | ||
255 | |||
256 | return NULL; | ||
257 | } | ||
258 | |||
259 | /* enters with d->lock held */ | ||
260 | void | ||
261 | aoecmd_work(struct aoedev *d) | ||
262 | { | ||
263 | struct frame *f; | ||
264 | struct buf *buf; | ||
265 | |||
266 | if (d->flags & DEVFL_PAUSE) { | ||
267 | if (!aoedev_isbusy(d)) | ||
268 | d->sendq_hd = aoecmd_cfg_pkts(d->aoemajor, | ||
269 | d->aoeminor, &d->sendq_tl); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | loop: | ||
274 | f = freeframe(d); | ||
275 | if (f == NULL) | ||
276 | return; | ||
277 | if (d->inprocess == NULL) { | ||
278 | if (list_empty(&d->bufq)) | ||
279 | return; | ||
280 | buf = container_of(d->bufq.next, struct buf, bufs); | ||
281 | list_del(d->bufq.next); | ||
282 | /*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */ | ||
283 | d->inprocess = buf; | ||
284 | } | ||
285 | aoecmd_ata_rw(d, f); | ||
286 | goto loop; | ||
287 | } | ||
288 | |||
289 | static void | 293 | static void |
290 | rexmit(struct aoedev *d, struct frame *f) | 294 | resend(struct aoedev *d, struct aoetgt *t, struct frame *f) |
291 | { | 295 | { |
292 | struct sk_buff *skb; | 296 | struct sk_buff *skb; |
293 | struct aoe_hdr *h; | 297 | struct aoe_hdr *h; |
@@ -295,41 +299,45 @@ rexmit(struct aoedev *d, struct frame *f) | |||
295 | char buf[128]; | 299 | char buf[128]; |
296 | u32 n; | 300 | u32 n; |
297 | 301 | ||
298 | n = newtag(d); | 302 | ifrotate(t); |
303 | n = newtag(t); | ||
304 | skb = f->skb; | ||
305 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
306 | ah = (struct aoe_atahdr *) (h+1); | ||
299 | 307 | ||
300 | snprintf(buf, sizeof buf, | 308 | snprintf(buf, sizeof buf, |
301 | "%15s e%ld.%ld oldtag=%08x@%08lx newtag=%08x\n", | 309 | "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x " |
302 | "retransmit", | 310 | "s=%012llx d=%012llx nout=%d\n", |
303 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); | 311 | "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n, |
312 | mac_addr(h->src), mac_addr(h->dst), t->nout); | ||
304 | aoechr_error(buf); | 313 | aoechr_error(buf); |
305 | 314 | ||
306 | skb = f->skb; | ||
307 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
308 | ah = (struct aoe_atahdr *) (h+1); | ||
309 | f->tag = n; | 315 | f->tag = n; |
310 | h->tag = cpu_to_be32(n); | 316 | h->tag = cpu_to_be32(n); |
311 | memcpy(h->dst, d->addr, sizeof h->dst); | 317 | memcpy(h->dst, t->addr, sizeof h->dst); |
312 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 318 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
313 | 319 | ||
314 | n = DEFAULTBCNT / 512; | 320 | switch (ah->cmdstat) { |
315 | if (ah->scnt > n) { | 321 | default: |
316 | ah->scnt = n; | 322 | break; |
323 | case WIN_READ: | ||
324 | case WIN_READ_EXT: | ||
325 | case WIN_WRITE: | ||
326 | case WIN_WRITE_EXT: | ||
327 | put_lba(ah, f->lba); | ||
328 | |||
329 | n = f->bcnt; | ||
330 | if (n > DEFAULTBCNT) | ||
331 | n = DEFAULTBCNT; | ||
332 | ah->scnt = n >> 9; | ||
317 | if (ah->aflags & AOEAFL_WRITE) { | 333 | if (ah->aflags & AOEAFL_WRITE) { |
318 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | 334 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), |
319 | offset_in_page(f->bufaddr), DEFAULTBCNT); | 335 | offset_in_page(f->bufaddr), n); |
320 | skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; | 336 | skb->len = sizeof *h + sizeof *ah + n; |
321 | skb->data_len = DEFAULTBCNT; | 337 | skb->data_len = n; |
322 | } | ||
323 | if (++d->lostjumbo > (d->nframes << 1)) | ||
324 | if (d->maxbcnt != DEFAULTBCNT) { | ||
325 | printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", | ||
326 | d->aoemajor, d->aoeminor, d->ifp->name); | ||
327 | d->maxbcnt = DEFAULTBCNT; | ||
328 | d->flags |= DEVFL_MAXBCNT; | ||
329 | } | 338 | } |
330 | } | 339 | } |
331 | 340 | skb->dev = t->ifp->nd; | |
332 | skb->dev = d->ifp; | ||
333 | skb = skb_clone(skb, GFP_ATOMIC); | 341 | skb = skb_clone(skb, GFP_ATOMIC); |
334 | if (skb == NULL) | 342 | if (skb == NULL) |
335 | return; | 343 | return; |
@@ -352,10 +360,92 @@ tsince(int tag) | |||
352 | return n; | 360 | return n; |
353 | } | 361 | } |
354 | 362 | ||
363 | static struct aoeif * | ||
364 | getif(struct aoetgt *t, struct net_device *nd) | ||
365 | { | ||
366 | struct aoeif *p, *e; | ||
367 | |||
368 | p = t->ifs; | ||
369 | e = p + NAOEIFS; | ||
370 | for (; p < e; p++) | ||
371 | if (p->nd == nd) | ||
372 | return p; | ||
373 | return NULL; | ||
374 | } | ||
375 | |||
376 | static struct aoeif * | ||
377 | addif(struct aoetgt *t, struct net_device *nd) | ||
378 | { | ||
379 | struct aoeif *p; | ||
380 | |||
381 | p = getif(t, NULL); | ||
382 | if (!p) | ||
383 | return NULL; | ||
384 | p->nd = nd; | ||
385 | p->maxbcnt = DEFAULTBCNT; | ||
386 | p->lost = 0; | ||
387 | p->lostjumbo = 0; | ||
388 | return p; | ||
389 | } | ||
390 | |||
391 | static void | ||
392 | ejectif(struct aoetgt *t, struct aoeif *ifp) | ||
393 | { | ||
394 | struct aoeif *e; | ||
395 | ulong n; | ||
396 | |||
397 | e = t->ifs + NAOEIFS - 1; | ||
398 | n = (e - ifp) * sizeof *ifp; | ||
399 | memmove(ifp, ifp+1, n); | ||
400 | e->nd = NULL; | ||
401 | } | ||
402 | |||
403 | static int | ||
404 | sthtith(struct aoedev *d) | ||
405 | { | ||
406 | struct frame *f, *e, *nf; | ||
407 | struct sk_buff *skb; | ||
408 | struct aoetgt *ht = *d->htgt; | ||
409 | |||
410 | f = ht->frames; | ||
411 | e = f + ht->nframes; | ||
412 | for (; f < e; f++) { | ||
413 | if (f->tag == FREETAG) | ||
414 | continue; | ||
415 | nf = freeframe(d); | ||
416 | if (!nf) | ||
417 | return 0; | ||
418 | skb = nf->skb; | ||
419 | *nf = *f; | ||
420 | f->skb = skb; | ||
421 | f->tag = FREETAG; | ||
422 | nf->waited = 0; | ||
423 | ht->nout--; | ||
424 | (*d->tgt)->nout++; | ||
425 | resend(d, *d->tgt, nf); | ||
426 | } | ||
427 | /* he's clean, he's useless. take away his interfaces */ | ||
428 | memset(ht->ifs, 0, sizeof ht->ifs); | ||
429 | d->htgt = NULL; | ||
430 | return 1; | ||
431 | } | ||
432 | |||
433 | static inline unsigned char | ||
434 | ata_scnt(unsigned char *packet) { | ||
435 | struct aoe_hdr *h; | ||
436 | struct aoe_atahdr *ah; | ||
437 | |||
438 | h = (struct aoe_hdr *) packet; | ||
439 | ah = (struct aoe_atahdr *) (h+1); | ||
440 | return ah->scnt; | ||
441 | } | ||
442 | |||
355 | static void | 443 | static void |
356 | rexmit_timer(ulong vp) | 444 | rexmit_timer(ulong vp) |
357 | { | 445 | { |
358 | struct aoedev *d; | 446 | struct aoedev *d; |
447 | struct aoetgt *t, **tt, **te; | ||
448 | struct aoeif *ifp; | ||
359 | struct frame *f, *e; | 449 | struct frame *f, *e; |
360 | struct sk_buff *sl; | 450 | struct sk_buff *sl; |
361 | register long timeout; | 451 | register long timeout; |
@@ -374,31 +464,79 @@ rexmit_timer(ulong vp) | |||
374 | spin_unlock_irqrestore(&d->lock, flags); | 464 | spin_unlock_irqrestore(&d->lock, flags); |
375 | return; | 465 | return; |
376 | } | 466 | } |
377 | f = d->frames; | 467 | tt = d->targets; |
378 | e = f + d->nframes; | 468 | te = tt + NTARGETS; |
379 | for (; f<e; f++) { | 469 | for (; tt < te && *tt; tt++) { |
380 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { | 470 | t = *tt; |
471 | f = t->frames; | ||
472 | e = f + t->nframes; | ||
473 | for (; f < e; f++) { | ||
474 | if (f->tag == FREETAG | ||
475 | || tsince(f->tag) < timeout) | ||
476 | continue; | ||
381 | n = f->waited += timeout; | 477 | n = f->waited += timeout; |
382 | n /= HZ; | 478 | n /= HZ; |
383 | if (n > aoe_deadsecs) { /* waited too long for response */ | 479 | if (n > aoe_deadsecs) { |
480 | /* waited too long. device failure. */ | ||
384 | aoedev_downdev(d); | 481 | aoedev_downdev(d); |
385 | break; | 482 | break; |
386 | } | 483 | } |
387 | rexmit(d, f); | 484 | |
485 | if (n > HELPWAIT /* see if another target can help */ | ||
486 | && (tt != d->targets || d->targets[1])) | ||
487 | d->htgt = tt; | ||
488 | |||
489 | if (t->nout == t->maxout) { | ||
490 | if (t->maxout > 1) | ||
491 | t->maxout--; | ||
492 | t->lastwadj = jiffies; | ||
493 | } | ||
494 | |||
495 | ifp = getif(t, f->skb->dev); | ||
496 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
497 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
498 | ejectif(t, ifp); | ||
499 | ifp = NULL; | ||
500 | } | ||
501 | |||
502 | if (ata_scnt(skb_mac_header(f->skb)) > DEFAULTBCNT / 512 | ||
503 | && ifp && ++ifp->lostjumbo > (t->nframes << 1) | ||
504 | && ifp->maxbcnt != DEFAULTBCNT) { | ||
505 | printk(KERN_INFO | ||
506 | "aoe: e%ld.%d: " | ||
507 | "too many lost jumbo on " | ||
508 | "%s:%012llx - " | ||
509 | "falling back to %d frames.\n", | ||
510 | d->aoemajor, d->aoeminor, | ||
511 | ifp->nd->name, mac_addr(t->addr), | ||
512 | DEFAULTBCNT); | ||
513 | ifp->maxbcnt = 0; | ||
514 | } | ||
515 | resend(d, t, f); | ||
516 | } | ||
517 | |||
518 | /* window check */ | ||
519 | if (t->nout == t->maxout | ||
520 | && t->maxout < t->nframes | ||
521 | && (jiffies - t->lastwadj)/HZ > 10) { | ||
522 | t->maxout++; | ||
523 | t->lastwadj = jiffies; | ||
388 | } | 524 | } |
389 | } | 525 | } |
390 | if (d->flags & DEVFL_KICKME) { | 526 | |
527 | if (d->sendq_hd) { | ||
528 | n = d->rttavg <<= 1; | ||
529 | if (n > MAXTIMER) | ||
530 | d->rttavg = MAXTIMER; | ||
531 | } | ||
532 | |||
533 | if (d->flags & DEVFL_KICKME || d->htgt) { | ||
391 | d->flags &= ~DEVFL_KICKME; | 534 | d->flags &= ~DEVFL_KICKME; |
392 | aoecmd_work(d); | 535 | aoecmd_work(d); |
393 | } | 536 | } |
394 | 537 | ||
395 | sl = d->sendq_hd; | 538 | sl = d->sendq_hd; |
396 | d->sendq_hd = d->sendq_tl = NULL; | 539 | d->sendq_hd = d->sendq_tl = NULL; |
397 | if (sl) { | ||
398 | n = d->rttavg <<= 1; | ||
399 | if (n > MAXTIMER) | ||
400 | d->rttavg = MAXTIMER; | ||
401 | } | ||
402 | 540 | ||
403 | d->timer.expires = jiffies + TIMERTICK; | 541 | d->timer.expires = jiffies + TIMERTICK; |
404 | add_timer(&d->timer); | 542 | add_timer(&d->timer); |
@@ -408,6 +546,25 @@ rexmit_timer(ulong vp) | |||
408 | aoenet_xmit(sl); | 546 | aoenet_xmit(sl); |
409 | } | 547 | } |
410 | 548 | ||
549 | /* enters with d->lock held */ | ||
550 | void | ||
551 | aoecmd_work(struct aoedev *d) | ||
552 | { | ||
553 | struct buf *buf; | ||
554 | loop: | ||
555 | if (d->htgt && !sthtith(d)) | ||
556 | return; | ||
557 | if (d->inprocess == NULL) { | ||
558 | if (list_empty(&d->bufq)) | ||
559 | return; | ||
560 | buf = container_of(d->bufq.next, struct buf, bufs); | ||
561 | list_del(d->bufq.next); | ||
562 | d->inprocess = buf; | ||
563 | } | ||
564 | if (aoecmd_ata_rw(d)) | ||
565 | goto loop; | ||
566 | } | ||
567 | |||
411 | /* this function performs work that has been deferred until sleeping is OK | 568 | /* this function performs work that has been deferred until sleeping is OK |
412 | */ | 569 | */ |
413 | void | 570 | void |
@@ -440,7 +597,7 @@ aoecmd_sleepwork(struct work_struct *work) | |||
440 | } | 597 | } |
441 | 598 | ||
442 | static void | 599 | static void |
443 | ataid_complete(struct aoedev *d, unsigned char *id) | 600 | ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) |
444 | { | 601 | { |
445 | u64 ssize; | 602 | u64 ssize; |
446 | u16 n; | 603 | u16 n; |
@@ -476,7 +633,7 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
476 | 633 | ||
477 | if (d->ssize != ssize) | 634 | if (d->ssize != ssize) |
478 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", | 635 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", |
479 | (unsigned long long)mac_addr(d->addr), | 636 | (unsigned long long)mac_addr(t->addr), |
480 | d->aoemajor, d->aoeminor, | 637 | d->aoemajor, d->aoeminor, |
481 | d->fw_ver, (long long)ssize); | 638 | d->fw_ver, (long long)ssize); |
482 | d->ssize = ssize; | 639 | d->ssize = ssize; |
@@ -484,15 +641,8 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
484 | if (d->gd != NULL) { | 641 | if (d->gd != NULL) { |
485 | d->gd->capacity = ssize; | 642 | d->gd->capacity = ssize; |
486 | d->flags |= DEVFL_NEWSIZE; | 643 | d->flags |= DEVFL_NEWSIZE; |
487 | } else { | 644 | } else |
488 | if (d->flags & DEVFL_GDALLOC) { | ||
489 | printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n", | ||
490 | d->aoemajor, d->aoeminor, | ||
491 | "it's already on! This shouldn't happen.\n"); | ||
492 | return; | ||
493 | } | ||
494 | d->flags |= DEVFL_GDALLOC; | 645 | d->flags |= DEVFL_GDALLOC; |
495 | } | ||
496 | schedule_work(&d->work); | 646 | schedule_work(&d->work); |
497 | } | 647 | } |
498 | 648 | ||
@@ -519,6 +669,31 @@ calc_rttavg(struct aoedev *d, int rtt) | |||
519 | d->rttavg += n >> 2; | 669 | d->rttavg += n >> 2; |
520 | } | 670 | } |
521 | 671 | ||
672 | static struct aoetgt * | ||
673 | gettgt(struct aoedev *d, char *addr) | ||
674 | { | ||
675 | struct aoetgt **t, **e; | ||
676 | |||
677 | t = d->targets; | ||
678 | e = t + NTARGETS; | ||
679 | for (; t < e && *t; t++) | ||
680 | if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) | ||
681 | return *t; | ||
682 | return NULL; | ||
683 | } | ||
684 | |||
685 | static inline void | ||
686 | diskstats(struct gendisk *disk, struct bio *bio, ulong duration) | ||
687 | { | ||
688 | unsigned long n_sect = bio->bi_size >> 9; | ||
689 | const int rw = bio_data_dir(bio); | ||
690 | |||
691 | disk_stat_inc(disk, ios[rw]); | ||
692 | disk_stat_add(disk, ticks[rw], duration); | ||
693 | disk_stat_add(disk, sectors[rw], n_sect); | ||
694 | disk_stat_add(disk, io_ticks, duration); | ||
695 | } | ||
696 | |||
522 | void | 697 | void |
523 | aoecmd_ata_rsp(struct sk_buff *skb) | 698 | aoecmd_ata_rsp(struct sk_buff *skb) |
524 | { | 699 | { |
@@ -528,6 +703,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
528 | struct frame *f; | 703 | struct frame *f; |
529 | struct buf *buf; | 704 | struct buf *buf; |
530 | struct sk_buff *sl; | 705 | struct sk_buff *sl; |
706 | struct aoetgt *t; | ||
707 | struct aoeif *ifp; | ||
531 | register long n; | 708 | register long n; |
532 | ulong flags; | 709 | ulong flags; |
533 | char ebuf[128]; | 710 | char ebuf[128]; |
@@ -547,7 +724,15 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
547 | spin_lock_irqsave(&d->lock, flags); | 724 | spin_lock_irqsave(&d->lock, flags); |
548 | 725 | ||
549 | n = be32_to_cpu(get_unaligned(&hin->tag)); | 726 | n = be32_to_cpu(get_unaligned(&hin->tag)); |
550 | f = getframe(d, n); | 727 | t = gettgt(d, hin->src); |
728 | if (t == NULL) { | ||
729 | printk(KERN_INFO "aoe: can't find target e%ld.%d:%012llx\n", | ||
730 | d->aoemajor, d->aoeminor, | ||
731 | (unsigned long long) mac_addr(hin->src)); | ||
732 | spin_unlock_irqrestore(&d->lock, flags); | ||
733 | return; | ||
734 | } | ||
735 | f = getframe(t, n); | ||
551 | if (f == NULL) { | 736 | if (f == NULL) { |
552 | calc_rttavg(d, -tsince(n)); | 737 | calc_rttavg(d, -tsince(n)); |
553 | spin_unlock_irqrestore(&d->lock, flags); | 738 | spin_unlock_irqrestore(&d->lock, flags); |
@@ -569,8 +754,6 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
569 | ahout = (struct aoe_atahdr *) (hout+1); | 754 | ahout = (struct aoe_atahdr *) (hout+1); |
570 | buf = f->buf; | 755 | buf = f->buf; |
571 | 756 | ||
572 | if (ahout->cmdstat == WIN_IDENTIFY) | ||
573 | d->flags &= ~DEVFL_PAUSE; | ||
574 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | 757 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ |
575 | printk(KERN_ERR | 758 | printk(KERN_ERR |
576 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", | 759 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", |
@@ -579,14 +762,16 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
579 | if (buf) | 762 | if (buf) |
580 | buf->flags |= BUFFL_FAIL; | 763 | buf->flags |= BUFFL_FAIL; |
581 | } else { | 764 | } else { |
765 | if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */ | ||
766 | d->htgt = NULL; | ||
582 | n = ahout->scnt << 9; | 767 | n = ahout->scnt << 9; |
583 | switch (ahout->cmdstat) { | 768 | switch (ahout->cmdstat) { |
584 | case WIN_READ: | 769 | case WIN_READ: |
585 | case WIN_READ_EXT: | 770 | case WIN_READ_EXT: |
586 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | 771 | if (skb->len - sizeof *hin - sizeof *ahin < n) { |
587 | printk(KERN_ERR | 772 | printk(KERN_ERR |
588 | "aoe: runt data size in read. skb->len=%d\n", | 773 | "aoe: %s. skb->len=%d need=%ld\n", |
589 | skb->len); | 774 | "runt data size in read", skb->len, n); |
590 | /* fail frame f? just returning will rexmit. */ | 775 | /* fail frame f? just returning will rexmit. */ |
591 | spin_unlock_irqrestore(&d->lock, flags); | 776 | spin_unlock_irqrestore(&d->lock, flags); |
592 | return; | 777 | return; |
@@ -594,32 +779,18 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
594 | memcpy(f->bufaddr, ahin+1, n); | 779 | memcpy(f->bufaddr, ahin+1, n); |
595 | case WIN_WRITE: | 780 | case WIN_WRITE: |
596 | case WIN_WRITE_EXT: | 781 | case WIN_WRITE_EXT: |
782 | ifp = getif(t, skb->dev); | ||
783 | if (ifp) { | ||
784 | ifp->lost = 0; | ||
785 | if (n > DEFAULTBCNT) | ||
786 | ifp->lostjumbo = 0; | ||
787 | } | ||
597 | if (f->bcnt -= n) { | 788 | if (f->bcnt -= n) { |
598 | skb = f->skb; | 789 | f->lba += n >> 9; |
599 | f->bufaddr += n; | 790 | f->bufaddr += n; |
600 | put_lba(ahout, f->lba += ahout->scnt); | 791 | resend(d, t, f); |
601 | n = f->bcnt; | 792 | goto xmit; |
602 | if (n > DEFAULTBCNT) | ||
603 | n = DEFAULTBCNT; | ||
604 | ahout->scnt = n >> 9; | ||
605 | if (ahout->aflags & AOEAFL_WRITE) { | ||
606 | skb_fill_page_desc(skb, 0, | ||
607 | virt_to_page(f->bufaddr), | ||
608 | offset_in_page(f->bufaddr), n); | ||
609 | skb->len = sizeof *hout + sizeof *ahout + n; | ||
610 | skb->data_len = n; | ||
611 | } | ||
612 | f->tag = newtag(d); | ||
613 | hout->tag = cpu_to_be32(f->tag); | ||
614 | skb->dev = d->ifp; | ||
615 | skb = skb_clone(skb, GFP_ATOMIC); | ||
616 | spin_unlock_irqrestore(&d->lock, flags); | ||
617 | if (skb) | ||
618 | aoenet_xmit(skb); | ||
619 | return; | ||
620 | } | 793 | } |
621 | if (n > DEFAULTBCNT) | ||
622 | d->lostjumbo = 0; | ||
623 | break; | 794 | break; |
624 | case WIN_IDENTIFY: | 795 | case WIN_IDENTIFY: |
625 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | 796 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { |
@@ -629,7 +800,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
629 | spin_unlock_irqrestore(&d->lock, flags); | 800 | spin_unlock_irqrestore(&d->lock, flags); |
630 | return; | 801 | return; |
631 | } | 802 | } |
632 | ataid_complete(d, (char *) (ahin+1)); | 803 | ataid_complete(d, t, (char *) (ahin+1)); |
633 | break; | 804 | break; |
634 | default: | 805 | default: |
635 | printk(KERN_INFO | 806 | printk(KERN_INFO |
@@ -640,28 +811,19 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
640 | } | 811 | } |
641 | } | 812 | } |
642 | 813 | ||
643 | if (buf) { | 814 | if (buf && --buf->nframesout == 0 && buf->resid == 0) { |
644 | buf->nframesout -= 1; | 815 | diskstats(d->gd, buf->bio, jiffies - buf->stime); |
645 | if (buf->nframesout == 0 && buf->resid == 0) { | 816 | n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; |
646 | unsigned long duration = jiffies - buf->start_time; | 817 | bio_endio(buf->bio, n); |
647 | unsigned long n_sect = buf->bio->bi_size >> 9; | 818 | mempool_free(buf, d->bufpool); |
648 | struct gendisk *disk = d->gd; | ||
649 | const int rw = bio_data_dir(buf->bio); | ||
650 | |||
651 | disk_stat_inc(disk, ios[rw]); | ||
652 | disk_stat_add(disk, ticks[rw], duration); | ||
653 | disk_stat_add(disk, sectors[rw], n_sect); | ||
654 | disk_stat_add(disk, io_ticks, duration); | ||
655 | n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; | ||
656 | bio_endio(buf->bio, n); | ||
657 | mempool_free(buf, d->bufpool); | ||
658 | } | ||
659 | } | 819 | } |
660 | 820 | ||
661 | f->buf = NULL; | 821 | f->buf = NULL; |
662 | f->tag = FREETAG; | 822 | f->tag = FREETAG; |
823 | t->nout--; | ||
663 | 824 | ||
664 | aoecmd_work(d); | 825 | aoecmd_work(d); |
826 | xmit: | ||
665 | sl = d->sendq_hd; | 827 | sl = d->sendq_hd; |
666 | d->sendq_hd = d->sendq_tl = NULL; | 828 | d->sendq_hd = d->sendq_tl = NULL; |
667 | 829 | ||
@@ -679,23 +841,20 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) | |||
679 | aoenet_xmit(sl); | 841 | aoenet_xmit(sl); |
680 | } | 842 | } |
681 | 843 | ||
682 | /* | 844 | struct sk_buff * |
683 | * Since we only call this in one place (and it only prepares one frame) | ||
684 | * we just return the skb. Usually we'd chain it up to the aoedev sendq. | ||
685 | */ | ||
686 | static struct sk_buff * | ||
687 | aoecmd_ata_id(struct aoedev *d) | 845 | aoecmd_ata_id(struct aoedev *d) |
688 | { | 846 | { |
689 | struct aoe_hdr *h; | 847 | struct aoe_hdr *h; |
690 | struct aoe_atahdr *ah; | 848 | struct aoe_atahdr *ah; |
691 | struct frame *f; | 849 | struct frame *f; |
692 | struct sk_buff *skb; | 850 | struct sk_buff *skb; |
851 | struct aoetgt *t; | ||
693 | 852 | ||
694 | f = freeframe(d); | 853 | f = freeframe(d); |
695 | if (f == NULL) { | 854 | if (f == NULL) |
696 | printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); | ||
697 | return NULL; | 855 | return NULL; |
698 | } | 856 | |
857 | t = *d->tgt; | ||
699 | 858 | ||
700 | /* initialize the headers & frame */ | 859 | /* initialize the headers & frame */ |
701 | skb = f->skb; | 860 | skb = f->skb; |
@@ -703,7 +862,8 @@ aoecmd_ata_id(struct aoedev *d) | |||
703 | ah = (struct aoe_atahdr *) (h+1); | 862 | ah = (struct aoe_atahdr *) (h+1); |
704 | skb_put(skb, sizeof *h + sizeof *ah); | 863 | skb_put(skb, sizeof *h + sizeof *ah); |
705 | memset(h, 0, skb->len); | 864 | memset(h, 0, skb->len); |
706 | f->tag = aoehdr_atainit(d, h); | 865 | f->tag = aoehdr_atainit(d, t, h); |
866 | t->nout++; | ||
707 | f->waited = 0; | 867 | f->waited = 0; |
708 | 868 | ||
709 | /* set up ata header */ | 869 | /* set up ata header */ |
@@ -711,7 +871,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
711 | ah->cmdstat = WIN_IDENTIFY; | 871 | ah->cmdstat = WIN_IDENTIFY; |
712 | ah->lba3 = 0xa0; | 872 | ah->lba3 = 0xa0; |
713 | 873 | ||
714 | skb->dev = d->ifp; | 874 | skb->dev = t->ifp->nd; |
715 | 875 | ||
716 | d->rttavg = MAXTIMER; | 876 | d->rttavg = MAXTIMER; |
717 | d->timer.function = rexmit_timer; | 877 | d->timer.function = rexmit_timer; |
@@ -719,12 +879,58 @@ aoecmd_ata_id(struct aoedev *d) | |||
719 | return skb_clone(skb, GFP_ATOMIC); | 879 | return skb_clone(skb, GFP_ATOMIC); |
720 | } | 880 | } |
721 | 881 | ||
882 | static struct aoetgt * | ||
883 | addtgt(struct aoedev *d, char *addr, ulong nframes) | ||
884 | { | ||
885 | struct aoetgt *t, **tt, **te; | ||
886 | struct frame *f, *e; | ||
887 | |||
888 | tt = d->targets; | ||
889 | te = tt + NTARGETS; | ||
890 | for (; tt < te && *tt; tt++) | ||
891 | ; | ||
892 | |||
893 | if (tt == te) | ||
894 | return NULL; | ||
895 | |||
896 | t = kcalloc(1, sizeof *t, GFP_ATOMIC); | ||
897 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | ||
898 | if (!t || !f) | ||
899 | goto bail; | ||
900 | t->nframes = nframes; | ||
901 | t->frames = f; | ||
902 | e = f + nframes; | ||
903 | for (; f < e; f++) { | ||
904 | f->tag = FREETAG; | ||
905 | f->skb = new_skb(ETH_ZLEN); | ||
906 | if (!f->skb) | ||
907 | break; | ||
908 | } | ||
909 | if (f != e) { | ||
910 | while (f > t->frames) { | ||
911 | f--; | ||
912 | dev_kfree_skb(f->skb); | ||
913 | } | ||
914 | goto bail; | ||
915 | } | ||
916 | memcpy(t->addr, addr, sizeof t->addr); | ||
917 | t->ifp = t->ifs; | ||
918 | t->maxout = t->nframes; | ||
919 | return *tt = t; | ||
920 | bail: | ||
921 | kfree(t); | ||
922 | kfree(f); | ||
923 | return NULL; | ||
924 | } | ||
925 | |||
722 | void | 926 | void |
723 | aoecmd_cfg_rsp(struct sk_buff *skb) | 927 | aoecmd_cfg_rsp(struct sk_buff *skb) |
724 | { | 928 | { |
725 | struct aoedev *d; | 929 | struct aoedev *d; |
726 | struct aoe_hdr *h; | 930 | struct aoe_hdr *h; |
727 | struct aoe_cfghdr *ch; | 931 | struct aoe_cfghdr *ch; |
932 | struct aoetgt *t; | ||
933 | struct aoeif *ifp; | ||
728 | ulong flags, sysminor, aoemajor; | 934 | ulong flags, sysminor, aoemajor; |
729 | struct sk_buff *sl; | 935 | struct sk_buff *sl; |
730 | enum { MAXFRAMES = 16 }; | 936 | enum { MAXFRAMES = 16 }; |
@@ -755,7 +961,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
755 | if (n > MAXFRAMES) /* keep it reasonable */ | 961 | if (n > MAXFRAMES) /* keep it reasonable */ |
756 | n = MAXFRAMES; | 962 | n = MAXFRAMES; |
757 | 963 | ||
758 | d = aoedev_by_sysminor_m(sysminor, n); | 964 | d = aoedev_by_sysminor_m(sysminor); |
759 | if (d == NULL) { | 965 | if (d == NULL) { |
760 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); | 966 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); |
761 | return; | 967 | return; |
@@ -763,38 +969,77 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
763 | 969 | ||
764 | spin_lock_irqsave(&d->lock, flags); | 970 | spin_lock_irqsave(&d->lock, flags); |
765 | 971 | ||
766 | /* permit device to migrate mac and network interface */ | 972 | t = gettgt(d, h->src); |
767 | d->ifp = skb->dev; | 973 | if (!t) { |
768 | memcpy(d->addr, h->src, sizeof d->addr); | 974 | t = addtgt(d, h->src, n); |
769 | if (!(d->flags & DEVFL_MAXBCNT)) { | 975 | if (!t) { |
770 | n = d->ifp->mtu; | 976 | printk(KERN_INFO |
977 | "aoe: device addtgt failure; " | ||
978 | "too many targets?\n"); | ||
979 | spin_unlock_irqrestore(&d->lock, flags); | ||
980 | return; | ||
981 | } | ||
982 | } | ||
983 | ifp = getif(t, skb->dev); | ||
984 | if (!ifp) { | ||
985 | ifp = addif(t, skb->dev); | ||
986 | if (!ifp) { | ||
987 | printk(KERN_INFO | ||
988 | "aoe: device addif failure; " | ||
989 | "too many interfaces?\n"); | ||
990 | spin_unlock_irqrestore(&d->lock, flags); | ||
991 | return; | ||
992 | } | ||
993 | } | ||
994 | if (ifp->maxbcnt) { | ||
995 | n = ifp->nd->mtu; | ||
771 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | 996 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); |
772 | n /= 512; | 997 | n /= 512; |
773 | if (n > ch->scnt) | 998 | if (n > ch->scnt) |
774 | n = ch->scnt; | 999 | n = ch->scnt; |
775 | n = n ? n * 512 : DEFAULTBCNT; | 1000 | n = n ? n * 512 : DEFAULTBCNT; |
776 | if (n != d->maxbcnt) { | 1001 | if (n != ifp->maxbcnt) { |
777 | printk(KERN_INFO | 1002 | printk(KERN_INFO |
778 | "aoe: e%ld.%ld: setting %d byte data frames on %s\n", | 1003 | "aoe: e%ld.%d: setting %d%s%s:%012llx\n", |
779 | d->aoemajor, d->aoeminor, n, d->ifp->name); | 1004 | d->aoemajor, d->aoeminor, n, |
780 | d->maxbcnt = n; | 1005 | " byte data frames on ", ifp->nd->name, |
1006 | (unsigned long long) mac_addr(t->addr)); | ||
1007 | ifp->maxbcnt = n; | ||
781 | } | 1008 | } |
782 | } | 1009 | } |
783 | 1010 | ||
784 | /* don't change users' perspective */ | 1011 | /* don't change users' perspective */ |
785 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { | 1012 | if (d->nopen) { |
786 | spin_unlock_irqrestore(&d->lock, flags); | 1013 | spin_unlock_irqrestore(&d->lock, flags); |
787 | return; | 1014 | return; |
788 | } | 1015 | } |
789 | d->flags |= DEVFL_PAUSE; /* force pause */ | ||
790 | d->mintimer = MINTIMER; | ||
791 | d->fw_ver = be16_to_cpu(ch->fwver); | 1016 | d->fw_ver = be16_to_cpu(ch->fwver); |
792 | 1017 | ||
793 | /* check for already outstanding ataid */ | 1018 | sl = aoecmd_ata_id(d); |
794 | sl = aoedev_isbusy(d) == 0 ? aoecmd_ata_id(d) : NULL; | ||
795 | 1019 | ||
796 | spin_unlock_irqrestore(&d->lock, flags); | 1020 | spin_unlock_irqrestore(&d->lock, flags); |
797 | 1021 | ||
798 | aoenet_xmit(sl); | 1022 | aoenet_xmit(sl); |
799 | } | 1023 | } |
800 | 1024 | ||
1025 | void | ||
1026 | aoecmd_cleanslate(struct aoedev *d) | ||
1027 | { | ||
1028 | struct aoetgt **t, **te; | ||
1029 | struct aoeif *p, *e; | ||
1030 | |||
1031 | d->mintimer = MINTIMER; | ||
1032 | |||
1033 | t = d->targets; | ||
1034 | te = t + NTARGETS; | ||
1035 | for (; t < te && *t; t++) { | ||
1036 | (*t)->maxout = (*t)->nframes; | ||
1037 | p = (*t)->ifs; | ||
1038 | e = p + NAOEIFS; | ||
1039 | for (; p < e; p++) { | ||
1040 | p->lostjumbo = 0; | ||
1041 | p->lost = 0; | ||
1042 | p->maxbcnt = DEFAULTBCNT; | ||
1043 | } | ||
1044 | } | ||
1045 | } | ||
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 51f50710e5fc..a4d625aefeaa 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -15,15 +15,18 @@ static spinlock_t devlist_lock; | |||
15 | int | 15 | int |
16 | aoedev_isbusy(struct aoedev *d) | 16 | aoedev_isbusy(struct aoedev *d) |
17 | { | 17 | { |
18 | struct aoetgt **t, **te; | ||
18 | struct frame *f, *e; | 19 | struct frame *f, *e; |
19 | 20 | ||
20 | f = d->frames; | 21 | t = d->targets; |
21 | e = f + d->nframes; | 22 | te = t + NTARGETS; |
22 | do { | 23 | for (; t < te && *t; t++) { |
23 | if (f->tag != FREETAG) | 24 | f = (*t)->frames; |
24 | return 1; | 25 | e = f + (*t)->nframes; |
25 | } while (++f < e); | 26 | for (; f < e; f++) |
26 | 27 | if (f->tag != FREETAG) | |
28 | return 1; | ||
29 | } | ||
27 | return 0; | 30 | return 0; |
28 | } | 31 | } |
29 | 32 | ||
@@ -55,75 +58,41 @@ dummy_timer(ulong vp) | |||
55 | add_timer(&d->timer); | 58 | add_timer(&d->timer); |
56 | } | 59 | } |
57 | 60 | ||
58 | /* called with devlist lock held */ | ||
59 | static struct aoedev * | ||
60 | aoedev_newdev(ulong nframes) | ||
61 | { | ||
62 | struct aoedev *d; | ||
63 | struct frame *f, *e; | ||
64 | |||
65 | d = kzalloc(sizeof *d, GFP_ATOMIC); | ||
66 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | ||
67 | switch (!d || !f) { | ||
68 | case 0: | ||
69 | d->nframes = nframes; | ||
70 | d->frames = f; | ||
71 | e = f + nframes; | ||
72 | for (; f<e; f++) { | ||
73 | f->tag = FREETAG; | ||
74 | f->skb = new_skb(ETH_ZLEN); | ||
75 | if (!f->skb) | ||
76 | break; | ||
77 | } | ||
78 | if (f == e) | ||
79 | break; | ||
80 | while (f > d->frames) { | ||
81 | f--; | ||
82 | dev_kfree_skb(f->skb); | ||
83 | } | ||
84 | default: | ||
85 | if (f) | ||
86 | kfree(f); | ||
87 | if (d) | ||
88 | kfree(d); | ||
89 | return NULL; | ||
90 | } | ||
91 | INIT_WORK(&d->work, aoecmd_sleepwork); | ||
92 | spin_lock_init(&d->lock); | ||
93 | init_timer(&d->timer); | ||
94 | d->timer.data = (ulong) d; | ||
95 | d->timer.function = dummy_timer; | ||
96 | d->timer.expires = jiffies + HZ; | ||
97 | add_timer(&d->timer); | ||
98 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ | ||
99 | INIT_LIST_HEAD(&d->bufq); | ||
100 | d->next = devlist; | ||
101 | devlist = d; | ||
102 | |||
103 | return d; | ||
104 | } | ||
105 | |||
106 | void | 61 | void |
107 | aoedev_downdev(struct aoedev *d) | 62 | aoedev_downdev(struct aoedev *d) |
108 | { | 63 | { |
64 | struct aoetgt **t, **te; | ||
109 | struct frame *f, *e; | 65 | struct frame *f, *e; |
110 | struct buf *buf; | 66 | struct buf *buf; |
111 | struct bio *bio; | 67 | struct bio *bio; |
112 | 68 | ||
113 | f = d->frames; | 69 | t = d->targets; |
114 | e = f + d->nframes; | 70 | te = t + NTARGETS; |
115 | for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) { | 71 | for (; t < te && *t; t++) { |
116 | if (f->tag == FREETAG || f->buf == NULL) | 72 | f = (*t)->frames; |
117 | continue; | 73 | e = f + (*t)->nframes; |
118 | buf = f->buf; | 74 | for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) { |
119 | bio = buf->bio; | 75 | if (f->tag == FREETAG || f->buf == NULL) |
120 | if (--buf->nframesout == 0) { | 76 | continue; |
121 | mempool_free(buf, d->bufpool); | 77 | buf = f->buf; |
122 | bio_endio(bio, -EIO); | 78 | bio = buf->bio; |
79 | if (--buf->nframesout == 0 | ||
80 | && buf != d->inprocess) { | ||
81 | mempool_free(buf, d->bufpool); | ||
82 | bio_endio(bio, -EIO); | ||
83 | } | ||
123 | } | 84 | } |
124 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | 85 | (*t)->maxout = (*t)->nframes; |
86 | (*t)->nout = 0; | ||
87 | } | ||
88 | buf = d->inprocess; | ||
89 | if (buf) { | ||
90 | bio = buf->bio; | ||
91 | mempool_free(buf, d->bufpool); | ||
92 | bio_endio(bio, -EIO); | ||
125 | } | 93 | } |
126 | d->inprocess = NULL; | 94 | d->inprocess = NULL; |
95 | d->htgt = NULL; | ||
127 | 96 | ||
128 | while (!list_empty(&d->bufq)) { | 97 | while (!list_empty(&d->bufq)) { |
129 | buf = container_of(d->bufq.next, struct buf, bufs); | 98 | buf = container_of(d->bufq.next, struct buf, bufs); |
@@ -136,12 +105,12 @@ aoedev_downdev(struct aoedev *d) | |||
136 | if (d->gd) | 105 | if (d->gd) |
137 | d->gd->capacity = 0; | 106 | d->gd->capacity = 0; |
138 | 107 | ||
139 | d->flags &= ~(DEVFL_UP | DEVFL_PAUSE); | 108 | d->flags &= ~DEVFL_UP; |
140 | } | 109 | } |
141 | 110 | ||
142 | /* find it or malloc it */ | 111 | /* find it or malloc it */ |
143 | struct aoedev * | 112 | struct aoedev * |
144 | aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | 113 | aoedev_by_sysminor_m(ulong sysminor) |
145 | { | 114 | { |
146 | struct aoedev *d; | 115 | struct aoedev *d; |
147 | ulong flags; | 116 | ulong flags; |
@@ -151,40 +120,61 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
151 | for (d=devlist; d; d=d->next) | 120 | for (d=devlist; d; d=d->next) |
152 | if (d->sysminor == sysminor) | 121 | if (d->sysminor == sysminor) |
153 | break; | 122 | break; |
154 | 123 | if (d) | |
155 | if (d == NULL) { | 124 | goto out; |
156 | d = aoedev_newdev(bufcnt); | 125 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); |
157 | if (d == NULL) { | 126 | if (!d) |
158 | spin_unlock_irqrestore(&devlist_lock, flags); | 127 | goto out; |
159 | printk(KERN_INFO "aoe: aoedev_newdev failure.\n"); | 128 | INIT_WORK(&d->work, aoecmd_sleepwork); |
160 | return NULL; | 129 | spin_lock_init(&d->lock); |
161 | } | 130 | init_timer(&d->timer); |
162 | d->sysminor = sysminor; | 131 | d->timer.data = (ulong) d; |
163 | d->aoemajor = AOEMAJOR(sysminor); | 132 | d->timer.function = dummy_timer; |
164 | d->aoeminor = AOEMINOR(sysminor); | 133 | d->timer.expires = jiffies + HZ; |
165 | } | 134 | add_timer(&d->timer); |
166 | 135 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ | |
136 | d->tgt = d->targets; | ||
137 | INIT_LIST_HEAD(&d->bufq); | ||
138 | d->sysminor = sysminor; | ||
139 | d->aoemajor = AOEMAJOR(sysminor); | ||
140 | d->aoeminor = AOEMINOR(sysminor); | ||
141 | d->mintimer = MINTIMER; | ||
142 | d->next = devlist; | ||
143 | devlist = d; | ||
144 | out: | ||
167 | spin_unlock_irqrestore(&devlist_lock, flags); | 145 | spin_unlock_irqrestore(&devlist_lock, flags); |
168 | return d; | 146 | return d; |
169 | } | 147 | } |
170 | 148 | ||
171 | static void | 149 | static void |
172 | aoedev_freedev(struct aoedev *d) | 150 | freetgt(struct aoetgt *t) |
173 | { | 151 | { |
174 | struct frame *f, *e; | 152 | struct frame *f, *e; |
175 | 153 | ||
154 | f = t->frames; | ||
155 | e = f + t->nframes; | ||
156 | for (; f < e; f++) { | ||
157 | skb_shinfo(f->skb)->nr_frags = 0; | ||
158 | dev_kfree_skb(f->skb); | ||
159 | } | ||
160 | kfree(t->frames); | ||
161 | kfree(t); | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | aoedev_freedev(struct aoedev *d) | ||
166 | { | ||
167 | struct aoetgt **t, **e; | ||
168 | |||
176 | if (d->gd) { | 169 | if (d->gd) { |
177 | aoedisk_rm_sysfs(d); | 170 | aoedisk_rm_sysfs(d); |
178 | del_gendisk(d->gd); | 171 | del_gendisk(d->gd); |
179 | put_disk(d->gd); | 172 | put_disk(d->gd); |
180 | } | 173 | } |
181 | f = d->frames; | 174 | t = d->targets; |
182 | e = f + d->nframes; | 175 | e = t + NTARGETS; |
183 | for (; f<e; f++) { | 176 | for (; t < e && *t; t++) |
184 | skb_shinfo(f->skb)->nr_frags = 0; | 177 | freetgt(*t); |
185 | dev_kfree_skb(f->skb); | ||
186 | } | ||
187 | kfree(d->frames); | ||
188 | if (d->bufpool) | 178 | if (d->bufpool) |
189 | mempool_destroy(d->bufpool); | 179 | mempool_destroy(d->bufpool); |
190 | kfree(d); | 180 | kfree(d); |
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 4e6deb7f5c24..7a38a45ce110 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -137,9 +137,12 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
137 | if (n > NECODES) | 137 | if (n > NECODES) |
138 | n = 0; | 138 | n = 0; |
139 | if (net_ratelimit()) | 139 | if (net_ratelimit()) |
140 | printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n", | 140 | printk(KERN_ERR |
141 | be16_to_cpu(get_unaligned(&h->major)), h->minor, | 141 | "%s%d.%d@%s; ecode=%d '%s'\n", |
142 | h->err, aoe_errlist[n]); | 142 | "aoe: error packet from ", |
143 | be16_to_cpu(get_unaligned(&h->major)), | ||
144 | h->minor, skb->dev->name, | ||
145 | h->err, aoe_errlist[n]); | ||
143 | goto exit; | 146 | goto exit; |
144 | } | 147 | } |
145 | 148 | ||