aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/aoe/aoecmd.c
diff options
context:
space:
mode:
authorEd L. Cashin <ecashin@coraid.com>2006-09-20 14:36:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-10-18 15:53:50 -0400
commit4f51dc5e9ae195d2e8c22e5f574e004c2f6518a4 (patch)
tree852ab0b29d19f1ac9a4f7e7eeba6510c0ee7bca1 /drivers/block/aoe/aoecmd.c
parentdced3a053dd5415a7321e1ae153c96dea644da4e (diff)
aoe: zero copy write 2 of 2
Avoid memory copy on writes. (This patch follows patch 4.) Signed-off-by: "Ed L. Cashin" <ecashin@coraid.com> Acked-by: Alan Cox <alan@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/block/aoe/aoecmd.c')
-rw-r--r--drivers/block/aoe/aoecmd.c82
1 files changed, 62 insertions, 20 deletions
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index c0bdc1fe21f0..9ebc98ade3c5 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -120,7 +120,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
120 h = (struct aoe_hdr *) skb->mac.raw; 120 h = (struct aoe_hdr *) skb->mac.raw;
121 ah = (struct aoe_atahdr *) (h+1); 121 ah = (struct aoe_atahdr *) (h+1);
122 skb->len = sizeof *h + sizeof *ah; 122 skb->len = sizeof *h + sizeof *ah;
123 memset(h, 0, skb->len); 123 memset(h, 0, ETH_ZLEN);
124 f->tag = aoehdr_atainit(d, h); 124 f->tag = aoehdr_atainit(d, h);
125 f->waited = 0; 125 f->waited = 0;
126 f->buf = buf; 126 f->buf = buf;
@@ -143,8 +143,9 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
143 skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), 143 skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
144 offset_in_page(f->bufaddr), bcnt); 144 offset_in_page(f->bufaddr), bcnt);
145 ah->aflags |= AOEAFL_WRITE; 145 ah->aflags |= AOEAFL_WRITE;
146 skb->len += bcnt;
147 skb->data_len = bcnt;
146 } else { 148 } else {
147 skb_shinfo(skb)->nr_frags = 0;
148 skb->len = ETH_ZLEN; 149 skb->len = ETH_ZLEN;
149 writebit = 0; 150 writebit = 0;
150 } 151 }
@@ -167,8 +168,9 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
167 } 168 }
168 169
169 skb->dev = d->ifp; 170 skb->dev = d->ifp;
170 skb_get(skb); 171 skb = skb_clone(skb, GFP_ATOMIC);
171 skb->next = NULL; 172 if (skb == NULL)
173 return;
172 if (d->sendq_hd) 174 if (d->sendq_hd)
173 d->sendq_tl->next = skb; 175 d->sendq_tl->next = skb;
174 else 176 else
@@ -224,6 +226,29 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
224 return sl; 226 return sl;
225} 227}
226 228
229static struct frame *
230freeframe(struct aoedev *d)
231{
232 struct frame *f, *e;
233 int n = 0;
234
235 f = d->frames;
236 e = f + d->nframes;
237 for (; f<e; f++) {
238 if (f->tag != FREETAG)
239 continue;
240 if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) {
241 skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
242 return f;
243 }
244 n++;
245 }
246 if (n == d->nframes) /* wait for network layer */
247 d->flags |= DEVFL_KICKME;
248
249 return NULL;
250}
251
227/* enters with d->lock held */ 252/* enters with d->lock held */
228void 253void
229aoecmd_work(struct aoedev *d) 254aoecmd_work(struct aoedev *d)
@@ -239,7 +264,7 @@ aoecmd_work(struct aoedev *d)
239 } 264 }
240 265
241loop: 266loop:
242 f = getframe(d, FREETAG); 267 f = freeframe(d);
243 if (f == NULL) 268 if (f == NULL)
244 return; 269 return;
245 if (d->inprocess == NULL) { 270 if (d->inprocess == NULL) {
@@ -282,20 +307,25 @@ rexmit(struct aoedev *d, struct frame *f)
282 n = DEFAULTBCNT / 512; 307 n = DEFAULTBCNT / 512;
283 if (ah->scnt > n) { 308 if (ah->scnt > n) {
284 ah->scnt = n; 309 ah->scnt = n;
285 if (ah->aflags & AOEAFL_WRITE) 310 if (ah->aflags & AOEAFL_WRITE) {
286 skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), 311 skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
287 offset_in_page(f->bufaddr), DEFAULTBCNT); 312 offset_in_page(f->bufaddr), DEFAULTBCNT);
313 skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT;
314 skb->data_len = DEFAULTBCNT;
315 }
288 if (++d->lostjumbo > (d->nframes << 1)) 316 if (++d->lostjumbo > (d->nframes << 1))
289 if (d->maxbcnt != DEFAULTBCNT) { 317 if (d->maxbcnt != DEFAULTBCNT) {
290 iprintk("too many lost jumbo - using 1KB frames.\n"); 318 iprintk("e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n",
319 d->aoemajor, d->aoeminor, d->ifp->name);
291 d->maxbcnt = DEFAULTBCNT; 320 d->maxbcnt = DEFAULTBCNT;
292 d->flags |= DEVFL_MAXBCNT; 321 d->flags |= DEVFL_MAXBCNT;
293 } 322 }
294 } 323 }
295 324
296 skb->dev = d->ifp; 325 skb->dev = d->ifp;
297 skb_get(skb); 326 skb = skb_clone(skb, GFP_ATOMIC);
298 skb->next = NULL; 327 if (skb == NULL)
328 return;
299 if (d->sendq_hd) 329 if (d->sendq_hd)
300 d->sendq_tl->next = skb; 330 d->sendq_tl->next = skb;
301 else 331 else
@@ -350,6 +380,10 @@ rexmit_timer(ulong vp)
350 rexmit(d, f); 380 rexmit(d, f);
351 } 381 }
352 } 382 }
383 if (d->flags & DEVFL_KICKME) {
384 d->flags &= ~DEVFL_KICKME;
385 aoecmd_work(d);
386 }
353 387
354 sl = d->sendq_hd; 388 sl = d->sendq_hd;
355 d->sendq_hd = d->sendq_tl = NULL; 389 d->sendq_hd = d->sendq_tl = NULL;
@@ -552,23 +586,27 @@ aoecmd_ata_rsp(struct sk_buff *skb)
552 case WIN_WRITE: 586 case WIN_WRITE:
553 case WIN_WRITE_EXT: 587 case WIN_WRITE_EXT:
554 if (f->bcnt -= n) { 588 if (f->bcnt -= n) {
589 skb = f->skb;
555 f->bufaddr += n; 590 f->bufaddr += n;
556 put_lba(ahout, f->lba += ahout->scnt); 591 put_lba(ahout, f->lba += ahout->scnt);
557 n = f->bcnt; 592 n = f->bcnt;
558 if (n > DEFAULTBCNT) 593 if (n > DEFAULTBCNT)
559 n = DEFAULTBCNT; 594 n = DEFAULTBCNT;
560 ahout->scnt = n >> 9; 595 ahout->scnt = n >> 9;
561 if (ahout->aflags & AOEAFL_WRITE) 596 if (ahout->aflags & AOEAFL_WRITE) {
562 skb_fill_page_desc(f->skb, 0, 597 skb_fill_page_desc(skb, 0,
563 virt_to_page(f->bufaddr), 598 virt_to_page(f->bufaddr),
564 offset_in_page(f->bufaddr), n); 599 offset_in_page(f->bufaddr), n);
600 skb->len = sizeof *hout + sizeof *ahout + n;
601 skb->data_len = n;
602 }
565 f->tag = newtag(d); 603 f->tag = newtag(d);
566 hout->tag = cpu_to_be32(f->tag); 604 hout->tag = cpu_to_be32(f->tag);
567 skb->dev = d->ifp; 605 skb->dev = d->ifp;
568 skb_get(f->skb); 606 skb = skb_clone(skb, GFP_ATOMIC);
569 f->skb->next = NULL;
570 spin_unlock_irqrestore(&d->lock, flags); 607 spin_unlock_irqrestore(&d->lock, flags);
571 aoenet_xmit(f->skb); 608 if (skb)
609 aoenet_xmit(skb);
572 return; 610 return;
573 } 611 }
574 if (n > DEFAULTBCNT) 612 if (n > DEFAULTBCNT)
@@ -642,7 +680,7 @@ aoecmd_ata_id(struct aoedev *d)
642 struct frame *f; 680 struct frame *f;
643 struct sk_buff *skb; 681 struct sk_buff *skb;
644 682
645 f = getframe(d, FREETAG); 683 f = freeframe(d);
646 if (f == NULL) { 684 if (f == NULL) {
647 eprintk("can't get a frame. This shouldn't happen.\n"); 685 eprintk("can't get a frame. This shouldn't happen.\n");
648 return NULL; 686 return NULL;
@@ -652,8 +690,8 @@ aoecmd_ata_id(struct aoedev *d)
652 skb = f->skb; 690 skb = f->skb;
653 h = (struct aoe_hdr *) skb->mac.raw; 691 h = (struct aoe_hdr *) skb->mac.raw;
654 ah = (struct aoe_atahdr *) (h+1); 692 ah = (struct aoe_atahdr *) (h+1);
655 skb->len = sizeof *h + sizeof *ah; 693 skb->len = ETH_ZLEN;
656 memset(h, 0, skb->len); 694 memset(h, 0, ETH_ZLEN);
657 f->tag = aoehdr_atainit(d, h); 695 f->tag = aoehdr_atainit(d, h);
658 f->waited = 0; 696 f->waited = 0;
659 697
@@ -663,12 +701,11 @@ aoecmd_ata_id(struct aoedev *d)
663 ah->lba3 = 0xa0; 701 ah->lba3 = 0xa0;
664 702
665 skb->dev = d->ifp; 703 skb->dev = d->ifp;
666 skb_get(skb);
667 704
668 d->rttavg = MAXTIMER; 705 d->rttavg = MAXTIMER;
669 d->timer.function = rexmit_timer; 706 d->timer.function = rexmit_timer;
670 707
671 return skb; 708 return skb_clone(skb, GFP_ATOMIC);
672} 709}
673 710
674void 711void
@@ -724,7 +761,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
724 n /= 512; 761 n /= 512;
725 if (n > ch->scnt) 762 if (n > ch->scnt)
726 n = ch->scnt; 763 n = ch->scnt;
727 d->maxbcnt = n ? n * 512 : DEFAULTBCNT; 764 n = n ? n * 512 : DEFAULTBCNT;
765 if (n != d->maxbcnt) {
766 iprintk("e%ld.%ld: setting %d byte data frames on %s\n",
767 d->aoemajor, d->aoeminor, n, d->ifp->name);
768 d->maxbcnt = n;
769 }
728 } 770 }
729 771
730 /* don't change users' perspective */ 772 /* don't change users' perspective */