diff options
-rw-r--r-- | drivers/block/aoe/aoe.h | 33 | ||||
-rw-r--r-- | drivers/block/aoe/aoechr.c | 3 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 732 | ||||
-rw-r--r-- | drivers/block/aoe/aoedev.c | 84 | ||||
-rw-r--r-- | drivers/block/aoe/aoemain.c | 8 | ||||
-rw-r--r-- | drivers/block/aoe/aoenet.c | 6 |
6 files changed, 560 insertions, 306 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 8ca8c8a929ae..0cd6c0f7a535 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -91,6 +91,7 @@ enum { | |||
91 | NTARGETS = 8, | 91 | NTARGETS = 8, |
92 | NAOEIFS = 8, | 92 | NAOEIFS = 8, |
93 | NSKBPOOLMAX = 128, | 93 | NSKBPOOLMAX = 128, |
94 | NFACTIVE = 17, | ||
94 | 95 | ||
95 | TIMERTICK = HZ / 10, | 96 | TIMERTICK = HZ / 10, |
96 | MINTIMER = HZ >> 2, | 97 | MINTIMER = HZ >> 2, |
@@ -112,13 +113,16 @@ struct buf { | |||
112 | }; | 113 | }; |
113 | 114 | ||
114 | struct frame { | 115 | struct frame { |
115 | int tag; | 116 | struct list_head head; |
117 | u32 tag; | ||
116 | ulong waited; | 118 | ulong waited; |
117 | struct buf *buf; | 119 | struct buf *buf; |
120 | struct aoetgt *t; /* parent target I belong to */ | ||
118 | char *bufaddr; | 121 | char *bufaddr; |
119 | ulong bcnt; | 122 | ulong bcnt; |
120 | sector_t lba; | 123 | sector_t lba; |
121 | struct sk_buff *skb; | 124 | struct sk_buff *skb; /* command skb freed on module exit */ |
125 | struct sk_buff *r_skb; /* response skb for async processing */ | ||
122 | struct bio_vec *bv; | 126 | struct bio_vec *bv; |
123 | ulong bv_off; | 127 | ulong bv_off; |
124 | }; | 128 | }; |
@@ -133,16 +137,18 @@ struct aoeif { | |||
133 | struct aoetgt { | 137 | struct aoetgt { |
134 | unsigned char addr[6]; | 138 | unsigned char addr[6]; |
135 | ushort nframes; | 139 | ushort nframes; |
136 | struct frame *frames; | 140 | struct aoedev *d; /* parent device I belong to */ |
141 | struct list_head factive[NFACTIVE]; /* hash of active frames */ | ||
142 | struct list_head ffree; /* list of free frames */ | ||
137 | struct aoeif ifs[NAOEIFS]; | 143 | struct aoeif ifs[NAOEIFS]; |
138 | struct aoeif *ifp; /* current aoeif in use */ | 144 | struct aoeif *ifp; /* current aoeif in use */ |
139 | ushort nout; | 145 | ushort nout; |
140 | ushort maxout; | 146 | ushort maxout; |
141 | u16 lasttag; /* last tag sent */ | 147 | u16 lasttag; /* last tag sent */ |
142 | u16 useme; | 148 | u16 useme; |
149 | ulong falloc; | ||
143 | ulong lastwadj; /* last window adjustment */ | 150 | ulong lastwadj; /* last window adjustment */ |
144 | int wpkts, rpkts; | 151 | int wpkts, rpkts; |
145 | int dataref; | ||
146 | }; | 152 | }; |
147 | 153 | ||
148 | struct aoedev { | 154 | struct aoedev { |
@@ -169,9 +175,20 @@ struct aoedev { | |||
169 | struct buf *inprocess; /* the one we're currently working on */ | 175 | struct buf *inprocess; /* the one we're currently working on */ |
170 | struct aoetgt *targets[NTARGETS]; | 176 | struct aoetgt *targets[NTARGETS]; |
171 | struct aoetgt **tgt; /* target in use when working */ | 177 | struct aoetgt **tgt; /* target in use when working */ |
172 | struct aoetgt **htgt; /* target needing rexmit assistance */ | 178 | struct aoetgt *htgt; /* target needing rexmit assistance */ |
179 | ulong ntargets; | ||
180 | ulong kicked; | ||
173 | }; | 181 | }; |
174 | 182 | ||
183 | /* kthread tracking */ | ||
184 | struct ktstate { | ||
185 | struct completion rendez; | ||
186 | struct task_struct *task; | ||
187 | wait_queue_head_t *waitq; | ||
188 | int (*fn) (void); | ||
189 | char *name; | ||
190 | spinlock_t *lock; | ||
191 | }; | ||
175 | 192 | ||
176 | int aoeblk_init(void); | 193 | int aoeblk_init(void); |
177 | void aoeblk_exit(void); | 194 | void aoeblk_exit(void); |
@@ -184,11 +201,14 @@ void aoechr_error(char *); | |||
184 | 201 | ||
185 | void aoecmd_work(struct aoedev *d); | 202 | void aoecmd_work(struct aoedev *d); |
186 | void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | 203 | void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); |
187 | void aoecmd_ata_rsp(struct sk_buff *); | 204 | struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); |
188 | void aoecmd_cfg_rsp(struct sk_buff *); | 205 | void aoecmd_cfg_rsp(struct sk_buff *); |
189 | void aoecmd_sleepwork(struct work_struct *); | 206 | void aoecmd_sleepwork(struct work_struct *); |
190 | void aoecmd_cleanslate(struct aoedev *); | 207 | void aoecmd_cleanslate(struct aoedev *); |
208 | void aoecmd_exit(void); | ||
209 | int aoecmd_init(void); | ||
191 | struct sk_buff *aoecmd_ata_id(struct aoedev *); | 210 | struct sk_buff *aoecmd_ata_id(struct aoedev *); |
211 | void aoe_freetframe(struct frame *); | ||
192 | 212 | ||
193 | int aoedev_init(void); | 213 | int aoedev_init(void); |
194 | void aoedev_exit(void); | 214 | void aoedev_exit(void); |
@@ -196,6 +216,7 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min); | |||
196 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); | 216 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); |
197 | void aoedev_downdev(struct aoedev *d); | 217 | void aoedev_downdev(struct aoedev *d); |
198 | int aoedev_flush(const char __user *str, size_t size); | 218 | int aoedev_flush(const char __user *str, size_t size); |
219 | void aoe_failbuf(struct aoedev *d, struct buf *buf); | ||
199 | 220 | ||
200 | int aoenet_init(void); | 221 | int aoenet_init(void); |
201 | void aoenet_exit(void); | 222 | void aoenet_exit(void); |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index e86d2062a164..f145388cb94a 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -86,10 +86,9 @@ revalidate(const char __user *str, size_t size) | |||
86 | if (copy_from_user(buf, str, size)) | 86 | if (copy_from_user(buf, str, size)) |
87 | return -EFAULT; | 87 | return -EFAULT; |
88 | 88 | ||
89 | /* should be e%d.%d format */ | ||
90 | n = sscanf(buf, "e%d.%d", &major, &minor); | 89 | n = sscanf(buf, "e%d.%d", &major, &minor); |
91 | if (n != 2) { | 90 | if (n != 2) { |
92 | printk(KERN_ERR "aoe: invalid device specification\n"); | 91 | pr_err("aoe: invalid device specification %s\n", buf); |
93 | return -EINVAL; | 92 | return -EINVAL; |
94 | } | 93 | } |
95 | d = aoedev_by_aoeaddr(major, minor); | 94 | d = aoedev_by_aoeaddr(major, minor); |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 9a58242290c0..59b333c902a6 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -12,10 +12,17 @@ | |||
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <linux/genhd.h> | 13 | #include <linux/genhd.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/kthread.h> | ||
15 | #include <net/net_namespace.h> | 17 | #include <net/net_namespace.h> |
16 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
19 | #include <linux/uio.h> | ||
17 | #include "aoe.h" | 20 | #include "aoe.h" |
18 | 21 | ||
22 | #define MAXIOC (8192) /* default meant to avoid most soft lockups */ | ||
23 | |||
24 | static void ktcomplete(struct frame *, struct sk_buff *); | ||
25 | |||
19 | static int aoe_deadsecs = 60 * 3; | 26 | static int aoe_deadsecs = 60 * 3; |
20 | module_param(aoe_deadsecs, int, 0644); | 27 | module_param(aoe_deadsecs, int, 0644); |
21 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | 28 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); |
@@ -25,6 +32,15 @@ module_param(aoe_maxout, int, 0644); | |||
25 | MODULE_PARM_DESC(aoe_maxout, | 32 | MODULE_PARM_DESC(aoe_maxout, |
26 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); | 33 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); |
27 | 34 | ||
35 | static wait_queue_head_t ktiowq; | ||
36 | static struct ktstate kts; | ||
37 | |||
38 | /* io completion queue */ | ||
39 | static struct { | ||
40 | struct list_head head; | ||
41 | spinlock_t lock; | ||
42 | } iocq; | ||
43 | |||
28 | static struct sk_buff * | 44 | static struct sk_buff * |
29 | new_skb(ulong len) | 45 | new_skb(ulong len) |
30 | { | 46 | { |
@@ -41,15 +57,21 @@ new_skb(ulong len) | |||
41 | } | 57 | } |
42 | 58 | ||
43 | static struct frame * | 59 | static struct frame * |
44 | getframe(struct aoetgt *t, int tag) | 60 | getframe(struct aoetgt *t, u32 tag) |
45 | { | 61 | { |
46 | struct frame *f, *e; | 62 | struct frame *f; |
63 | struct list_head *head, *pos, *nx; | ||
64 | u32 n; | ||
47 | 65 | ||
48 | f = t->frames; | 66 | n = tag % NFACTIVE; |
49 | e = f + t->nframes; | 67 | head = &t->factive[n]; |
50 | for (; f<e; f++) | 68 | list_for_each_safe(pos, nx, head) { |
51 | if (f->tag == tag) | 69 | f = list_entry(pos, struct frame, head); |
70 | if (f->tag == tag) { | ||
71 | list_del(pos); | ||
52 | return f; | 72 | return f; |
73 | } | ||
74 | } | ||
53 | return NULL; | 75 | return NULL; |
54 | } | 76 | } |
55 | 77 | ||
@@ -67,7 +89,7 @@ newtag(struct aoetgt *t) | |||
67 | return n |= (++t->lasttag & 0x7fff) << 16; | 89 | return n |= (++t->lasttag & 0x7fff) << 16; |
68 | } | 90 | } |
69 | 91 | ||
70 | static int | 92 | static u32 |
71 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) | 93 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) |
72 | { | 94 | { |
73 | u32 host_tag = newtag(t); | 95 | u32 host_tag = newtag(t); |
@@ -129,75 +151,96 @@ skb_pool_get(struct aoedev *d) | |||
129 | return NULL; | 151 | return NULL; |
130 | } | 152 | } |
131 | 153 | ||
132 | /* freeframe is where we do our load balancing so it's a little hairy. */ | 154 | void |
155 | aoe_freetframe(struct frame *f) | ||
156 | { | ||
157 | struct aoetgt *t; | ||
158 | |||
159 | t = f->t; | ||
160 | f->buf = NULL; | ||
161 | f->bv = NULL; | ||
162 | f->r_skb = NULL; | ||
163 | list_add(&f->head, &t->ffree); | ||
164 | } | ||
165 | |||
133 | static struct frame * | 166 | static struct frame * |
134 | freeframe(struct aoedev *d) | 167 | newtframe(struct aoedev *d, struct aoetgt *t) |
135 | { | 168 | { |
136 | struct frame *f, *e, *rf; | 169 | struct frame *f; |
137 | struct aoetgt **t; | ||
138 | struct sk_buff *skb; | 170 | struct sk_buff *skb; |
171 | struct list_head *pos; | ||
172 | |||
173 | if (list_empty(&t->ffree)) { | ||
174 | if (t->falloc >= NSKBPOOLMAX*2) | ||
175 | return NULL; | ||
176 | f = kcalloc(1, sizeof(*f), GFP_ATOMIC); | ||
177 | if (f == NULL) | ||
178 | return NULL; | ||
179 | t->falloc++; | ||
180 | f->t = t; | ||
181 | } else { | ||
182 | pos = t->ffree.next; | ||
183 | list_del(pos); | ||
184 | f = list_entry(pos, struct frame, head); | ||
185 | } | ||
186 | |||
187 | skb = f->skb; | ||
188 | if (skb == NULL) { | ||
189 | f->skb = skb = new_skb(ETH_ZLEN); | ||
190 | if (!skb) { | ||
191 | bail: aoe_freetframe(f); | ||
192 | return NULL; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | if (atomic_read(&skb_shinfo(skb)->dataref) != 1) { | ||
197 | skb = skb_pool_get(d); | ||
198 | if (skb == NULL) | ||
199 | goto bail; | ||
200 | skb_pool_put(d, f->skb); | ||
201 | f->skb = skb; | ||
202 | } | ||
203 | |||
204 | skb->truesize -= skb->data_len; | ||
205 | skb_shinfo(skb)->nr_frags = skb->data_len = 0; | ||
206 | skb_trim(skb, 0); | ||
207 | return f; | ||
208 | } | ||
209 | |||
210 | static struct frame * | ||
211 | newframe(struct aoedev *d) | ||
212 | { | ||
213 | struct frame *f; | ||
214 | struct aoetgt *t, **tt; | ||
215 | int totout = 0; | ||
139 | 216 | ||
140 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ | 217 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ |
141 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); | 218 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); |
142 | return NULL; | 219 | return NULL; |
143 | } | 220 | } |
144 | t = d->tgt; | 221 | tt = d->tgt; /* last used target */ |
145 | t++; | ||
146 | if (t >= &d->targets[NTARGETS] || !*t) | ||
147 | t = d->targets; | ||
148 | for (;;) { | 222 | for (;;) { |
149 | if ((*t)->nout < (*t)->maxout | 223 | tt++; |
224 | if (tt >= &d->targets[NTARGETS] || !*tt) | ||
225 | tt = d->targets; | ||
226 | t = *tt; | ||
227 | totout += t->nout; | ||
228 | if (t->nout < t->maxout | ||
150 | && t != d->htgt | 229 | && t != d->htgt |
151 | && (*t)->ifp->nd) { | 230 | && t->ifp->nd) { |
152 | rf = NULL; | 231 | f = newtframe(d, t); |
153 | f = (*t)->frames; | 232 | if (f) { |
154 | e = f + (*t)->nframes; | 233 | d->tgt = tt; |
155 | for (; f < e; f++) { | 234 | ifrotate(t); |
156 | if (f->tag != FREETAG) | ||
157 | continue; | ||
158 | skb = f->skb; | ||
159 | if (!skb | ||
160 | && !(f->skb = skb = new_skb(ETH_ZLEN))) | ||
161 | continue; | ||
162 | if (atomic_read(&skb_shinfo(skb)->dataref) | ||
163 | != 1) { | ||
164 | if (!rf) | ||
165 | rf = f; | ||
166 | continue; | ||
167 | } | ||
168 | gotone: skb->truesize -= skb->data_len; | ||
169 | skb_shinfo(skb)->nr_frags = skb->data_len = 0; | ||
170 | skb_trim(skb, 0); | ||
171 | d->tgt = t; | ||
172 | ifrotate(*t); | ||
173 | return f; | 235 | return f; |
174 | } | 236 | } |
175 | /* Work can be done, but the network layer is | ||
176 | holding our precious packets. Try to grab | ||
177 | one from the pool. */ | ||
178 | f = rf; | ||
179 | if (f == NULL) { /* more paranoia */ | ||
180 | printk(KERN_ERR | ||
181 | "aoe: freeframe: %s.\n", | ||
182 | "unexpected null rf"); | ||
183 | d->flags |= DEVFL_KICKME; | ||
184 | return NULL; | ||
185 | } | ||
186 | skb = skb_pool_get(d); | ||
187 | if (skb) { | ||
188 | skb_pool_put(d, f->skb); | ||
189 | f->skb = skb; | ||
190 | goto gotone; | ||
191 | } | ||
192 | (*t)->dataref++; | ||
193 | if ((*t)->nout == 0) | ||
194 | d->flags |= DEVFL_KICKME; | ||
195 | } | 237 | } |
196 | if (t == d->tgt) /* we've looped and found nada */ | 238 | if (tt == d->tgt) /* we've looped and found nada */ |
197 | break; | 239 | break; |
198 | t++; | 240 | } |
199 | if (t >= &d->targets[NTARGETS] || !*t) | 241 | if (totout == 0) { |
200 | t = d->targets; | 242 | d->kicked++; |
243 | d->flags |= DEVFL_KICKME; | ||
201 | } | 244 | } |
202 | return NULL; | 245 | return NULL; |
203 | } | 246 | } |
@@ -220,6 +263,16 @@ loop: | |||
220 | goto loop; | 263 | goto loop; |
221 | } | 264 | } |
222 | 265 | ||
266 | static void | ||
267 | fhash(struct frame *f) | ||
268 | { | ||
269 | struct aoetgt *t = f->t; | ||
270 | u32 n; | ||
271 | |||
272 | n = f->tag % NFACTIVE; | ||
273 | list_add_tail(&f->head, &t->factive[n]); | ||
274 | } | ||
275 | |||
223 | static int | 276 | static int |
224 | aoecmd_ata_rw(struct aoedev *d) | 277 | aoecmd_ata_rw(struct aoedev *d) |
225 | { | 278 | { |
@@ -236,7 +289,7 @@ aoecmd_ata_rw(struct aoedev *d) | |||
236 | writebit = 0x10; | 289 | writebit = 0x10; |
237 | extbit = 0x4; | 290 | extbit = 0x4; |
238 | 291 | ||
239 | f = freeframe(d); | 292 | f = newframe(d); |
240 | if (f == NULL) | 293 | if (f == NULL) |
241 | return 0; | 294 | return 0; |
242 | t = *d->tgt; | 295 | t = *d->tgt; |
@@ -274,6 +327,7 @@ aoecmd_ata_rw(struct aoedev *d) | |||
274 | skb_put(skb, sizeof *h + sizeof *ah); | 327 | skb_put(skb, sizeof *h + sizeof *ah); |
275 | memset(h, 0, skb->len); | 328 | memset(h, 0, skb->len); |
276 | f->tag = aoehdr_atainit(d, t, h); | 329 | f->tag = aoehdr_atainit(d, t, h); |
330 | fhash(f); | ||
277 | t->nout++; | 331 | t->nout++; |
278 | f->waited = 0; | 332 | f->waited = 0; |
279 | f->buf = buf; | 333 | f->buf = buf; |
@@ -358,14 +412,16 @@ cont: | |||
358 | } | 412 | } |
359 | 413 | ||
360 | static void | 414 | static void |
361 | resend(struct aoedev *d, struct aoetgt *t, struct frame *f) | 415 | resend(struct aoedev *d, struct frame *f) |
362 | { | 416 | { |
363 | struct sk_buff *skb; | 417 | struct sk_buff *skb; |
364 | struct aoe_hdr *h; | 418 | struct aoe_hdr *h; |
365 | struct aoe_atahdr *ah; | 419 | struct aoe_atahdr *ah; |
420 | struct aoetgt *t; | ||
366 | char buf[128]; | 421 | char buf[128]; |
367 | u32 n; | 422 | u32 n; |
368 | 423 | ||
424 | t = f->t; | ||
369 | ifrotate(t); | 425 | ifrotate(t); |
370 | n = newtag(t); | 426 | n = newtag(t); |
371 | skb = f->skb; | 427 | skb = f->skb; |
@@ -379,28 +435,11 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f) | |||
379 | aoechr_error(buf); | 435 | aoechr_error(buf); |
380 | 436 | ||
381 | f->tag = n; | 437 | f->tag = n; |
438 | fhash(f); | ||
382 | h->tag = cpu_to_be32(n); | 439 | h->tag = cpu_to_be32(n); |
383 | memcpy(h->dst, t->addr, sizeof h->dst); | 440 | memcpy(h->dst, t->addr, sizeof h->dst); |
384 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); | 441 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
385 | 442 | ||
386 | switch (ah->cmdstat) { | ||
387 | default: | ||
388 | break; | ||
389 | case ATA_CMD_PIO_READ: | ||
390 | case ATA_CMD_PIO_READ_EXT: | ||
391 | case ATA_CMD_PIO_WRITE: | ||
392 | case ATA_CMD_PIO_WRITE_EXT: | ||
393 | put_lba(ah, f->lba); | ||
394 | |||
395 | n = f->bcnt; | ||
396 | ah->scnt = n >> 9; | ||
397 | if (ah->aflags & AOEAFL_WRITE) { | ||
398 | skb_fillup(skb, f->bv, f->bv_off, n); | ||
399 | skb->len = sizeof *h + sizeof *ah + n; | ||
400 | skb->data_len = n; | ||
401 | skb->truesize += n; | ||
402 | } | ||
403 | } | ||
404 | skb->dev = t->ifp->nd; | 443 | skb->dev = t->ifp->nd; |
405 | skb = skb_clone(skb, GFP_ATOMIC); | 444 | skb = skb_clone(skb, GFP_ATOMIC); |
406 | if (skb == NULL) | 445 | if (skb == NULL) |
@@ -409,7 +448,7 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f) | |||
409 | } | 448 | } |
410 | 449 | ||
411 | static int | 450 | static int |
412 | tsince(int tag) | 451 | tsince(u32 tag) |
413 | { | 452 | { |
414 | int n; | 453 | int n; |
415 | 454 | ||
@@ -463,26 +502,38 @@ ejectif(struct aoetgt *t, struct aoeif *ifp) | |||
463 | static int | 502 | static int |
464 | sthtith(struct aoedev *d) | 503 | sthtith(struct aoedev *d) |
465 | { | 504 | { |
466 | struct frame *f, *e, *nf; | 505 | struct frame *f, *nf; |
506 | struct list_head *nx, *pos, *head; | ||
467 | struct sk_buff *skb; | 507 | struct sk_buff *skb; |
468 | struct aoetgt *ht = *d->htgt; | 508 | struct aoetgt *ht = d->htgt; |
469 | 509 | int i; | |
470 | f = ht->frames; | 510 | |
471 | e = f + ht->nframes; | 511 | for (i = 0; i < NFACTIVE; i++) { |
472 | for (; f < e; f++) { | 512 | head = &ht->factive[i]; |
473 | if (f->tag == FREETAG) | 513 | list_for_each_safe(pos, nx, head) { |
474 | continue; | 514 | f = list_entry(pos, struct frame, head); |
475 | nf = freeframe(d); | 515 | nf = newframe(d); |
476 | if (!nf) | 516 | if (!nf) |
477 | return 0; | 517 | return 0; |
478 | skb = nf->skb; | 518 | |
479 | *nf = *f; | 519 | /* remove frame from active list */ |
480 | f->skb = skb; | 520 | list_del(pos); |
481 | f->tag = FREETAG; | 521 | |
482 | nf->waited = 0; | 522 | /* reassign all pertinent bits to new outbound frame */ |
483 | ht->nout--; | 523 | skb = nf->skb; |
484 | (*d->tgt)->nout++; | 524 | nf->skb = f->skb; |
485 | resend(d, *d->tgt, nf); | 525 | nf->buf = f->buf; |
526 | nf->bcnt = f->bcnt; | ||
527 | nf->lba = f->lba; | ||
528 | nf->bv = f->bv; | ||
529 | nf->bv_off = f->bv_off; | ||
530 | nf->waited = 0; | ||
531 | f->skb = skb; | ||
532 | aoe_freetframe(f); | ||
533 | ht->nout--; | ||
534 | nf->t->nout++; | ||
535 | resend(d, nf); | ||
536 | } | ||
486 | } | 537 | } |
487 | /* he's clean, he's useless. take away his interfaces */ | 538 | /* he's clean, he's useless. take away his interfaces */ |
488 | memset(ht->ifs, 0, sizeof ht->ifs); | 539 | memset(ht->ifs, 0, sizeof ht->ifs); |
@@ -507,9 +558,12 @@ rexmit_timer(ulong vp) | |||
507 | struct aoedev *d; | 558 | struct aoedev *d; |
508 | struct aoetgt *t, **tt, **te; | 559 | struct aoetgt *t, **tt, **te; |
509 | struct aoeif *ifp; | 560 | struct aoeif *ifp; |
510 | struct frame *f, *e; | 561 | struct frame *f; |
562 | struct list_head *head, *pos, *nx; | ||
563 | LIST_HEAD(flist); | ||
511 | register long timeout; | 564 | register long timeout; |
512 | ulong flags, n; | 565 | ulong flags, n; |
566 | int i; | ||
513 | 567 | ||
514 | d = (struct aoedev *) vp; | 568 | d = (struct aoedev *) vp; |
515 | 569 | ||
@@ -523,41 +577,21 @@ rexmit_timer(ulong vp) | |||
523 | spin_unlock_irqrestore(&d->lock, flags); | 577 | spin_unlock_irqrestore(&d->lock, flags); |
524 | return; | 578 | return; |
525 | } | 579 | } |
580 | |||
581 | /* collect all frames to rexmit into flist */ | ||
526 | tt = d->targets; | 582 | tt = d->targets; |
527 | te = tt + NTARGETS; | 583 | te = tt + NTARGETS; |
528 | for (; tt < te && *tt; tt++) { | 584 | for (; tt < te && *tt; tt++) { |
529 | t = *tt; | 585 | t = *tt; |
530 | f = t->frames; | 586 | for (i = 0; i < NFACTIVE; i++) { |
531 | e = f + t->nframes; | 587 | head = &t->factive[i]; |
532 | for (; f < e; f++) { | 588 | list_for_each_safe(pos, nx, head) { |
533 | if (f->tag == FREETAG | 589 | f = list_entry(pos, struct frame, head); |
534 | || tsince(f->tag) < timeout) | 590 | if (tsince(f->tag) < timeout) |
535 | continue; | 591 | continue; |
536 | n = f->waited += timeout; | 592 | /* move to flist for later processing */ |
537 | n /= HZ; | 593 | list_move_tail(pos, &flist); |
538 | if (n > aoe_deadsecs) { | ||
539 | /* waited too long. device failure. */ | ||
540 | aoedev_downdev(d); | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | if (n > HELPWAIT /* see if another target can help */ | ||
545 | && (tt != d->targets || d->targets[1])) | ||
546 | d->htgt = tt; | ||
547 | |||
548 | if (t->nout == t->maxout) { | ||
549 | if (t->maxout > 1) | ||
550 | t->maxout--; | ||
551 | t->lastwadj = jiffies; | ||
552 | } | ||
553 | |||
554 | ifp = getif(t, f->skb->dev); | ||
555 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
556 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
557 | ejectif(t, ifp); | ||
558 | ifp = NULL; | ||
559 | } | 594 | } |
560 | resend(d, t, f); | ||
561 | } | 595 | } |
562 | 596 | ||
563 | /* window check */ | 597 | /* window check */ |
@@ -569,6 +603,44 @@ rexmit_timer(ulong vp) | |||
569 | } | 603 | } |
570 | } | 604 | } |
571 | 605 | ||
606 | /* process expired frames */ | ||
607 | while (!list_empty(&flist)) { | ||
608 | pos = flist.next; | ||
609 | f = list_entry(pos, struct frame, head); | ||
610 | n = f->waited += timeout; | ||
611 | n /= HZ; | ||
612 | if (n > aoe_deadsecs) { | ||
613 | /* Waited too long. Device failure. | ||
614 | * Hang all frames on first hash bucket for downdev | ||
615 | * to clean up. | ||
616 | */ | ||
617 | list_splice(&flist, &f->t->factive[0]); | ||
618 | aoedev_downdev(d); | ||
619 | break; | ||
620 | } | ||
621 | list_del(pos); | ||
622 | |||
623 | t = f->t; | ||
624 | if (n > HELPWAIT) { | ||
625 | /* see if another target can help */ | ||
626 | if (d->ntargets > 1) | ||
627 | d->htgt = t; | ||
628 | } | ||
629 | if (t->nout == t->maxout) { | ||
630 | if (t->maxout > 1) | ||
631 | t->maxout--; | ||
632 | t->lastwadj = jiffies; | ||
633 | } | ||
634 | |||
635 | ifp = getif(t, f->skb->dev); | ||
636 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
637 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
638 | ejectif(t, ifp); | ||
639 | ifp = NULL; | ||
640 | } | ||
641 | resend(d, f); | ||
642 | } | ||
643 | |||
572 | if (!skb_queue_empty(&d->sendq)) { | 644 | if (!skb_queue_empty(&d->sendq)) { |
573 | n = d->rttavg <<= 1; | 645 | n = d->rttavg <<= 1; |
574 | if (n > MAXTIMER) | 646 | if (n > MAXTIMER) |
@@ -750,7 +822,7 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector | |||
750 | } | 822 | } |
751 | 823 | ||
752 | static void | 824 | static void |
753 | bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, ulong cnt) | 825 | bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt) |
754 | { | 826 | { |
755 | ulong fcnt; | 827 | ulong fcnt; |
756 | char *p; | 828 | char *p; |
@@ -771,60 +843,225 @@ loop: | |||
771 | } | 843 | } |
772 | 844 | ||
773 | static void | 845 | static void |
774 | fadvance(struct frame *f, ulong cnt) | 846 | ktiocomplete(struct frame *f) |
775 | { | 847 | { |
776 | ulong fcnt; | 848 | struct aoe_hdr *hin, *hout; |
849 | struct aoe_atahdr *ahin, *ahout; | ||
850 | struct buf *buf; | ||
851 | struct sk_buff *skb; | ||
852 | struct aoetgt *t; | ||
853 | struct aoeif *ifp; | ||
854 | struct aoedev *d; | ||
855 | long n; | ||
777 | 856 | ||
778 | f->lba += cnt >> 9; | 857 | if (f == NULL) |
779 | loop: | ||
780 | fcnt = f->bv->bv_len - (f->bv_off - f->bv->bv_offset); | ||
781 | if (fcnt > cnt) { | ||
782 | f->bv_off += cnt; | ||
783 | return; | 858 | return; |
859 | |||
860 | t = f->t; | ||
861 | d = t->d; | ||
862 | |||
863 | hout = (struct aoe_hdr *) skb_mac_header(f->skb); | ||
864 | ahout = (struct aoe_atahdr *) (hout+1); | ||
865 | buf = f->buf; | ||
866 | skb = f->r_skb; | ||
867 | if (skb == NULL) | ||
868 | goto noskb; /* just fail the buf. */ | ||
869 | |||
870 | hin = (struct aoe_hdr *) skb->data; | ||
871 | skb_pull(skb, sizeof(*hin)); | ||
872 | ahin = (struct aoe_atahdr *) skb->data; | ||
873 | skb_pull(skb, sizeof(*ahin)); | ||
874 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | ||
875 | pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", | ||
876 | ahout->cmdstat, ahin->cmdstat, | ||
877 | d->aoemajor, d->aoeminor); | ||
878 | noskb: if (buf) | ||
879 | buf->flags |= BUFFL_FAIL; | ||
880 | goto badrsp; | ||
784 | } | 881 | } |
785 | cnt -= fcnt; | 882 | |
786 | f->bv++; | 883 | n = ahout->scnt << 9; |
787 | f->bv_off = f->bv->bv_offset; | 884 | switch (ahout->cmdstat) { |
788 | goto loop; | 885 | case ATA_CMD_PIO_READ: |
886 | case ATA_CMD_PIO_READ_EXT: | ||
887 | if (skb->len < n) { | ||
888 | pr_err("aoe: runt data size in read. skb->len=%d need=%ld\n", | ||
889 | skb->len, n); | ||
890 | buf->flags |= BUFFL_FAIL; | ||
891 | break; | ||
892 | } | ||
893 | bvcpy(f->bv, f->bv_off, skb, n); | ||
894 | case ATA_CMD_PIO_WRITE: | ||
895 | case ATA_CMD_PIO_WRITE_EXT: | ||
896 | spin_lock_irq(&d->lock); | ||
897 | ifp = getif(t, skb->dev); | ||
898 | if (ifp) { | ||
899 | ifp->lost = 0; | ||
900 | if (n > DEFAULTBCNT) | ||
901 | ifp->lostjumbo = 0; | ||
902 | } | ||
903 | if (d->htgt == t) /* I'll help myself, thank you. */ | ||
904 | d->htgt = NULL; | ||
905 | spin_unlock_irq(&d->lock); | ||
906 | break; | ||
907 | case ATA_CMD_ID_ATA: | ||
908 | if (skb->len < 512) { | ||
909 | pr_info("aoe: runt data size in ataid. skb->len=%d\n", | ||
910 | skb->len); | ||
911 | break; | ||
912 | } | ||
913 | if (skb_linearize(skb)) | ||
914 | break; | ||
915 | spin_lock_irq(&d->lock); | ||
916 | ataid_complete(d, t, skb->data); | ||
917 | spin_unlock_irq(&d->lock); | ||
918 | break; | ||
919 | default: | ||
920 | pr_info("aoe: unrecognized ata command %2.2Xh for %d.%d\n", | ||
921 | ahout->cmdstat, | ||
922 | be16_to_cpu(get_unaligned(&hin->major)), | ||
923 | hin->minor); | ||
924 | } | ||
925 | badrsp: | ||
926 | spin_lock_irq(&d->lock); | ||
927 | |||
928 | aoe_freetframe(f); | ||
929 | |||
930 | if (buf && --buf->nframesout == 0 && buf->resid == 0) { | ||
931 | struct bio *bio = buf->bio; | ||
932 | |||
933 | diskstats(d->gd, bio, jiffies - buf->stime, buf->sector); | ||
934 | n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; | ||
935 | mempool_free(buf, d->bufpool); | ||
936 | spin_unlock_irq(&d->lock); | ||
937 | if (n != -EIO) | ||
938 | bio_flush_dcache_pages(buf->bio); | ||
939 | bio_endio(bio, n); | ||
940 | } else | ||
941 | spin_unlock_irq(&d->lock); | ||
942 | dev_kfree_skb(skb); | ||
789 | } | 943 | } |
790 | 944 | ||
791 | void | 945 | /* Enters with iocq.lock held. |
946 | * Returns true iff responses needing processing remain. | ||
947 | */ | ||
948 | static int | ||
949 | ktio(void) | ||
950 | { | ||
951 | struct frame *f; | ||
952 | struct list_head *pos; | ||
953 | int i; | ||
954 | |||
955 | for (i = 0; ; ++i) { | ||
956 | if (i == MAXIOC) | ||
957 | return 1; | ||
958 | if (list_empty(&iocq.head)) | ||
959 | return 0; | ||
960 | pos = iocq.head.next; | ||
961 | list_del(pos); | ||
962 | spin_unlock_irq(&iocq.lock); | ||
963 | f = list_entry(pos, struct frame, head); | ||
964 | ktiocomplete(f); | ||
965 | spin_lock_irq(&iocq.lock); | ||
966 | } | ||
967 | } | ||
968 | |||
969 | static int | ||
970 | kthread(void *vp) | ||
971 | { | ||
972 | struct ktstate *k; | ||
973 | DECLARE_WAITQUEUE(wait, current); | ||
974 | int more; | ||
975 | |||
976 | k = vp; | ||
977 | current->flags |= PF_NOFREEZE; | ||
978 | set_user_nice(current, -10); | ||
979 | complete(&k->rendez); /* tell spawner we're running */ | ||
980 | do { | ||
981 | spin_lock_irq(k->lock); | ||
982 | more = k->fn(); | ||
983 | if (!more) { | ||
984 | add_wait_queue(k->waitq, &wait); | ||
985 | __set_current_state(TASK_INTERRUPTIBLE); | ||
986 | } | ||
987 | spin_unlock_irq(k->lock); | ||
988 | if (!more) { | ||
989 | schedule(); | ||
990 | remove_wait_queue(k->waitq, &wait); | ||
991 | } else | ||
992 | cond_resched(); | ||
993 | } while (!kthread_should_stop()); | ||
994 | complete(&k->rendez); /* tell spawner we're stopping */ | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static void | ||
999 | aoe_ktstop(struct ktstate *k) | ||
1000 | { | ||
1001 | kthread_stop(k->task); | ||
1002 | wait_for_completion(&k->rendez); | ||
1003 | } | ||
1004 | |||
1005 | static int | ||
1006 | aoe_ktstart(struct ktstate *k) | ||
1007 | { | ||
1008 | struct task_struct *task; | ||
1009 | |||
1010 | init_completion(&k->rendez); | ||
1011 | task = kthread_run(kthread, k, k->name); | ||
1012 | if (task == NULL || IS_ERR(task)) | ||
1013 | return -ENOMEM; | ||
1014 | k->task = task; | ||
1015 | wait_for_completion(&k->rendez); /* allow kthread to start */ | ||
1016 | init_completion(&k->rendez); /* for waiting for exit later */ | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | /* pass it off to kthreads for processing */ | ||
1021 | static void | ||
1022 | ktcomplete(struct frame *f, struct sk_buff *skb) | ||
1023 | { | ||
1024 | ulong flags; | ||
1025 | |||
1026 | f->r_skb = skb; | ||
1027 | spin_lock_irqsave(&iocq.lock, flags); | ||
1028 | list_add_tail(&f->head, &iocq.head); | ||
1029 | spin_unlock_irqrestore(&iocq.lock, flags); | ||
1030 | wake_up(&ktiowq); | ||
1031 | } | ||
1032 | |||
1033 | struct sk_buff * | ||
792 | aoecmd_ata_rsp(struct sk_buff *skb) | 1034 | aoecmd_ata_rsp(struct sk_buff *skb) |
793 | { | 1035 | { |
794 | struct sk_buff_head queue; | ||
795 | struct aoedev *d; | 1036 | struct aoedev *d; |
796 | struct aoe_hdr *hin, *hout; | 1037 | struct aoe_hdr *h; |
797 | struct aoe_atahdr *ahin, *ahout; | ||
798 | struct frame *f; | 1038 | struct frame *f; |
799 | struct buf *buf; | ||
800 | struct aoetgt *t; | 1039 | struct aoetgt *t; |
801 | struct aoeif *ifp; | 1040 | u32 n; |
802 | register long n; | ||
803 | ulong flags; | 1041 | ulong flags; |
804 | char ebuf[128]; | 1042 | char ebuf[128]; |
805 | u16 aoemajor; | 1043 | u16 aoemajor; |
806 | 1044 | ||
807 | hin = (struct aoe_hdr *) skb_mac_header(skb); | 1045 | h = (struct aoe_hdr *) skb->data; |
808 | skb_pull(skb, sizeof(*hin)); | 1046 | aoemajor = be16_to_cpu(get_unaligned(&h->major)); |
809 | aoemajor = get_unaligned_be16(&hin->major); | 1047 | d = aoedev_by_aoeaddr(aoemajor, h->minor); |
810 | d = aoedev_by_aoeaddr(aoemajor, hin->minor); | ||
811 | if (d == NULL) { | 1048 | if (d == NULL) { |
812 | snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response " | 1049 | snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response " |
813 | "for unknown device %d.%d\n", | 1050 | "for unknown device %d.%d\n", |
814 | aoemajor, hin->minor); | 1051 | aoemajor, h->minor); |
815 | aoechr_error(ebuf); | 1052 | aoechr_error(ebuf); |
816 | return; | 1053 | return skb; |
817 | } | 1054 | } |
818 | 1055 | ||
819 | spin_lock_irqsave(&d->lock, flags); | 1056 | spin_lock_irqsave(&d->lock, flags); |
820 | 1057 | ||
821 | n = get_unaligned_be32(&hin->tag); | 1058 | n = be32_to_cpu(get_unaligned(&h->tag)); |
822 | t = gettgt(d, hin->src); | 1059 | t = gettgt(d, h->src); |
823 | if (t == NULL) { | 1060 | if (t == NULL) { |
824 | printk(KERN_INFO "aoe: can't find target e%ld.%d:%pm\n", | 1061 | printk(KERN_INFO "aoe: can't find target e%ld.%d:%pm\n", |
825 | d->aoemajor, d->aoeminor, hin->src); | 1062 | d->aoemajor, d->aoeminor, h->src); |
826 | spin_unlock_irqrestore(&d->lock, flags); | 1063 | spin_unlock_irqrestore(&d->lock, flags); |
827 | return; | 1064 | return skb; |
828 | } | 1065 | } |
829 | f = getframe(t, n); | 1066 | f = getframe(t, n); |
830 | if (f == NULL) { | 1067 | if (f == NULL) { |
@@ -833,102 +1070,26 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
833 | snprintf(ebuf, sizeof ebuf, | 1070 | snprintf(ebuf, sizeof ebuf, |
834 | "%15s e%d.%d tag=%08x@%08lx\n", | 1071 | "%15s e%d.%d tag=%08x@%08lx\n", |
835 | "unexpected rsp", | 1072 | "unexpected rsp", |
836 | get_unaligned_be16(&hin->major), | 1073 | get_unaligned_be16(&h->major), |
837 | hin->minor, | 1074 | h->minor, |
838 | get_unaligned_be32(&hin->tag), | 1075 | get_unaligned_be32(&h->tag), |
839 | jiffies); | 1076 | jiffies); |
840 | aoechr_error(ebuf); | 1077 | aoechr_error(ebuf); |
841 | return; | 1078 | return skb; |
842 | } | 1079 | } |
843 | |||
844 | calc_rttavg(d, tsince(f->tag)); | 1080 | calc_rttavg(d, tsince(f->tag)); |
845 | |||
846 | ahin = (struct aoe_atahdr *) skb->data; | ||
847 | skb_pull(skb, sizeof(*ahin)); | ||
848 | hout = (struct aoe_hdr *) skb_mac_header(f->skb); | ||
849 | ahout = (struct aoe_atahdr *) (hout+1); | ||
850 | buf = f->buf; | ||
851 | |||
852 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | ||
853 | printk(KERN_ERR | ||
854 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", | ||
855 | ahout->cmdstat, ahin->cmdstat, | ||
856 | d->aoemajor, d->aoeminor); | ||
857 | if (buf) | ||
858 | buf->flags |= BUFFL_FAIL; | ||
859 | } else { | ||
860 | if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */ | ||
861 | d->htgt = NULL; | ||
862 | n = ahout->scnt << 9; | ||
863 | switch (ahout->cmdstat) { | ||
864 | case ATA_CMD_PIO_READ: | ||
865 | case ATA_CMD_PIO_READ_EXT: | ||
866 | if (skb->len < n) { | ||
867 | printk(KERN_ERR | ||
868 | "aoe: %s. skb->len=%d need=%ld\n", | ||
869 | "runt data size in read", skb->len, n); | ||
870 | /* fail frame f? just returning will rexmit. */ | ||
871 | spin_unlock_irqrestore(&d->lock, flags); | ||
872 | return; | ||
873 | } | ||
874 | bvcpy(f->bv, f->bv_off, skb, n); | ||
875 | case ATA_CMD_PIO_WRITE: | ||
876 | case ATA_CMD_PIO_WRITE_EXT: | ||
877 | ifp = getif(t, skb->dev); | ||
878 | if (ifp) { | ||
879 | ifp->lost = 0; | ||
880 | if (n > DEFAULTBCNT) | ||
881 | ifp->lostjumbo = 0; | ||
882 | } | ||
883 | if (f->bcnt -= n) { | ||
884 | fadvance(f, n); | ||
885 | resend(d, t, f); | ||
886 | goto xmit; | ||
887 | } | ||
888 | break; | ||
889 | case ATA_CMD_ID_ATA: | ||
890 | if (skb->len < 512) { | ||
891 | printk(KERN_INFO | ||
892 | "aoe: runt data size in ataid. skb->len=%d\n", | ||
893 | skb->len); | ||
894 | spin_unlock_irqrestore(&d->lock, flags); | ||
895 | return; | ||
896 | } | ||
897 | if (skb_linearize(skb)) | ||
898 | break; | ||
899 | ataid_complete(d, t, skb->data); | ||
900 | break; | ||
901 | default: | ||
902 | printk(KERN_INFO | ||
903 | "aoe: unrecognized ata command %2.2Xh for %d.%d\n", | ||
904 | ahout->cmdstat, | ||
905 | get_unaligned_be16(&hin->major), | ||
906 | hin->minor); | ||
907 | } | ||
908 | } | ||
909 | |||
910 | if (buf && --buf->nframesout == 0 && buf->resid == 0) { | ||
911 | diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector); | ||
912 | if (buf->flags & BUFFL_FAIL) | ||
913 | bio_endio(buf->bio, -EIO); | ||
914 | else { | ||
915 | bio_flush_dcache_pages(buf->bio); | ||
916 | bio_endio(buf->bio, 0); | ||
917 | } | ||
918 | mempool_free(buf, d->bufpool); | ||
919 | } | ||
920 | |||
921 | f->buf = NULL; | ||
922 | f->tag = FREETAG; | ||
923 | t->nout--; | 1081 | t->nout--; |
924 | |||
925 | aoecmd_work(d); | 1082 | aoecmd_work(d); |
926 | xmit: | ||
927 | __skb_queue_head_init(&queue); | ||
928 | skb_queue_splice_init(&d->sendq, &queue); | ||
929 | 1083 | ||
930 | spin_unlock_irqrestore(&d->lock, flags); | 1084 | spin_unlock_irqrestore(&d->lock, flags); |
931 | aoenet_xmit(&queue); | 1085 | |
1086 | ktcomplete(f, skb); | ||
1087 | |||
1088 | /* | ||
1089 | * Note here that we do not perform an aoedev_put, as we are | ||
1090 | * leaving this reference for the ktio to release. | ||
1091 | */ | ||
1092 | return NULL; | ||
932 | } | 1093 | } |
933 | 1094 | ||
934 | void | 1095 | void |
@@ -950,7 +1111,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
950 | struct sk_buff *skb; | 1111 | struct sk_buff *skb; |
951 | struct aoetgt *t; | 1112 | struct aoetgt *t; |
952 | 1113 | ||
953 | f = freeframe(d); | 1114 | f = newframe(d); |
954 | if (f == NULL) | 1115 | if (f == NULL) |
955 | return NULL; | 1116 | return NULL; |
956 | 1117 | ||
@@ -963,6 +1124,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
963 | skb_put(skb, sizeof *h + sizeof *ah); | 1124 | skb_put(skb, sizeof *h + sizeof *ah); |
964 | memset(h, 0, skb->len); | 1125 | memset(h, 0, skb->len); |
965 | f->tag = aoehdr_atainit(d, t, h); | 1126 | f->tag = aoehdr_atainit(d, t, h); |
1127 | fhash(f); | ||
966 | t->nout++; | 1128 | t->nout++; |
967 | f->waited = 0; | 1129 | f->waited = 0; |
968 | 1130 | ||
@@ -983,7 +1145,7 @@ static struct aoetgt * | |||
983 | addtgt(struct aoedev *d, char *addr, ulong nframes) | 1145 | addtgt(struct aoedev *d, char *addr, ulong nframes) |
984 | { | 1146 | { |
985 | struct aoetgt *t, **tt, **te; | 1147 | struct aoetgt *t, **tt, **te; |
986 | struct frame *f, *e; | 1148 | int i; |
987 | 1149 | ||
988 | tt = d->targets; | 1150 | tt = d->targets; |
989 | te = tt + NTARGETS; | 1151 | te = tt + NTARGETS; |
@@ -995,23 +1157,21 @@ addtgt(struct aoedev *d, char *addr, ulong nframes) | |||
995 | "aoe: device addtgt failure; too many targets\n"); | 1157 | "aoe: device addtgt failure; too many targets\n"); |
996 | return NULL; | 1158 | return NULL; |
997 | } | 1159 | } |
998 | t = kcalloc(1, sizeof *t, GFP_ATOMIC); | 1160 | t = kzalloc(sizeof(*t), GFP_ATOMIC); |
999 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | 1161 | if (!t) { |
1000 | if (!t || !f) { | ||
1001 | kfree(f); | ||
1002 | kfree(t); | ||
1003 | printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); | 1162 | printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); |
1004 | return NULL; | 1163 | return NULL; |
1005 | } | 1164 | } |
1006 | 1165 | ||
1166 | d->ntargets++; | ||
1007 | t->nframes = nframes; | 1167 | t->nframes = nframes; |
1008 | t->frames = f; | 1168 | t->d = d; |
1009 | e = f + nframes; | ||
1010 | for (; f < e; f++) | ||
1011 | f->tag = FREETAG; | ||
1012 | memcpy(t->addr, addr, sizeof t->addr); | 1169 | memcpy(t->addr, addr, sizeof t->addr); |
1013 | t->ifp = t->ifs; | 1170 | t->ifp = t->ifs; |
1014 | t->maxout = t->nframes; | 1171 | t->maxout = t->nframes; |
1172 | INIT_LIST_HEAD(&t->ffree); | ||
1173 | for (i = 0; i < NFACTIVE; ++i) | ||
1174 | INIT_LIST_HEAD(&t->factive[i]); | ||
1015 | return *tt = t; | 1175 | return *tt = t; |
1016 | } | 1176 | } |
1017 | 1177 | ||
@@ -1136,3 +1296,53 @@ aoecmd_cleanslate(struct aoedev *d) | |||
1136 | } | 1296 | } |
1137 | } | 1297 | } |
1138 | } | 1298 | } |
1299 | |||
1300 | static void | ||
1301 | flush_iocq(void) | ||
1302 | { | ||
1303 | struct frame *f; | ||
1304 | struct aoedev *d; | ||
1305 | LIST_HEAD(flist); | ||
1306 | struct list_head *pos; | ||
1307 | struct sk_buff *skb; | ||
1308 | ulong flags; | ||
1309 | |||
1310 | spin_lock_irqsave(&iocq.lock, flags); | ||
1311 | list_splice_init(&iocq.head, &flist); | ||
1312 | spin_unlock_irqrestore(&iocq.lock, flags); | ||
1313 | while (!list_empty(&flist)) { | ||
1314 | pos = flist.next; | ||
1315 | list_del(pos); | ||
1316 | f = list_entry(pos, struct frame, head); | ||
1317 | d = f->t->d; | ||
1318 | skb = f->r_skb; | ||
1319 | spin_lock_irqsave(&d->lock, flags); | ||
1320 | if (f->buf) { | ||
1321 | f->buf->nframesout--; | ||
1322 | aoe_failbuf(d, f->buf); | ||
1323 | } | ||
1324 | aoe_freetframe(f); | ||
1325 | spin_unlock_irqrestore(&d->lock, flags); | ||
1326 | dev_kfree_skb(skb); | ||
1327 | } | ||
1328 | } | ||
1329 | |||
1330 | int __init | ||
1331 | aoecmd_init(void) | ||
1332 | { | ||
1333 | INIT_LIST_HEAD(&iocq.head); | ||
1334 | spin_lock_init(&iocq.lock); | ||
1335 | init_waitqueue_head(&ktiowq); | ||
1336 | kts.name = "aoe_ktio"; | ||
1337 | kts.fn = ktio; | ||
1338 | kts.waitq = &ktiowq; | ||
1339 | kts.lock = &iocq.lock; | ||
1340 | return aoe_ktstart(&kts); | ||
1341 | } | ||
1342 | |||
1343 | void | ||
1344 | aoecmd_exit(void) | ||
1345 | { | ||
1346 | aoe_ktstop(&kts); | ||
1347 | flush_iocq(); | ||
1348 | } | ||
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index b2d1fd354eac..40bae1a1ff1e 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -48,47 +48,60 @@ dummy_timer(ulong vp) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | void | 50 | void |
51 | aoedev_downdev(struct aoedev *d) | 51 | aoe_failbuf(struct aoedev *d, struct buf *buf) |
52 | { | 52 | { |
53 | struct aoetgt **t, **te; | ||
54 | struct frame *f, *e; | ||
55 | struct buf *buf; | ||
56 | struct bio *bio; | 53 | struct bio *bio; |
57 | 54 | ||
58 | t = d->targets; | 55 | if (buf == NULL) |
59 | te = t + NTARGETS; | 56 | return; |
60 | for (; t < te && *t; t++) { | 57 | buf->flags |= BUFFL_FAIL; |
61 | f = (*t)->frames; | 58 | if (buf->nframesout == 0) { |
62 | e = f + (*t)->nframes; | 59 | if (buf == d->inprocess) /* ensure we only process this once */ |
63 | for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) { | 60 | d->inprocess = NULL; |
64 | if (f->tag == FREETAG || f->buf == NULL) | ||
65 | continue; | ||
66 | buf = f->buf; | ||
67 | bio = buf->bio; | ||
68 | if (--buf->nframesout == 0 | ||
69 | && buf != d->inprocess) { | ||
70 | mempool_free(buf, d->bufpool); | ||
71 | bio_endio(bio, -EIO); | ||
72 | } | ||
73 | } | ||
74 | (*t)->maxout = (*t)->nframes; | ||
75 | (*t)->nout = 0; | ||
76 | } | ||
77 | buf = d->inprocess; | ||
78 | if (buf) { | ||
79 | bio = buf->bio; | 61 | bio = buf->bio; |
80 | mempool_free(buf, d->bufpool); | 62 | mempool_free(buf, d->bufpool); |
81 | bio_endio(bio, -EIO); | 63 | bio_endio(bio, -EIO); |
82 | } | 64 | } |
65 | } | ||
66 | |||
67 | void | ||
68 | aoedev_downdev(struct aoedev *d) | ||
69 | { | ||
70 | struct aoetgt *t, **tt, **te; | ||
71 | struct frame *f; | ||
72 | struct list_head *head, *pos, *nx; | ||
73 | int i; | ||
74 | |||
75 | /* clean out active buffers on all targets */ | ||
76 | tt = d->targets; | ||
77 | te = tt + NTARGETS; | ||
78 | for (; tt < te && (t = *tt); tt++) { | ||
79 | for (i = 0; i < NFACTIVE; i++) { | ||
80 | head = &t->factive[i]; | ||
81 | list_for_each_safe(pos, nx, head) { | ||
82 | list_del(pos); | ||
83 | f = list_entry(pos, struct frame, head); | ||
84 | if (f->buf) { | ||
85 | f->buf->nframesout--; | ||
86 | aoe_failbuf(d, f->buf); | ||
87 | } | ||
88 | aoe_freetframe(f); | ||
89 | } | ||
90 | } | ||
91 | t->maxout = t->nframes; | ||
92 | t->nout = 0; | ||
93 | } | ||
94 | |||
95 | /* clean out the in-process buffer (if any) */ | ||
96 | aoe_failbuf(d, d->inprocess); | ||
83 | d->inprocess = NULL; | 97 | d->inprocess = NULL; |
84 | d->htgt = NULL; | 98 | d->htgt = NULL; |
85 | 99 | ||
100 | /* clean out all pending I/O */ | ||
86 | while (!list_empty(&d->bufq)) { | 101 | while (!list_empty(&d->bufq)) { |
87 | buf = container_of(d->bufq.next, struct buf, bufs); | 102 | struct buf *buf = container_of(d->bufq.next, struct buf, bufs); |
88 | list_del(d->bufq.next); | 103 | list_del(d->bufq.next); |
89 | bio = buf->bio; | 104 | aoe_failbuf(d, buf); |
90 | mempool_free(buf, d->bufpool); | ||
91 | bio_endio(bio, -EIO); | ||
92 | } | 105 | } |
93 | 106 | ||
94 | if (d->gd) | 107 | if (d->gd) |
@@ -242,13 +255,16 @@ aoedev_by_sysminor_m(ulong sysminor) | |||
242 | static void | 255 | static void |
243 | freetgt(struct aoedev *d, struct aoetgt *t) | 256 | freetgt(struct aoedev *d, struct aoetgt *t) |
244 | { | 257 | { |
245 | struct frame *f, *e; | 258 | struct frame *f; |
259 | struct list_head *pos, *nx, *head; | ||
246 | 260 | ||
247 | f = t->frames; | 261 | head = &t->ffree; |
248 | e = f + t->nframes; | 262 | list_for_each_safe(pos, nx, head) { |
249 | for (; f < e; f++) | 263 | list_del(pos); |
264 | f = list_entry(pos, struct frame, head); | ||
250 | skbfree(f->skb); | 265 | skbfree(f->skb); |
251 | kfree(t->frames); | 266 | kfree(f); |
267 | } | ||
252 | kfree(t); | 268 | kfree(t); |
253 | } | 269 | } |
254 | 270 | ||
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 7f83ad90e76f..6fc4b050fab1 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c | |||
@@ -61,6 +61,7 @@ aoe_exit(void) | |||
61 | 61 | ||
62 | aoenet_exit(); | 62 | aoenet_exit(); |
63 | unregister_blkdev(AOE_MAJOR, DEVICE_NAME); | 63 | unregister_blkdev(AOE_MAJOR, DEVICE_NAME); |
64 | aoecmd_exit(); | ||
64 | aoechr_exit(); | 65 | aoechr_exit(); |
65 | aoedev_exit(); | 66 | aoedev_exit(); |
66 | aoeblk_exit(); /* free cache after de-allocating bufs */ | 67 | aoeblk_exit(); /* free cache after de-allocating bufs */ |
@@ -83,17 +84,20 @@ aoe_init(void) | |||
83 | ret = aoenet_init(); | 84 | ret = aoenet_init(); |
84 | if (ret) | 85 | if (ret) |
85 | goto net_fail; | 86 | goto net_fail; |
87 | ret = aoecmd_init(); | ||
88 | if (ret) | ||
89 | goto cmd_fail; | ||
86 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); | 90 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); |
87 | if (ret < 0) { | 91 | if (ret < 0) { |
88 | printk(KERN_ERR "aoe: can't register major\n"); | 92 | printk(KERN_ERR "aoe: can't register major\n"); |
89 | goto blkreg_fail; | 93 | goto blkreg_fail; |
90 | } | 94 | } |
91 | |||
92 | printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); | 95 | printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); |
93 | discover_timer(TINIT); | 96 | discover_timer(TINIT); |
94 | return 0; | 97 | return 0; |
95 | |||
96 | blkreg_fail: | 98 | blkreg_fail: |
99 | aoecmd_exit(); | ||
100 | cmd_fail: | ||
97 | aoenet_exit(); | 101 | aoenet_exit(); |
98 | net_fail: | 102 | net_fail: |
99 | aoeblk_exit(); | 103 | aoeblk_exit(); |
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 07878076e43c..000eff2b53a8 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -142,7 +142,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
142 | 142 | ||
143 | switch (h->cmd) { | 143 | switch (h->cmd) { |
144 | case AOECMD_ATA: | 144 | case AOECMD_ATA: |
145 | aoecmd_ata_rsp(skb); | 145 | /* ata_rsp may keep skb for later processing or give it back */ |
146 | skb = aoecmd_ata_rsp(skb); | ||
146 | break; | 147 | break; |
147 | case AOECMD_CFG: | 148 | case AOECMD_CFG: |
148 | aoecmd_cfg_rsp(skb); | 149 | aoecmd_cfg_rsp(skb); |
@@ -152,6 +153,9 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
152 | break; /* don't complain about vendor commands */ | 153 | break; /* don't complain about vendor commands */ |
153 | printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd); | 154 | printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd); |
154 | } | 155 | } |
156 | |||
157 | if (!skb) | ||
158 | return 0; | ||
155 | exit: | 159 | exit: |
156 | dev_kfree_skb(skb); | 160 | dev_kfree_skb(skb); |
157 | return 0; | 161 | return 0; |