Skip to content

Commit

Permalink
aoe: jumbo frame support 1 of 2
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ed L. Cashin authored and Greg Kroah-Hartman committed Oct 18, 2006
1 parent e407a7f commit 19bf263
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 17 deletions.
11 changes: 8 additions & 3 deletions drivers/block/aoe/aoe.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct aoe_atahdr {
struct aoe_cfghdr {
__be16 bufcnt;
__be16 fwver;
unsigned char res;
unsigned char scnt;
unsigned char aoeccmd;
unsigned char cslen[2];
};
Expand All @@ -78,12 +78,13 @@ enum {
DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */
DEVFL_PAUSE = (1<<5),
DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */

BUFFL_FAIL = 1,
};

enum {
MAXATADATA = 1024,
DEFAULTBCNT = 2 * 512, /* 2 sectors */
NPERSHELF = 16, /* number of slots per shelf address */
FREETAG = -1,
MIN_BUFS = 8,
Expand All @@ -107,6 +108,8 @@ struct frame {
ulong waited;
struct buf *buf;
char *bufaddr;
ulong bcnt;
sector_t lba;
struct sk_buff *skb;
};

Expand All @@ -120,6 +123,7 @@ struct aoedev {
ulong nopen; /* (bd_openers isn't available without sleeping) */
ulong rttavg; /* round trip average of requests/responses */
u16 fw_ver; /* version of blade's firmware */
u16 maxbcnt;
struct work_struct work;/* disk create work struct */
struct gendisk *gd;
request_queue_t blkq;
Expand All @@ -134,7 +138,8 @@ struct aoedev {
struct list_head bufq; /* queue of bios to work on */
struct buf *inprocess; /* the one we're currently working on */
ulong lasttag; /* last tag sent */
ulong nframes; /* number of frames below */
ushort lostjumbo;
ushort nframes; /* number of frames below */
struct frame *frames;
};

Expand Down
1 change: 1 addition & 0 deletions drivers/block/aoe/aoechr.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ revalidate(const char __user *str, size_t size)
return -EINVAL;

spin_lock_irqsave(&d->lock, flags);
d->flags &= ~DEVFL_MAXBCNT;
d->flags |= DEVFL_PAUSE;
spin_unlock_irqrestore(&d->lock, flags);
aoecmd_cfg(major, minor);
Expand Down
77 changes: 63 additions & 14 deletions drivers/block/aoe/aoecmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h)
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
aoecmd_ata_rw(struct aoedev *d, struct frame *f)
{
Expand All @@ -101,8 +112,8 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)

sector = buf->sector;
bcnt = buf->bv_resid;
if (bcnt > MAXATADATA)
bcnt = MAXATADATA;
if (bcnt > d->maxbcnt)
bcnt = d->maxbcnt;

/* initialize the headers & frame */
skb = f->skb;
Expand All @@ -114,17 +125,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
f->waited = 0;
f->buf = buf;
f->bufaddr = buf->bufaddr;
f->bcnt = bcnt;
f->lba = sector;

/* set up ata header */
ah->scnt = bcnt >> 9;
ah->lba0 = sector;
ah->lba1 = sector >>= 8;
ah->lba2 = sector >>= 8;
ah->lba3 = sector >>= 8;
put_lba(ah, sector);
if (d->flags & DEVFL_EXT) {
ah->aflags |= AOEAFL_EXT;
ah->lba4 = sector >>= 8;
ah->lba5 = sector >>= 8;
} else {
extbit = 0;
ah->lba3 &= 0x0f;
Expand Down Expand Up @@ -251,6 +259,7 @@ rexmit(struct aoedev *d, struct frame *f)
{
struct sk_buff *skb;
struct aoe_hdr *h;
struct aoe_atahdr *ah;
char buf[128];
u32 n;

Expand All @@ -264,11 +273,27 @@ rexmit(struct aoedev *d, struct frame *f)

skb = f->skb;
h = (struct aoe_hdr *) skb->mac.raw;
ah = (struct aoe_atahdr *) (h+1);
f->tag = n;
h->tag = cpu_to_be32(n);
memcpy(h->dst, d->addr, sizeof h->dst);
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_get(skb);
skb->next = NULL;
Expand Down Expand Up @@ -506,10 +531,10 @@ aoecmd_ata_rsp(struct sk_buff *skb)
if (buf)
buf->flags |= BUFFL_FAIL;
} else {
n = ahout->scnt << 9;
switch (ahout->cmdstat) {
case WIN_READ:
case WIN_READ_EXT:
n = ahout->scnt << 9;
if (skb->len - sizeof *hin - sizeof *ahin < n) {
printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
"ata data size in read. skb->len=%d\n",
Expand All @@ -521,6 +546,22 @@ aoecmd_ata_rsp(struct sk_buff *skb)
memcpy(f->bufaddr, ahin+1, n);
case WIN_WRITE:
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;
case WIN_IDENTIFY:
if (skb->len - sizeof *hin - sizeof *ahin < 512) {
Expand Down Expand Up @@ -628,9 +669,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
struct aoe_hdr *h;
struct aoe_cfghdr *ch;
ulong flags, sysminor, aoemajor;
u16 bufcnt;
struct sk_buff *sl;
enum { MAXFRAMES = 16 };
u16 n;

h = (struct aoe_hdr *) skb->mac.raw;
ch = (struct aoe_cfghdr *) (h+1);
Expand All @@ -654,11 +695,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
return;
}

bufcnt = be16_to_cpu(ch->bufcnt);
if (bufcnt > MAXFRAMES) /* keep it reasonable */
bufcnt = MAXFRAMES;
n = be16_to_cpu(ch->bufcnt);
if (n > MAXFRAMES) /* keep it reasonable */
n = MAXFRAMES;

d = aoedev_by_sysminor_m(sysminor, bufcnt);
d = aoedev_by_sysminor_m(sysminor, n);
if (d == NULL) {
printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");
return;
Expand All @@ -669,6 +710,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
/* permit device to migrate mac and network interface */
d->ifp = skb->dev;
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 */
if (d->nopen && !(d->flags & DEVFL_PAUSE)) {
Expand Down

0 comments on commit 19bf263

Please sign in to comment.