diff options
Diffstat (limited to 'drivers/block/aoe/aoecmd.c')
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 732 |
1 files changed, 471 insertions, 261 deletions
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 | } | ||