diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/aoe/aoe.h | 11 | ||||
-rw-r--r-- | drivers/block/aoe/aoechr.c | 1 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 77 |
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 { | |||
65 | struct aoe_cfghdr { | 65 | struct 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 | ||
85 | enum { | 86 | enum { |
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 | ||
86 | static inline void | ||
87 | put_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 | |||
86 | static void | 97 | static void |
87 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 98 | aoecmd_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)) { |