Commit 19bf2635 authored by Ed L. Cashin's avatar Ed L. Cashin Committed by Greg Kroah-Hartman

aoe: jumbo frame support 1 of 2

Add support for jumbo ethernet frames.
(This patch depends on patch 7 to follow.)
Signed-off-by: default avatar"Ed L. Cashin" <ecashin@coraid.com>
Acked-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e407a7f6
...@@ -65,7 +65,7 @@ struct aoe_atahdr { ...@@ -65,7 +65,7 @@ struct aoe_atahdr {
struct aoe_cfghdr { struct aoe_cfghdr {
__be16 bufcnt; __be16 bufcnt;
__be16 fwver; __be16 fwver;
unsigned char res; unsigned char scnt;
unsigned char aoeccmd; unsigned char aoeccmd;
unsigned char cslen[2]; unsigned char cslen[2];
}; };
...@@ -78,12 +78,13 @@ enum { ...@@ -78,12 +78,13 @@ enum {
DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */
DEVFL_PAUSE = (1<<5), DEVFL_PAUSE = (1<<5),
DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */
BUFFL_FAIL = 1, BUFFL_FAIL = 1,
}; };
enum { enum {
MAXATADATA = 1024, DEFAULTBCNT = 2 * 512, /* 2 sectors */
NPERSHELF = 16, /* number of slots per shelf address */ NPERSHELF = 16, /* number of slots per shelf address */
FREETAG = -1, FREETAG = -1,
MIN_BUFS = 8, MIN_BUFS = 8,
...@@ -107,6 +108,8 @@ struct frame { ...@@ -107,6 +108,8 @@ struct frame {
ulong waited; ulong waited;
struct buf *buf; struct buf *buf;
char *bufaddr; char *bufaddr;
ulong bcnt;
sector_t lba;
struct sk_buff *skb; struct sk_buff *skb;
}; };
...@@ -120,6 +123,7 @@ struct aoedev { ...@@ -120,6 +123,7 @@ struct aoedev {
ulong nopen; /* (bd_openers isn't available without sleeping) */ ulong nopen; /* (bd_openers isn't available without sleeping) */
ulong rttavg; /* round trip average of requests/responses */ ulong rttavg; /* round trip average of requests/responses */
u16 fw_ver; /* version of blade's firmware */ u16 fw_ver; /* version of blade's firmware */
u16 maxbcnt;
struct work_struct work;/* disk create work struct */ struct work_struct work;/* disk create work struct */
struct gendisk *gd; struct gendisk *gd;
request_queue_t blkq; request_queue_t blkq;
...@@ -134,7 +138,8 @@ struct aoedev { ...@@ -134,7 +138,8 @@ struct aoedev {
struct list_head bufq; /* queue of bios to work on */ struct list_head bufq; /* queue of bios to work on */
struct buf *inprocess; /* the one we're currently working on */ struct buf *inprocess; /* the one we're currently working on */
ulong lasttag; /* last tag sent */ ulong lasttag; /* last tag sent */
ulong nframes; /* number of frames below */ ushort lostjumbo;
ushort nframes; /* number of frames below */
struct frame *frames; struct frame *frames;
}; };
......
...@@ -89,6 +89,7 @@ revalidate(const char __user *str, size_t size) ...@@ -89,6 +89,7 @@ revalidate(const char __user *str, size_t size)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&d->lock, flags); spin_lock_irqsave(&d->lock, flags);
d->flags &= ~DEVFL_MAXBCNT;
d->flags |= DEVFL_PAUSE; d->flags |= DEVFL_PAUSE;
spin_unlock_irqrestore(&d->lock, flags); spin_unlock_irqrestore(&d->lock, flags);
aoecmd_cfg(major, minor); aoecmd_cfg(major, minor);
......
...@@ -83,6 +83,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) ...@@ -83,6 +83,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h)
return host_tag; return host_tag;
} }
static inline void
put_lba(struct aoe_atahdr *ah, sector_t lba)
{
ah->lba0 = lba;
ah->lba1 = lba >>= 8;
ah->lba2 = lba >>= 8;
ah->lba3 = lba >>= 8;
ah->lba4 = lba >>= 8;
ah->lba5 = lba >>= 8;
}
static void static void
aoecmd_ata_rw(struct aoedev *d, struct frame *f) aoecmd_ata_rw(struct aoedev *d, struct frame *f)
{ {
...@@ -101,8 +112,8 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) ...@@ -101,8 +112,8 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
sector = buf->sector; sector = buf->sector;
bcnt = buf->bv_resid; bcnt = buf->bv_resid;
if (bcnt > MAXATADATA) if (bcnt > d->maxbcnt)
bcnt = MAXATADATA; bcnt = d->maxbcnt;
/* initialize the headers & frame */ /* initialize the headers & frame */
skb = f->skb; skb = f->skb;
...@@ -114,17 +125,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) ...@@ -114,17 +125,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
f->waited = 0; f->waited = 0;
f->buf = buf; f->buf = buf;
f->bufaddr = buf->bufaddr; f->bufaddr = buf->bufaddr;
f->bcnt = bcnt;
f->lba = sector;
/* set up ata header */ /* set up ata header */
ah->scnt = bcnt >> 9; ah->scnt = bcnt >> 9;
ah->lba0 = sector; put_lba(ah, sector);
ah->lba1 = sector >>= 8;
ah->lba2 = sector >>= 8;
ah->lba3 = sector >>= 8;
if (d->flags & DEVFL_EXT) { if (d->flags & DEVFL_EXT) {
ah->aflags |= AOEAFL_EXT; ah->aflags |= AOEAFL_EXT;
ah->lba4 = sector >>= 8;
ah->lba5 = sector >>= 8;
} else { } else {
extbit = 0; extbit = 0;
ah->lba3 &= 0x0f; ah->lba3 &= 0x0f;
...@@ -251,6 +259,7 @@ rexmit(struct aoedev *d, struct frame *f) ...@@ -251,6 +259,7 @@ rexmit(struct aoedev *d, struct frame *f)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct aoe_hdr *h; struct aoe_hdr *h;
struct aoe_atahdr *ah;
char buf[128]; char buf[128];
u32 n; u32 n;
...@@ -264,11 +273,27 @@ rexmit(struct aoedev *d, struct frame *f) ...@@ -264,11 +273,27 @@ rexmit(struct aoedev *d, struct frame *f)
skb = f->skb; skb = f->skb;
h = (struct aoe_hdr *) skb->mac.raw; h = (struct aoe_hdr *) skb->mac.raw;
ah = (struct aoe_atahdr *) (h+1);
f->tag = n; f->tag = n;
h->tag = cpu_to_be32(n); h->tag = cpu_to_be32(n);
memcpy(h->dst, d->addr, sizeof h->dst); memcpy(h->dst, d->addr, sizeof h->dst);
memcpy(h->src, d->ifp->dev_addr, sizeof h->src); memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
n = DEFAULTBCNT / 512;
if (ah->scnt > n) {
ah->scnt = n;
if (ah->aflags & AOEAFL_WRITE)
skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
offset_in_page(f->bufaddr), DEFAULTBCNT);
if (++d->lostjumbo > (d->nframes << 1))
if (d->maxbcnt != DEFAULTBCNT) {
printk(KERN_INFO "aoe: rexmit: too many lost jumbo. "
"dropping back to 1KB frames.\n");
d->maxbcnt = DEFAULTBCNT;
d->flags |= DEVFL_MAXBCNT;
}
}
skb->dev = d->ifp; skb->dev = d->ifp;
skb_get(skb); skb_get(skb);
skb->next = NULL; skb->next = NULL;
...@@ -506,10 +531,10 @@ aoecmd_ata_rsp(struct sk_buff *skb) ...@@ -506,10 +531,10 @@ aoecmd_ata_rsp(struct sk_buff *skb)
if (buf) if (buf)
buf->flags |= BUFFL_FAIL; buf->flags |= BUFFL_FAIL;
} else { } else {
n = ahout->scnt << 9;
switch (ahout->cmdstat) { switch (ahout->cmdstat) {
case WIN_READ: case WIN_READ:
case WIN_READ_EXT: case WIN_READ_EXT:
n = ahout->scnt << 9;
if (skb->len - sizeof *hin - sizeof *ahin < n) { if (skb->len - sizeof *hin - sizeof *ahin < n) {
printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
"ata data size in read. skb->len=%d\n", "ata data size in read. skb->len=%d\n",
...@@ -521,6 +546,22 @@ aoecmd_ata_rsp(struct sk_buff *skb) ...@@ -521,6 +546,22 @@ aoecmd_ata_rsp(struct sk_buff *skb)
memcpy(f->bufaddr, ahin+1, n); memcpy(f->bufaddr, ahin+1, n);
case WIN_WRITE: case WIN_WRITE:
case WIN_WRITE_EXT: case WIN_WRITE_EXT:
if (f->bcnt -= n) {
f->bufaddr += n;
put_lba(ahout, f->lba += ahout->scnt);
n = f->bcnt > DEFAULTBCNT ? DEFAULTBCNT : f->bcnt;
ahout->scnt = n >> 9;
if (ahout->aflags & AOEAFL_WRITE)
skb_fill_page_desc(f->skb, 0, virt_to_page(f->bufaddr),
offset_in_page(f->bufaddr), n);
skb_get(f->skb);
f->skb->next = NULL;
spin_unlock_irqrestore(&d->lock, flags);
aoenet_xmit(f->skb);
return;
}
if (n > DEFAULTBCNT)
d->lostjumbo = 0;
break; break;
case WIN_IDENTIFY: case WIN_IDENTIFY:
if (skb->len - sizeof *hin - sizeof *ahin < 512) { if (skb->len - sizeof *hin - sizeof *ahin < 512) {
...@@ -628,9 +669,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb) ...@@ -628,9 +669,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
struct aoe_hdr *h; struct aoe_hdr *h;
struct aoe_cfghdr *ch; struct aoe_cfghdr *ch;
ulong flags, sysminor, aoemajor; ulong flags, sysminor, aoemajor;
u16 bufcnt;
struct sk_buff *sl; struct sk_buff *sl;
enum { MAXFRAMES = 16 }; enum { MAXFRAMES = 16 };
u16 n;
h = (struct aoe_hdr *) skb->mac.raw; h = (struct aoe_hdr *) skb->mac.raw;
ch = (struct aoe_cfghdr *) (h+1); ch = (struct aoe_cfghdr *) (h+1);
...@@ -654,11 +695,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb) ...@@ -654,11 +695,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
return; return;
} }
bufcnt = be16_to_cpu(ch->bufcnt); n = be16_to_cpu(ch->bufcnt);
if (bufcnt > MAXFRAMES) /* keep it reasonable */ if (n > MAXFRAMES) /* keep it reasonable */
bufcnt = MAXFRAMES; n = MAXFRAMES;
d = aoedev_by_sysminor_m(sysminor, bufcnt); d = aoedev_by_sysminor_m(sysminor, n);
if (d == NULL) { if (d == NULL) {
printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");
return; return;
...@@ -669,6 +710,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb) ...@@ -669,6 +710,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
/* permit device to migrate mac and network interface */ /* permit device to migrate mac and network interface */
d->ifp = skb->dev; d->ifp = skb->dev;
memcpy(d->addr, h->src, sizeof d->addr); memcpy(d->addr, h->src, sizeof d->addr);
if (!(d->flags & DEVFL_MAXBCNT)) {
n = d->ifp->mtu;
n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr);
n /= 512;
if (n > ch->scnt)
n = ch->scnt;
d->maxbcnt = n ? n * 512 : DEFAULTBCNT;
}
/* don't change users' perspective */ /* don't change users' perspective */
if (d->nopen && !(d->flags & DEVFL_PAUSE)) { if (d->nopen && !(d->flags & DEVFL_PAUSE)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment