Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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];
};
@@ -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,
@@ -107,6 +108,8 @@ struct frame {
	ulong waited;
	struct buf *buf;
	char *bufaddr;
	ulong bcnt;
	sector_t lba;
	struct sk_buff *skb;
};

@@ -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;
@@ -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;
};

+1 −0
Original line number Diff line number Diff line
@@ -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);
+63 −14
Original line number Diff line number Diff line
@@ -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)
{
@@ -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;
@@ -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;
@@ -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;

@@ -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;
@@ -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",
@@ -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) {
@@ -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);
@@ -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;
@@ -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)) {