xref: /openbmc/linux/drivers/block/aoe/aoecmd.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
2*1da177e4SLinus Torvalds /*
3*1da177e4SLinus Torvalds  * aoecmd.c
4*1da177e4SLinus Torvalds  * Filesystem request handling methods
5*1da177e4SLinus Torvalds  */
6*1da177e4SLinus Torvalds 
7*1da177e4SLinus Torvalds #include <linux/hdreg.h>
8*1da177e4SLinus Torvalds #include <linux/blkdev.h>
9*1da177e4SLinus Torvalds #include <linux/skbuff.h>
10*1da177e4SLinus Torvalds #include <linux/netdevice.h>
11*1da177e4SLinus Torvalds #include "aoe.h"
12*1da177e4SLinus Torvalds 
13*1da177e4SLinus Torvalds #define TIMERTICK (HZ / 10)
14*1da177e4SLinus Torvalds #define MINTIMER (2 * TIMERTICK)
15*1da177e4SLinus Torvalds #define MAXTIMER (HZ << 1)
16*1da177e4SLinus Torvalds #define MAXWAIT (60 * 3)	/* After MAXWAIT seconds, give up and fail dev */
17*1da177e4SLinus Torvalds 
18*1da177e4SLinus Torvalds static struct sk_buff *
19*1da177e4SLinus Torvalds new_skb(struct net_device *if_dev, ulong len)
20*1da177e4SLinus Torvalds {
21*1da177e4SLinus Torvalds 	struct sk_buff *skb;
22*1da177e4SLinus Torvalds 
23*1da177e4SLinus Torvalds 	skb = alloc_skb(len, GFP_ATOMIC);
24*1da177e4SLinus Torvalds 	if (skb) {
25*1da177e4SLinus Torvalds 		skb->nh.raw = skb->mac.raw = skb->data;
26*1da177e4SLinus Torvalds 		skb->dev = if_dev;
27*1da177e4SLinus Torvalds 		skb->protocol = __constant_htons(ETH_P_AOE);
28*1da177e4SLinus Torvalds 		skb->priority = 0;
29*1da177e4SLinus Torvalds 		skb_put(skb, len);
30*1da177e4SLinus Torvalds 		skb->next = skb->prev = NULL;
31*1da177e4SLinus Torvalds 
32*1da177e4SLinus Torvalds 		/* tell the network layer not to perform IP checksums
33*1da177e4SLinus Torvalds 		 * or to get the NIC to do it
34*1da177e4SLinus Torvalds 		 */
35*1da177e4SLinus Torvalds 		skb->ip_summed = CHECKSUM_NONE;
36*1da177e4SLinus Torvalds 	}
37*1da177e4SLinus Torvalds 	return skb;
38*1da177e4SLinus Torvalds }
39*1da177e4SLinus Torvalds 
40*1da177e4SLinus Torvalds static struct sk_buff *
41*1da177e4SLinus Torvalds skb_prepare(struct aoedev *d, struct frame *f)
42*1da177e4SLinus Torvalds {
43*1da177e4SLinus Torvalds 	struct sk_buff *skb;
44*1da177e4SLinus Torvalds 	char *p;
45*1da177e4SLinus Torvalds 
46*1da177e4SLinus Torvalds 	skb = new_skb(d->ifp, f->ndata + f->writedatalen);
47*1da177e4SLinus Torvalds 	if (!skb) {
48*1da177e4SLinus Torvalds 		printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n");
49*1da177e4SLinus Torvalds 		return NULL;
50*1da177e4SLinus Torvalds 	}
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds 	p = skb->mac.raw;
53*1da177e4SLinus Torvalds 	memcpy(p, f->data, f->ndata);
54*1da177e4SLinus Torvalds 
55*1da177e4SLinus Torvalds 	if (f->writedatalen) {
56*1da177e4SLinus Torvalds 		p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
57*1da177e4SLinus Torvalds 		memcpy(p, f->bufaddr, f->writedatalen);
58*1da177e4SLinus Torvalds 	}
59*1da177e4SLinus Torvalds 
60*1da177e4SLinus Torvalds 	return skb;
61*1da177e4SLinus Torvalds }
62*1da177e4SLinus Torvalds 
63*1da177e4SLinus Torvalds static struct frame *
64*1da177e4SLinus Torvalds getframe(struct aoedev *d, int tag)
65*1da177e4SLinus Torvalds {
66*1da177e4SLinus Torvalds 	struct frame *f, *e;
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds 	f = d->frames;
69*1da177e4SLinus Torvalds 	e = f + d->nframes;
70*1da177e4SLinus Torvalds 	for (; f<e; f++)
71*1da177e4SLinus Torvalds 		if (f->tag == tag)
72*1da177e4SLinus Torvalds 			return f;
73*1da177e4SLinus Torvalds 	return NULL;
74*1da177e4SLinus Torvalds }
75*1da177e4SLinus Torvalds 
76*1da177e4SLinus Torvalds /*
77*1da177e4SLinus Torvalds  * Leave the top bit clear so we have tagspace for userland.
78*1da177e4SLinus Torvalds  * The bottom 16 bits are the xmit tick for rexmit/rttavg processing.
79*1da177e4SLinus Torvalds  * This driver reserves tag -1 to mean "unused frame."
80*1da177e4SLinus Torvalds  */
81*1da177e4SLinus Torvalds static int
82*1da177e4SLinus Torvalds newtag(struct aoedev *d)
83*1da177e4SLinus Torvalds {
84*1da177e4SLinus Torvalds 	register ulong n;
85*1da177e4SLinus Torvalds 
86*1da177e4SLinus Torvalds 	n = jiffies & 0xffff;
87*1da177e4SLinus Torvalds 	return n |= (++d->lasttag & 0x7fff) << 16;
88*1da177e4SLinus Torvalds }
89*1da177e4SLinus Torvalds 
90*1da177e4SLinus Torvalds static int
91*1da177e4SLinus Torvalds aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h)
92*1da177e4SLinus Torvalds {
93*1da177e4SLinus Torvalds 	u16 type = __constant_cpu_to_be16(ETH_P_AOE);
94*1da177e4SLinus Torvalds 	u16 aoemajor = __cpu_to_be16(d->aoemajor);
95*1da177e4SLinus Torvalds 	u32 host_tag = newtag(d);
96*1da177e4SLinus Torvalds 	u32 tag = __cpu_to_be32(host_tag);
97*1da177e4SLinus Torvalds 
98*1da177e4SLinus Torvalds 	memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
99*1da177e4SLinus Torvalds 	memcpy(h->dst, d->addr, sizeof h->dst);
100*1da177e4SLinus Torvalds 	memcpy(h->type, &type, sizeof type);
101*1da177e4SLinus Torvalds 	h->verfl = AOE_HVER;
102*1da177e4SLinus Torvalds 	memcpy(h->major, &aoemajor, sizeof aoemajor);
103*1da177e4SLinus Torvalds 	h->minor = d->aoeminor;
104*1da177e4SLinus Torvalds 	h->cmd = AOECMD_ATA;
105*1da177e4SLinus Torvalds 	memcpy(h->tag, &tag, sizeof tag);
106*1da177e4SLinus Torvalds 
107*1da177e4SLinus Torvalds 	return host_tag;
108*1da177e4SLinus Torvalds }
109*1da177e4SLinus Torvalds 
110*1da177e4SLinus Torvalds static void
111*1da177e4SLinus Torvalds aoecmd_ata_rw(struct aoedev *d, struct frame *f)
112*1da177e4SLinus Torvalds {
113*1da177e4SLinus Torvalds 	struct aoe_hdr *h;
114*1da177e4SLinus Torvalds 	struct aoe_atahdr *ah;
115*1da177e4SLinus Torvalds 	struct buf *buf;
116*1da177e4SLinus Torvalds 	struct sk_buff *skb;
117*1da177e4SLinus Torvalds 	ulong bcnt;
118*1da177e4SLinus Torvalds 	register sector_t sector;
119*1da177e4SLinus Torvalds 	char writebit, extbit;
120*1da177e4SLinus Torvalds 
121*1da177e4SLinus Torvalds 	writebit = 0x10;
122*1da177e4SLinus Torvalds 	extbit = 0x4;
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds 	buf = d->inprocess;
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds 	sector = buf->sector;
127*1da177e4SLinus Torvalds 	bcnt = buf->bv_resid;
128*1da177e4SLinus Torvalds 	if (bcnt > MAXATADATA)
129*1da177e4SLinus Torvalds 		bcnt = MAXATADATA;
130*1da177e4SLinus Torvalds 
131*1da177e4SLinus Torvalds 	/* initialize the headers & frame */
132*1da177e4SLinus Torvalds 	h = (struct aoe_hdr *) f->data;
133*1da177e4SLinus Torvalds 	ah = (struct aoe_atahdr *) (h+1);
134*1da177e4SLinus Torvalds 	f->ndata = sizeof *h + sizeof *ah;
135*1da177e4SLinus Torvalds 	memset(h, 0, f->ndata);
136*1da177e4SLinus Torvalds 	f->tag = aoehdr_atainit(d, h);
137*1da177e4SLinus Torvalds 	f->waited = 0;
138*1da177e4SLinus Torvalds 	f->buf = buf;
139*1da177e4SLinus Torvalds 	f->bufaddr = buf->bufaddr;
140*1da177e4SLinus Torvalds 
141*1da177e4SLinus Torvalds 	/* set up ata header */
142*1da177e4SLinus Torvalds 	ah->scnt = bcnt >> 9;
143*1da177e4SLinus Torvalds 	ah->lba0 = sector;
144*1da177e4SLinus Torvalds 	ah->lba1 = sector >>= 8;
145*1da177e4SLinus Torvalds 	ah->lba2 = sector >>= 8;
146*1da177e4SLinus Torvalds 	ah->lba3 = sector >>= 8;
147*1da177e4SLinus Torvalds 	if (d->flags & DEVFL_EXT) {
148*1da177e4SLinus Torvalds 		ah->aflags |= AOEAFL_EXT;
149*1da177e4SLinus Torvalds 		ah->lba4 = sector >>= 8;
150*1da177e4SLinus Torvalds 		ah->lba5 = sector >>= 8;
151*1da177e4SLinus Torvalds 	} else {
152*1da177e4SLinus Torvalds 		extbit = 0;
153*1da177e4SLinus Torvalds 		ah->lba3 &= 0x0f;
154*1da177e4SLinus Torvalds 		ah->lba3 |= 0xe0;	/* LBA bit + obsolete 0xa0 */
155*1da177e4SLinus Torvalds 	}
156*1da177e4SLinus Torvalds 
157*1da177e4SLinus Torvalds 	if (bio_data_dir(buf->bio) == WRITE) {
158*1da177e4SLinus Torvalds 		ah->aflags |= AOEAFL_WRITE;
159*1da177e4SLinus Torvalds 		f->writedatalen = bcnt;
160*1da177e4SLinus Torvalds 	} else {
161*1da177e4SLinus Torvalds 		writebit = 0;
162*1da177e4SLinus Torvalds 		f->writedatalen = 0;
163*1da177e4SLinus Torvalds 	}
164*1da177e4SLinus Torvalds 
165*1da177e4SLinus Torvalds 	ah->cmdstat = WIN_READ | writebit | extbit;
166*1da177e4SLinus Torvalds 
167*1da177e4SLinus Torvalds 	/* mark all tracking fields and load out */
168*1da177e4SLinus Torvalds 	buf->nframesout += 1;
169*1da177e4SLinus Torvalds 	buf->bufaddr += bcnt;
170*1da177e4SLinus Torvalds 	buf->bv_resid -= bcnt;
171*1da177e4SLinus Torvalds /* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */
172*1da177e4SLinus Torvalds 	buf->resid -= bcnt;
173*1da177e4SLinus Torvalds 	buf->sector += bcnt >> 9;
174*1da177e4SLinus Torvalds 	if (buf->resid == 0) {
175*1da177e4SLinus Torvalds 		d->inprocess = NULL;
176*1da177e4SLinus Torvalds 	} else if (buf->bv_resid == 0) {
177*1da177e4SLinus Torvalds 		buf->bv++;
178*1da177e4SLinus Torvalds 		buf->bv_resid = buf->bv->bv_len;
179*1da177e4SLinus Torvalds 		buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
180*1da177e4SLinus Torvalds 	}
181*1da177e4SLinus Torvalds 
182*1da177e4SLinus Torvalds 	skb = skb_prepare(d, f);
183*1da177e4SLinus Torvalds 	if (skb) {
184*1da177e4SLinus Torvalds 		skb->next = d->skblist;
185*1da177e4SLinus Torvalds 		d->skblist = skb;
186*1da177e4SLinus Torvalds 	}
187*1da177e4SLinus Torvalds }
188*1da177e4SLinus Torvalds 
189*1da177e4SLinus Torvalds /* enters with d->lock held */
190*1da177e4SLinus Torvalds void
191*1da177e4SLinus Torvalds aoecmd_work(struct aoedev *d)
192*1da177e4SLinus Torvalds {
193*1da177e4SLinus Torvalds 	struct frame *f;
194*1da177e4SLinus Torvalds 	struct buf *buf;
195*1da177e4SLinus Torvalds loop:
196*1da177e4SLinus Torvalds 	f = getframe(d, FREETAG);
197*1da177e4SLinus Torvalds 	if (f == NULL)
198*1da177e4SLinus Torvalds 		return;
199*1da177e4SLinus Torvalds 	if (d->inprocess == NULL) {
200*1da177e4SLinus Torvalds 		if (list_empty(&d->bufq))
201*1da177e4SLinus Torvalds 			return;
202*1da177e4SLinus Torvalds 		buf = container_of(d->bufq.next, struct buf, bufs);
203*1da177e4SLinus Torvalds 		list_del(d->bufq.next);
204*1da177e4SLinus Torvalds /*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */
205*1da177e4SLinus Torvalds 		d->inprocess = buf;
206*1da177e4SLinus Torvalds 	}
207*1da177e4SLinus Torvalds 	aoecmd_ata_rw(d, f);
208*1da177e4SLinus Torvalds 	goto loop;
209*1da177e4SLinus Torvalds }
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds static void
212*1da177e4SLinus Torvalds rexmit(struct aoedev *d, struct frame *f)
213*1da177e4SLinus Torvalds {
214*1da177e4SLinus Torvalds 	struct sk_buff *skb;
215*1da177e4SLinus Torvalds 	struct aoe_hdr *h;
216*1da177e4SLinus Torvalds 	char buf[128];
217*1da177e4SLinus Torvalds 	u32 n;
218*1da177e4SLinus Torvalds 	u32 net_tag;
219*1da177e4SLinus Torvalds 
220*1da177e4SLinus Torvalds 	n = newtag(d);
221*1da177e4SLinus Torvalds 
222*1da177e4SLinus Torvalds 	snprintf(buf, sizeof buf,
223*1da177e4SLinus Torvalds 		"%15s e%ld.%ld oldtag=%08x@%08lx newtag=%08x\n",
224*1da177e4SLinus Torvalds 		"retransmit",
225*1da177e4SLinus Torvalds 		d->aoemajor, d->aoeminor, f->tag, jiffies, n);
226*1da177e4SLinus Torvalds 	aoechr_error(buf);
227*1da177e4SLinus Torvalds 
228*1da177e4SLinus Torvalds 	h = (struct aoe_hdr *) f->data;
229*1da177e4SLinus Torvalds 	f->tag = n;
230*1da177e4SLinus Torvalds 	net_tag = __cpu_to_be32(n);
231*1da177e4SLinus Torvalds 	memcpy(h->tag, &net_tag, sizeof net_tag);
232*1da177e4SLinus Torvalds 
233*1da177e4SLinus Torvalds 	skb = skb_prepare(d, f);
234*1da177e4SLinus Torvalds 	if (skb) {
235*1da177e4SLinus Torvalds 		skb->next = d->skblist;
236*1da177e4SLinus Torvalds 		d->skblist = skb;
237*1da177e4SLinus Torvalds 	}
238*1da177e4SLinus Torvalds }
239*1da177e4SLinus Torvalds 
240*1da177e4SLinus Torvalds static int
241*1da177e4SLinus Torvalds tsince(int tag)
242*1da177e4SLinus Torvalds {
243*1da177e4SLinus Torvalds 	int n;
244*1da177e4SLinus Torvalds 
245*1da177e4SLinus Torvalds 	n = jiffies & 0xffff;
246*1da177e4SLinus Torvalds 	n -= tag & 0xffff;
247*1da177e4SLinus Torvalds 	if (n < 0)
248*1da177e4SLinus Torvalds 		n += 1<<16;
249*1da177e4SLinus Torvalds 	return n;
250*1da177e4SLinus Torvalds }
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds static void
253*1da177e4SLinus Torvalds rexmit_timer(ulong vp)
254*1da177e4SLinus Torvalds {
255*1da177e4SLinus Torvalds 	struct aoedev *d;
256*1da177e4SLinus Torvalds 	struct frame *f, *e;
257*1da177e4SLinus Torvalds 	struct sk_buff *sl;
258*1da177e4SLinus Torvalds 	register long timeout;
259*1da177e4SLinus Torvalds 	ulong flags, n;
260*1da177e4SLinus Torvalds 
261*1da177e4SLinus Torvalds 	d = (struct aoedev *) vp;
262*1da177e4SLinus Torvalds 	sl = NULL;
263*1da177e4SLinus Torvalds 
264*1da177e4SLinus Torvalds 	/* timeout is always ~150% of the moving average */
265*1da177e4SLinus Torvalds 	timeout = d->rttavg;
266*1da177e4SLinus Torvalds 	timeout += timeout >> 1;
267*1da177e4SLinus Torvalds 
268*1da177e4SLinus Torvalds 	spin_lock_irqsave(&d->lock, flags);
269*1da177e4SLinus Torvalds 
270*1da177e4SLinus Torvalds 	if (d->flags & DEVFL_TKILL) {
271*1da177e4SLinus Torvalds tdie:		spin_unlock_irqrestore(&d->lock, flags);
272*1da177e4SLinus Torvalds 		return;
273*1da177e4SLinus Torvalds 	}
274*1da177e4SLinus Torvalds 	f = d->frames;
275*1da177e4SLinus Torvalds 	e = f + d->nframes;
276*1da177e4SLinus Torvalds 	for (; f<e; f++) {
277*1da177e4SLinus Torvalds 		if (f->tag != FREETAG && tsince(f->tag) >= timeout) {
278*1da177e4SLinus Torvalds 			n = f->waited += timeout;
279*1da177e4SLinus Torvalds 			n /= HZ;
280*1da177e4SLinus Torvalds 			if (n > MAXWAIT) { /* waited too long.  device failure. */
281*1da177e4SLinus Torvalds 				aoedev_downdev(d);
282*1da177e4SLinus Torvalds 				goto tdie;
283*1da177e4SLinus Torvalds 			}
284*1da177e4SLinus Torvalds 			rexmit(d, f);
285*1da177e4SLinus Torvalds 		}
286*1da177e4SLinus Torvalds 	}
287*1da177e4SLinus Torvalds 
288*1da177e4SLinus Torvalds 	sl = d->skblist;
289*1da177e4SLinus Torvalds 	d->skblist = NULL;
290*1da177e4SLinus Torvalds 	if (sl) {
291*1da177e4SLinus Torvalds 		n = d->rttavg <<= 1;
292*1da177e4SLinus Torvalds 		if (n > MAXTIMER)
293*1da177e4SLinus Torvalds 			d->rttavg = MAXTIMER;
294*1da177e4SLinus Torvalds 	}
295*1da177e4SLinus Torvalds 
296*1da177e4SLinus Torvalds 	d->timer.expires = jiffies + TIMERTICK;
297*1da177e4SLinus Torvalds 	add_timer(&d->timer);
298*1da177e4SLinus Torvalds 
299*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&d->lock, flags);
300*1da177e4SLinus Torvalds 
301*1da177e4SLinus Torvalds 	aoenet_xmit(sl);
302*1da177e4SLinus Torvalds }
303*1da177e4SLinus Torvalds 
304*1da177e4SLinus Torvalds static void
305*1da177e4SLinus Torvalds ataid_complete(struct aoedev *d, unsigned char *id)
306*1da177e4SLinus Torvalds {
307*1da177e4SLinus Torvalds 	u64 ssize;
308*1da177e4SLinus Torvalds 	u16 n;
309*1da177e4SLinus Torvalds 
310*1da177e4SLinus Torvalds 	/* word 83: command set supported */
311*1da177e4SLinus Torvalds 	n = __le16_to_cpu(*((u16 *) &id[83<<1]));
312*1da177e4SLinus Torvalds 
313*1da177e4SLinus Torvalds 	/* word 86: command set/feature enabled */
314*1da177e4SLinus Torvalds 	n |= __le16_to_cpu(*((u16 *) &id[86<<1]));
315*1da177e4SLinus Torvalds 
316*1da177e4SLinus Torvalds 	if (n & (1<<10)) {	/* bit 10: LBA 48 */
317*1da177e4SLinus Torvalds 		d->flags |= DEVFL_EXT;
318*1da177e4SLinus Torvalds 
319*1da177e4SLinus Torvalds 		/* word 100: number lba48 sectors */
320*1da177e4SLinus Torvalds 		ssize = __le64_to_cpu(*((u64 *) &id[100<<1]));
321*1da177e4SLinus Torvalds 
322*1da177e4SLinus Torvalds 		/* set as in ide-disk.c:init_idedisk_capacity */
323*1da177e4SLinus Torvalds 		d->geo.cylinders = ssize;
324*1da177e4SLinus Torvalds 		d->geo.cylinders /= (255 * 63);
325*1da177e4SLinus Torvalds 		d->geo.heads = 255;
326*1da177e4SLinus Torvalds 		d->geo.sectors = 63;
327*1da177e4SLinus Torvalds 	} else {
328*1da177e4SLinus Torvalds 		d->flags &= ~DEVFL_EXT;
329*1da177e4SLinus Torvalds 
330*1da177e4SLinus Torvalds 		/* number lba28 sectors */
331*1da177e4SLinus Torvalds 		ssize = __le32_to_cpu(*((u32 *) &id[60<<1]));
332*1da177e4SLinus Torvalds 
333*1da177e4SLinus Torvalds 		/* NOTE: obsolete in ATA 6 */
334*1da177e4SLinus Torvalds 		d->geo.cylinders = __le16_to_cpu(*((u16 *) &id[54<<1]));
335*1da177e4SLinus Torvalds 		d->geo.heads = __le16_to_cpu(*((u16 *) &id[55<<1]));
336*1da177e4SLinus Torvalds 		d->geo.sectors = __le16_to_cpu(*((u16 *) &id[56<<1]));
337*1da177e4SLinus Torvalds 	}
338*1da177e4SLinus Torvalds 	d->ssize = ssize;
339*1da177e4SLinus Torvalds 	d->geo.start = 0;
340*1da177e4SLinus Torvalds 	if (d->gd != NULL) {
341*1da177e4SLinus Torvalds 		d->gd->capacity = ssize;
342*1da177e4SLinus Torvalds 		d->flags |= DEVFL_UP;
343*1da177e4SLinus Torvalds 		return;
344*1da177e4SLinus Torvalds 	}
345*1da177e4SLinus Torvalds 	if (d->flags & DEVFL_WORKON) {
346*1da177e4SLinus Torvalds 		printk(KERN_INFO "aoe: ataid_complete: can't schedule work, it's already on!  "
347*1da177e4SLinus Torvalds 			"(This really shouldn't happen).\n");
348*1da177e4SLinus Torvalds 		return;
349*1da177e4SLinus Torvalds 	}
350*1da177e4SLinus Torvalds 	INIT_WORK(&d->work, aoeblk_gdalloc, d);
351*1da177e4SLinus Torvalds 	schedule_work(&d->work);
352*1da177e4SLinus Torvalds 	d->flags |= DEVFL_WORKON;
353*1da177e4SLinus Torvalds }
354*1da177e4SLinus Torvalds 
355*1da177e4SLinus Torvalds static void
356*1da177e4SLinus Torvalds calc_rttavg(struct aoedev *d, int rtt)
357*1da177e4SLinus Torvalds {
358*1da177e4SLinus Torvalds 	register long n;
359*1da177e4SLinus Torvalds 
360*1da177e4SLinus Torvalds 	n = rtt;
361*1da177e4SLinus Torvalds 	if (n < MINTIMER)
362*1da177e4SLinus Torvalds 		n = MINTIMER;
363*1da177e4SLinus Torvalds 	else if (n > MAXTIMER)
364*1da177e4SLinus Torvalds 		n = MAXTIMER;
365*1da177e4SLinus Torvalds 
366*1da177e4SLinus Torvalds 	/* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */
367*1da177e4SLinus Torvalds 	n -= d->rttavg;
368*1da177e4SLinus Torvalds 	d->rttavg += n >> 2;
369*1da177e4SLinus Torvalds }
370*1da177e4SLinus Torvalds 
371*1da177e4SLinus Torvalds void
372*1da177e4SLinus Torvalds aoecmd_ata_rsp(struct sk_buff *skb)
373*1da177e4SLinus Torvalds {
374*1da177e4SLinus Torvalds 	struct aoedev *d;
375*1da177e4SLinus Torvalds 	struct aoe_hdr *hin;
376*1da177e4SLinus Torvalds 	struct aoe_atahdr *ahin, *ahout;
377*1da177e4SLinus Torvalds 	struct frame *f;
378*1da177e4SLinus Torvalds 	struct buf *buf;
379*1da177e4SLinus Torvalds 	struct sk_buff *sl;
380*1da177e4SLinus Torvalds 	register long n;
381*1da177e4SLinus Torvalds 	ulong flags;
382*1da177e4SLinus Torvalds 	char ebuf[128];
383*1da177e4SLinus Torvalds 
384*1da177e4SLinus Torvalds 	hin = (struct aoe_hdr *) skb->mac.raw;
385*1da177e4SLinus Torvalds 	d = aoedev_bymac(hin->src);
386*1da177e4SLinus Torvalds 	if (d == NULL) {
387*1da177e4SLinus Torvalds 		snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
388*1da177e4SLinus Torvalds 			"for unknown device %d.%d\n",
389*1da177e4SLinus Torvalds 			 __be16_to_cpu(*((u16 *) hin->major)),
390*1da177e4SLinus Torvalds 			hin->minor);
391*1da177e4SLinus Torvalds 		aoechr_error(ebuf);
392*1da177e4SLinus Torvalds 		return;
393*1da177e4SLinus Torvalds 	}
394*1da177e4SLinus Torvalds 
395*1da177e4SLinus Torvalds 	spin_lock_irqsave(&d->lock, flags);
396*1da177e4SLinus Torvalds 
397*1da177e4SLinus Torvalds 	f = getframe(d, __be32_to_cpu(*((u32 *) hin->tag)));
398*1da177e4SLinus Torvalds 	if (f == NULL) {
399*1da177e4SLinus Torvalds 		spin_unlock_irqrestore(&d->lock, flags);
400*1da177e4SLinus Torvalds 		snprintf(ebuf, sizeof ebuf,
401*1da177e4SLinus Torvalds 			"%15s e%d.%d    tag=%08x@%08lx\n",
402*1da177e4SLinus Torvalds 			"unexpected rsp",
403*1da177e4SLinus Torvalds 			__be16_to_cpu(*((u16 *) hin->major)),
404*1da177e4SLinus Torvalds 			hin->minor,
405*1da177e4SLinus Torvalds 			__be32_to_cpu(*((u32 *) hin->tag)),
406*1da177e4SLinus Torvalds 			jiffies);
407*1da177e4SLinus Torvalds 		aoechr_error(ebuf);
408*1da177e4SLinus Torvalds 		return;
409*1da177e4SLinus Torvalds 	}
410*1da177e4SLinus Torvalds 
411*1da177e4SLinus Torvalds 	calc_rttavg(d, tsince(f->tag));
412*1da177e4SLinus Torvalds 
413*1da177e4SLinus Torvalds 	ahin = (struct aoe_atahdr *) (hin+1);
414*1da177e4SLinus Torvalds 	ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr));
415*1da177e4SLinus Torvalds 	buf = f->buf;
416*1da177e4SLinus Torvalds 
417*1da177e4SLinus Torvalds 	if (ahin->cmdstat & 0xa9) {	/* these bits cleared on success */
418*1da177e4SLinus Torvalds 		printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
419*1da177e4SLinus Torvalds 			"stat=%2.2Xh from e%ld.%ld\n",
420*1da177e4SLinus Torvalds 			ahout->cmdstat, ahin->cmdstat,
421*1da177e4SLinus Torvalds 			d->aoemajor, d->aoeminor);
422*1da177e4SLinus Torvalds 		if (buf)
423*1da177e4SLinus Torvalds 			buf->flags |= BUFFL_FAIL;
424*1da177e4SLinus Torvalds 	} else {
425*1da177e4SLinus Torvalds 		switch (ahout->cmdstat) {
426*1da177e4SLinus Torvalds 		case WIN_READ:
427*1da177e4SLinus Torvalds 		case WIN_READ_EXT:
428*1da177e4SLinus Torvalds 			n = ahout->scnt << 9;
429*1da177e4SLinus Torvalds 			if (skb->len - sizeof *hin - sizeof *ahin < n) {
430*1da177e4SLinus Torvalds 				printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
431*1da177e4SLinus Torvalds 					"ata data size in read.  skb->len=%d\n",
432*1da177e4SLinus Torvalds 					skb->len);
433*1da177e4SLinus Torvalds 				/* fail frame f?  just returning will rexmit. */
434*1da177e4SLinus Torvalds 				spin_unlock_irqrestore(&d->lock, flags);
435*1da177e4SLinus Torvalds 				return;
436*1da177e4SLinus Torvalds 			}
437*1da177e4SLinus Torvalds 			memcpy(f->bufaddr, ahin+1, n);
438*1da177e4SLinus Torvalds 		case WIN_WRITE:
439*1da177e4SLinus Torvalds 		case WIN_WRITE_EXT:
440*1da177e4SLinus Torvalds 			break;
441*1da177e4SLinus Torvalds 		case WIN_IDENTIFY:
442*1da177e4SLinus Torvalds 			if (skb->len - sizeof *hin - sizeof *ahin < 512) {
443*1da177e4SLinus Torvalds 				printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size "
444*1da177e4SLinus Torvalds 					"in ataid.  skb->len=%d\n", skb->len);
445*1da177e4SLinus Torvalds 				spin_unlock_irqrestore(&d->lock, flags);
446*1da177e4SLinus Torvalds 				return;
447*1da177e4SLinus Torvalds 			}
448*1da177e4SLinus Torvalds 			ataid_complete(d, (char *) (ahin+1));
449*1da177e4SLinus Torvalds 			/* d->flags |= DEVFL_WC_UPDATE; */
450*1da177e4SLinus Torvalds 			break;
451*1da177e4SLinus Torvalds 		default:
452*1da177e4SLinus Torvalds 			printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized "
453*1da177e4SLinus Torvalds 			       "outbound ata command %2.2Xh for %d.%d\n",
454*1da177e4SLinus Torvalds 			       ahout->cmdstat,
455*1da177e4SLinus Torvalds 			       __be16_to_cpu(*((u16 *) hin->major)),
456*1da177e4SLinus Torvalds 			       hin->minor);
457*1da177e4SLinus Torvalds 		}
458*1da177e4SLinus Torvalds 	}
459*1da177e4SLinus Torvalds 
460*1da177e4SLinus Torvalds 	if (buf) {
461*1da177e4SLinus Torvalds 		buf->nframesout -= 1;
462*1da177e4SLinus Torvalds 		if (buf->nframesout == 0 && buf->resid == 0) {
463*1da177e4SLinus Torvalds 			n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
464*1da177e4SLinus Torvalds 			bio_endio(buf->bio, buf->bio->bi_size, n);
465*1da177e4SLinus Torvalds 			mempool_free(buf, d->bufpool);
466*1da177e4SLinus Torvalds 		}
467*1da177e4SLinus Torvalds 	}
468*1da177e4SLinus Torvalds 
469*1da177e4SLinus Torvalds 	f->buf = NULL;
470*1da177e4SLinus Torvalds 	f->tag = FREETAG;
471*1da177e4SLinus Torvalds 
472*1da177e4SLinus Torvalds 	aoecmd_work(d);
473*1da177e4SLinus Torvalds 
474*1da177e4SLinus Torvalds 	sl = d->skblist;
475*1da177e4SLinus Torvalds 	d->skblist = NULL;
476*1da177e4SLinus Torvalds 
477*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&d->lock, flags);
478*1da177e4SLinus Torvalds 
479*1da177e4SLinus Torvalds 	aoenet_xmit(sl);
480*1da177e4SLinus Torvalds }
481*1da177e4SLinus Torvalds 
482*1da177e4SLinus Torvalds void
483*1da177e4SLinus Torvalds aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
484*1da177e4SLinus Torvalds {
485*1da177e4SLinus Torvalds 	struct aoe_hdr *h;
486*1da177e4SLinus Torvalds 	struct aoe_cfghdr *ch;
487*1da177e4SLinus Torvalds 	struct sk_buff *skb, *sl;
488*1da177e4SLinus Torvalds 	struct net_device *ifp;
489*1da177e4SLinus Torvalds 	u16 aoe_type = __constant_cpu_to_be16(ETH_P_AOE);
490*1da177e4SLinus Torvalds 	u16 net_aoemajor = __cpu_to_be16(aoemajor);
491*1da177e4SLinus Torvalds 
492*1da177e4SLinus Torvalds 	sl = NULL;
493*1da177e4SLinus Torvalds 
494*1da177e4SLinus Torvalds 	read_lock(&dev_base_lock);
495*1da177e4SLinus Torvalds 	for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
496*1da177e4SLinus Torvalds 		dev_hold(ifp);
497*1da177e4SLinus Torvalds 		if (!is_aoe_netif(ifp))
498*1da177e4SLinus Torvalds 			continue;
499*1da177e4SLinus Torvalds 
500*1da177e4SLinus Torvalds 		skb = new_skb(ifp, sizeof *h + sizeof *ch);
501*1da177e4SLinus Torvalds 		if (skb == NULL) {
502*1da177e4SLinus Torvalds 			printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
503*1da177e4SLinus Torvalds 			continue;
504*1da177e4SLinus Torvalds 		}
505*1da177e4SLinus Torvalds 		h = (struct aoe_hdr *) skb->mac.raw;
506*1da177e4SLinus Torvalds 		memset(h, 0, sizeof *h + sizeof *ch);
507*1da177e4SLinus Torvalds 
508*1da177e4SLinus Torvalds 		memset(h->dst, 0xff, sizeof h->dst);
509*1da177e4SLinus Torvalds 		memcpy(h->src, ifp->dev_addr, sizeof h->src);
510*1da177e4SLinus Torvalds 		memcpy(h->type, &aoe_type, sizeof aoe_type);
511*1da177e4SLinus Torvalds 		h->verfl = AOE_HVER;
512*1da177e4SLinus Torvalds 		memcpy(h->major, &net_aoemajor, sizeof net_aoemajor);
513*1da177e4SLinus Torvalds 		h->minor = aoeminor;
514*1da177e4SLinus Torvalds 		h->cmd = AOECMD_CFG;
515*1da177e4SLinus Torvalds 
516*1da177e4SLinus Torvalds 		skb->next = sl;
517*1da177e4SLinus Torvalds 		sl = skb;
518*1da177e4SLinus Torvalds 	}
519*1da177e4SLinus Torvalds 	read_unlock(&dev_base_lock);
520*1da177e4SLinus Torvalds 
521*1da177e4SLinus Torvalds 	aoenet_xmit(sl);
522*1da177e4SLinus Torvalds }
523*1da177e4SLinus Torvalds 
524*1da177e4SLinus Torvalds /*
525*1da177e4SLinus Torvalds  * Since we only call this in one place (and it only prepares one frame)
526*1da177e4SLinus Torvalds  * we just return the skb.  Usually we'd chain it up to the d->skblist.
527*1da177e4SLinus Torvalds  */
528*1da177e4SLinus Torvalds static struct sk_buff *
529*1da177e4SLinus Torvalds aoecmd_ata_id(struct aoedev *d)
530*1da177e4SLinus Torvalds {
531*1da177e4SLinus Torvalds 	struct aoe_hdr *h;
532*1da177e4SLinus Torvalds 	struct aoe_atahdr *ah;
533*1da177e4SLinus Torvalds 	struct frame *f;
534*1da177e4SLinus Torvalds 	struct sk_buff *skb;
535*1da177e4SLinus Torvalds 
536*1da177e4SLinus Torvalds 	f = getframe(d, FREETAG);
537*1da177e4SLinus Torvalds 	if (f == NULL) {
538*1da177e4SLinus Torvalds 		printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame.  "
539*1da177e4SLinus Torvalds 			"This shouldn't happen.\n");
540*1da177e4SLinus Torvalds 		return NULL;
541*1da177e4SLinus Torvalds 	}
542*1da177e4SLinus Torvalds 
543*1da177e4SLinus Torvalds 	/* initialize the headers & frame */
544*1da177e4SLinus Torvalds 	h = (struct aoe_hdr *) f->data;
545*1da177e4SLinus Torvalds 	ah = (struct aoe_atahdr *) (h+1);
546*1da177e4SLinus Torvalds 	f->ndata = sizeof *h + sizeof *ah;
547*1da177e4SLinus Torvalds 	memset(h, 0, f->ndata);
548*1da177e4SLinus Torvalds 	f->tag = aoehdr_atainit(d, h);
549*1da177e4SLinus Torvalds 	f->waited = 0;
550*1da177e4SLinus Torvalds 	f->writedatalen = 0;
551*1da177e4SLinus Torvalds 
552*1da177e4SLinus Torvalds 	/* this message initializes the device, so we reset the rttavg */
553*1da177e4SLinus Torvalds 	d->rttavg = MAXTIMER;
554*1da177e4SLinus Torvalds 
555*1da177e4SLinus Torvalds 	/* set up ata header */
556*1da177e4SLinus Torvalds 	ah->scnt = 1;
557*1da177e4SLinus Torvalds 	ah->cmdstat = WIN_IDENTIFY;
558*1da177e4SLinus Torvalds 	ah->lba3 = 0xa0;
559*1da177e4SLinus Torvalds 
560*1da177e4SLinus Torvalds 	skb = skb_prepare(d, f);
561*1da177e4SLinus Torvalds 
562*1da177e4SLinus Torvalds 	/* we now want to start the rexmit tracking */
563*1da177e4SLinus Torvalds 	d->flags &= ~DEVFL_TKILL;
564*1da177e4SLinus Torvalds 	d->timer.data = (ulong) d;
565*1da177e4SLinus Torvalds 	d->timer.function = rexmit_timer;
566*1da177e4SLinus Torvalds 	d->timer.expires = jiffies + TIMERTICK;
567*1da177e4SLinus Torvalds 	add_timer(&d->timer);
568*1da177e4SLinus Torvalds 
569*1da177e4SLinus Torvalds 	return skb;
570*1da177e4SLinus Torvalds }
571*1da177e4SLinus Torvalds 
572*1da177e4SLinus Torvalds void
573*1da177e4SLinus Torvalds aoecmd_cfg_rsp(struct sk_buff *skb)
574*1da177e4SLinus Torvalds {
575*1da177e4SLinus Torvalds 	struct aoedev *d;
576*1da177e4SLinus Torvalds 	struct aoe_hdr *h;
577*1da177e4SLinus Torvalds 	struct aoe_cfghdr *ch;
578*1da177e4SLinus Torvalds 	ulong flags, bufcnt, sysminor, aoemajor;
579*1da177e4SLinus Torvalds 	struct sk_buff *sl;
580*1da177e4SLinus Torvalds 	enum { MAXFRAMES = 8, MAXSYSMINOR = 255 };
581*1da177e4SLinus Torvalds 
582*1da177e4SLinus Torvalds 	h = (struct aoe_hdr *) skb->mac.raw;
583*1da177e4SLinus Torvalds 	ch = (struct aoe_cfghdr *) (h+1);
584*1da177e4SLinus Torvalds 
585*1da177e4SLinus Torvalds 	/*
586*1da177e4SLinus Torvalds 	 * Enough people have their dip switches set backwards to
587*1da177e4SLinus Torvalds 	 * warrant a loud message for this special case.
588*1da177e4SLinus Torvalds 	 */
589*1da177e4SLinus Torvalds 	aoemajor = __be16_to_cpu(*((u16 *) h->major));
590*1da177e4SLinus Torvalds 	if (aoemajor == 0xfff) {
591*1da177e4SLinus Torvalds 		printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf "
592*1da177e4SLinus Torvalds 			"address is all ones.  Check shelf dip switches\n");
593*1da177e4SLinus Torvalds 		return;
594*1da177e4SLinus Torvalds 	}
595*1da177e4SLinus Torvalds 
596*1da177e4SLinus Torvalds 	sysminor = SYSMINOR(aoemajor, h->minor);
597*1da177e4SLinus Torvalds 	if (sysminor > MAXSYSMINOR) {
598*1da177e4SLinus Torvalds 		printk(KERN_INFO "aoe: aoecmd_cfg_rsp: sysminor %ld too "
599*1da177e4SLinus Torvalds 			"large\n", sysminor);
600*1da177e4SLinus Torvalds 		return;
601*1da177e4SLinus Torvalds 	}
602*1da177e4SLinus Torvalds 
603*1da177e4SLinus Torvalds 	bufcnt = __be16_to_cpu(*((u16 *) ch->bufcnt));
604*1da177e4SLinus Torvalds 	if (bufcnt > MAXFRAMES)	/* keep it reasonable */
605*1da177e4SLinus Torvalds 		bufcnt = MAXFRAMES;
606*1da177e4SLinus Torvalds 
607*1da177e4SLinus Torvalds 	d = aoedev_set(sysminor, h->src, skb->dev, bufcnt);
608*1da177e4SLinus Torvalds 	if (d == NULL) {
609*1da177e4SLinus Torvalds 		printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device set failure\n");
610*1da177e4SLinus Torvalds 		return;
611*1da177e4SLinus Torvalds 	}
612*1da177e4SLinus Torvalds 
613*1da177e4SLinus Torvalds 	spin_lock_irqsave(&d->lock, flags);
614*1da177e4SLinus Torvalds 
615*1da177e4SLinus Torvalds 	if (d->flags & (DEVFL_UP | DEVFL_CLOSEWAIT)) {
616*1da177e4SLinus Torvalds 		spin_unlock_irqrestore(&d->lock, flags);
617*1da177e4SLinus Torvalds 		return;
618*1da177e4SLinus Torvalds 	}
619*1da177e4SLinus Torvalds 
620*1da177e4SLinus Torvalds 	d->fw_ver = __be16_to_cpu(*((u16 *) ch->fwver));
621*1da177e4SLinus Torvalds 
622*1da177e4SLinus Torvalds 	/* we get here only if the device is new */
623*1da177e4SLinus Torvalds 	sl = aoecmd_ata_id(d);
624*1da177e4SLinus Torvalds 
625*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&d->lock, flags);
626*1da177e4SLinus Torvalds 
627*1da177e4SLinus Torvalds 	aoenet_xmit(sl);
628*1da177e4SLinus Torvalds }
629*1da177e4SLinus Torvalds 
630