aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
commit19bf26353c50bc2be375109ec73f2f0bbd616ed1 (patch)
tree5bcdf714d67d573885d2f42a7c0a79586de77c25 /drivers
parente407a7f6cd143b3ab4eb3d7e1cf882e96b710eb5 (diff)
aoe: jumbo frame support 1 of 2
Add support for jumbo ethernet frames. (This patch depends on patch 7 to follow.) 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')
-rw-r--r--drivers/block/aoe/aoe.h11
-rw-r--r--drivers/block/aoe/aoechr.c1
-rw-r--r--drivers/block/aoe/aoecmd.c77
3 files changed, 72 insertions, 17 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index fa2d804b2665..1cec19986c40 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -65,7 +65,7 @@ struct aoe_atahdr {
65struct aoe_cfghdr { 65struct aoe_cfghdr {
66 __be16 bufcnt; 66 __be16 bufcnt;
67 __be16 fwver; 67 __be16 fwver;
68 unsigned char res; 68 unsigned char scnt;
69 unsigned char aoeccmd; 69 unsigned char aoeccmd;
70 unsigned char cslen[2]; 70 unsigned char cslen[2];
71}; 71};
@@ -78,12 +78,13 @@ enum {
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_PAUSE = (1<<5),
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 */
81 82
82 BUFFL_FAIL = 1, 83 BUFFL_FAIL = 1,
83}; 84};
84 85
85enum { 86enum {
86 MAXATADATA = 1024, 87 DEFAULTBCNT = 2 * 512, /* 2 sectors */
87 NPERSHELF = 16, /* number of slots per shelf address */ 88 NPERSHELF = 16, /* number of slots per shelf address */
88 FREETAG = -1, 89 FREETAG = -1,
89 MIN_BUFS = 8, 90 MIN_BUFS = 8,
@@ -107,6 +108,8 @@ struct frame {
107 ulong waited; 108 ulong waited;
108 struct buf *buf; 109 struct buf *buf;
109 char *bufaddr; 110 char *bufaddr;
111 ulong bcnt;
112 sector_t lba;
110 struct sk_buff *skb; 113 struct sk_buff *skb;
111}; 114};
112 115
@@ -120,6 +123,7 @@ struct aoedev {
120 ulong nopen; /* (bd_openers isn't available without sleeping) */ 123 ulong nopen; /* (bd_openers isn't available without sleeping) */
121 ulong rttavg; /* round trip average of requests/responses */ 124 ulong rttavg; /* round trip average of requests/responses */
122 u16 fw_ver; /* version of blade's firmware */ 125 u16 fw_ver; /* version of blade's firmware */
126 u16 maxbcnt;
123 struct work_struct work;/* disk create work struct */ 127 struct work_struct work;/* disk create work struct */
124 struct gendisk *gd; 128 struct gendisk *gd;
125 request_queue_t blkq; 129 request_queue_t blkq;
@@ -134,7 +138,8 @@ struct aoedev {
134 struct list_head bufq; /* queue of bios to work on */ 138 struct list_head bufq; /* queue of bios to work on */
135 struct buf *inprocess; /* the one we're currently working on */ 139 struct buf *inprocess; /* the one we're currently working on */
136 ulong lasttag; /* last tag sent */ 140 ulong lasttag; /* last tag sent */
137 ulong nframes; /* number of frames below */ 141 ushort lostjumbo;
142 ushort nframes; /* number of frames below */
138 struct frame *frames; 143 struct frame *frames;
139}; 144};
140 145
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 0c543d3bfe58..2b5256cc733d 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -89,6 +89,7 @@ revalidate(const char __user *str, size_t size)
89 return -EINVAL; 89 return -EINVAL;
90 90
91 spin_lock_irqsave(&d->lock, flags); 91 spin_lock_irqsave(&d->lock, flags);
92 d->flags &= ~DEVFL_MAXBCNT;
92 d->flags |= DEVFL_PAUSE; 93 d->flags |= DEVFL_PAUSE;
93 spin_unlock_irqrestore(&d->lock, flags); 94 spin_unlock_irqrestore(&d->lock, flags);
94 aoecmd_cfg(major, minor); 95 aoecmd_cfg(major, minor);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 1aeb2969987f..666797d646d6 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -83,6 +83,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h)
83 return host_tag; 83 return host_tag;
84} 84}
85 85
86static inline void
87put_lba(struct aoe_atahdr *ah, sector_t lba)
88{
89 ah->lba0 = lba;
90 ah->lba1 = lba >>= 8;
91 ah->lba2 = lba >>= 8;
92 ah->lba3 = lba >>= 8;
93 ah->lba4 = lba >>= 8;
94 ah->lba5 = lba >>= 8;
95}
96
86static void 97static void
87aoecmd_ata_rw(struct aoedev *d, struct frame *f) 98aoecmd_ata_rw(struct aoedev *d, struct frame *f)
88{ 99{
@@ -101,8 +112,8 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
101 112
102 sector = buf->sector; 113 sector = buf->sector;
103 bcnt = buf->bv_resid; 114 bcnt = buf->bv_resid;
104 if (bcnt > MAXATADATA) 115 if (bcnt > d->maxbcnt)
105 bcnt = MAXATADATA; 116 bcnt = d->maxbcnt;
106 117
107 /* initialize the headers & frame */ 118 /* initialize the headers & frame */
108 skb = f->skb; 119 skb = f->skb;
@@ -114,17 +125,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
114 f->waited = 0; 125 f->waited = 0;
115 f->buf = buf; 126 f->buf = buf;
116 f->bufaddr = buf->bufaddr; 127 f->bufaddr = buf->bufaddr;
128 f->bcnt = bcnt;
129 f->lba = sector;
117 130
118 /* set up ata header */ 131 /* set up ata header */
119 ah->scnt = bcnt >> 9; 132 ah->scnt = bcnt >> 9;
120 ah->lba0 = sector; 133 put_lba(ah, sector);
121 ah->lba1 = sector >>= 8;
122 ah->lba2 = sector >>= 8;
123 ah->lba3 = sector >>= 8;
124 if (d->flags & DEVFL_EXT) { 134 if (d->flags & DEVFL_EXT) {
125 ah->aflags |= AOEAFL_EXT; 135 ah->aflags |= AOEAFL_EXT;
126 ah->lba4 = sector >>= 8;
127 ah->lba5 = sector >>= 8;
128 } else { 136 } else {
129 extbit = 0; 137 extbit = 0;
130 ah->lba3 &= 0x0f; 138 ah->lba3 &= 0x0f;
@@ -251,6 +259,7 @@ rexmit(struct aoedev *d, struct frame *f)
251{ 259{
252 struct sk_buff *skb; 260 struct sk_buff *skb;
253 struct aoe_hdr *h; 261 struct aoe_hdr *h;
262 struct aoe_atahdr *ah;
254 char buf[128]; 263 char buf[128];
255 u32 n; 264 u32 n;
256 265
@@ -264,11 +273,27 @@ rexmit(struct aoedev *d, struct frame *f)
264 273
265 skb = f->skb; 274 skb = f->skb;
266 h = (struct aoe_hdr *) skb->mac.raw; 275 h = (struct aoe_hdr *) skb->mac.raw;
276 ah = (struct aoe_atahdr *) (h+1);
267 f->tag = n; 277 f->tag = n;
268 h->tag = cpu_to_be32(n); 278 h->tag = cpu_to_be32(n);
269 memcpy(h->dst, d->addr, sizeof h->dst); 279 memcpy(h->dst, d->addr, sizeof h->dst);
270 memcpy(h->src, d->ifp->dev_addr, sizeof h->src); 280 memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
271 281
282 n = DEFAULTBCNT / 512;
283 if (ah->scnt > n) {
284 ah->scnt = n;
285 if (ah->aflags & AOEAFL_WRITE)
286 skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
287 offset_in_page(f->bufaddr), DEFAULTBCNT);
288 if (++d->lostjumbo > (d->nframes << 1))
289 if (d->maxbcnt != DEFAULTBCNT) {
290 printk(KERN_INFO "aoe: rexmit: too many lost jumbo. "
291 "dropping back to 1KB frames.\n");
292 d->maxbcnt = DEFAULTBCNT;
293 d->flags |= DEVFL_MAXBCNT;
294 }
295 }
296
272 skb->dev = d->ifp; 297 skb->dev = d->ifp;
273 skb_get(skb); 298 skb_get(skb);
274 skb->next = NULL; 299 skb->next = NULL;
@@ -506,10 +531,10 @@ aoecmd_ata_rsp(struct sk_buff *skb)
506 if (buf) 531 if (buf)
507 buf->flags |= BUFFL_FAIL; 532 buf->flags |= BUFFL_FAIL;
508 } else { 533 } else {
534 n = ahout->scnt << 9;
509 switch (ahout->cmdstat) { 535 switch (ahout->cmdstat) {
510 case WIN_READ: 536 case WIN_READ:
511 case WIN_READ_EXT: 537 case WIN_READ_EXT:
512 n = ahout->scnt << 9;
513 if (skb->len - sizeof *hin - sizeof *ahin < n) { 538 if (skb->len - sizeof *hin - sizeof *ahin < n) {
514 printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " 539 printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
515 "ata data size in read. skb->len=%d\n", 540 "ata data size in read. skb->len=%d\n",
@@ -521,6 +546,22 @@ aoecmd_ata_rsp(struct sk_buff *skb)
521 memcpy(f->bufaddr, ahin+1, n); 546 memcpy(f->bufaddr, ahin+1, n);
522 case WIN_WRITE: 547 case WIN_WRITE:
523 case WIN_WRITE_EXT: 548 case WIN_WRITE_EXT:
549 if (f->bcnt -= n) {
550 f->bufaddr += n;
551 put_lba(ahout, f->lba += ahout->scnt);
552 n = f->bcnt > DEFAULTBCNT ? DEFAULTBCNT : f->bcnt;
553 ahout->scnt = n >> 9;
554 if (ahout->aflags & AOEAFL_WRITE)
555 skb_fill_page_desc(f->skb, 0, virt_to_page(f->bufaddr),
556 offset_in_page(f->bufaddr), n);
557 skb_get(f->skb);
558 f->skb->next = NULL;
559 spin_unlock_irqrestore(&d->lock, flags);
560 aoenet_xmit(f->skb);
561 return;
562 }
563 if (n > DEFAULTBCNT)
564 d->lostjumbo = 0;
524 break; 565 break;
525 case WIN_IDENTIFY: 566 case WIN_IDENTIFY:
526 if (skb->len - sizeof *hin - sizeof *ahin < 512) { 567 if (skb->len - sizeof *hin - sizeof *ahin < 512) {
@@ -628,9 +669,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
628 struct aoe_hdr *h; 669 struct aoe_hdr *h;
629 struct aoe_cfghdr *ch; 670 struct aoe_cfghdr *ch;
630 ulong flags, sysminor, aoemajor; 671 ulong flags, sysminor, aoemajor;
631 u16 bufcnt;
632 struct sk_buff *sl; 672 struct sk_buff *sl;
633 enum { MAXFRAMES = 16 }; 673 enum { MAXFRAMES = 16 };
674 u16 n;
634 675
635 h = (struct aoe_hdr *) skb->mac.raw; 676 h = (struct aoe_hdr *) skb->mac.raw;
636 ch = (struct aoe_cfghdr *) (h+1); 677 ch = (struct aoe_cfghdr *) (h+1);
@@ -654,11 +695,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
654 return; 695 return;
655 } 696 }
656 697
657 bufcnt = be16_to_cpu(ch->bufcnt); 698 n = be16_to_cpu(ch->bufcnt);
658 if (bufcnt > MAXFRAMES) /* keep it reasonable */ 699 if (n > MAXFRAMES) /* keep it reasonable */
659 bufcnt = MAXFRAMES; 700 n = MAXFRAMES;
660 701
661 d = aoedev_by_sysminor_m(sysminor, bufcnt); 702 d = aoedev_by_sysminor_m(sysminor, n);
662 if (d == NULL) { 703 if (d == NULL) {
663 printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); 704 printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");
664 return; 705 return;
@@ -669,6 +710,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
669 /* permit device to migrate mac and network interface */ 710 /* permit device to migrate mac and network interface */
670 d->ifp = skb->dev; 711 d->ifp = skb->dev;
671 memcpy(d->addr, h->src, sizeof d->addr); 712 memcpy(d->addr, h->src, sizeof d->addr);
713 if (!(d->flags & DEVFL_MAXBCNT)) {
714 n = d->ifp->mtu;
715 n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr);
716 n /= 512;
717 if (n > ch->scnt)
718 n = ch->scnt;
719 d->maxbcnt = n ? n * 512 : DEFAULTBCNT;
720 }
672 721
673 /* don't change users' perspective */ 722 /* don't change users' perspective */
674 if (d->nopen && !(d->flags & DEVFL_PAUSE)) { 723 if (d->nopen && !(d->flags & DEVFL_PAUSE)) {