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