1fea05a26SEd Cashin /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * aoecmd.c 41da177e4SLinus Torvalds * Filesystem request handling methods 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 704b3ab52SBartlomiej Zolnierkiewicz #include <linux/ata.h> 85a0e3ad6STejun Heo #include <linux/slab.h> 91da177e4SLinus Torvalds #include <linux/hdreg.h> 101da177e4SLinus Torvalds #include <linux/blkdev.h> 111da177e4SLinus Torvalds #include <linux/skbuff.h> 121da177e4SLinus Torvalds #include <linux/netdevice.h> 133ae1c24eSEd L. Cashin #include <linux/genhd.h> 1468e0d42fSEd L. Cashin #include <linux/moduleparam.h> 15896831f5SEd Cashin #include <linux/workqueue.h> 16896831f5SEd Cashin #include <linux/kthread.h> 17881d966bSEric W. Biederman #include <net/net_namespace.h> 18475172fbSEd L. Cashin #include <asm/unaligned.h> 19896831f5SEd Cashin #include <linux/uio.h> 201da177e4SLinus Torvalds #include "aoe.h" 211da177e4SLinus Torvalds 22896831f5SEd Cashin #define MAXIOC (8192) /* default meant to avoid most soft lockups */ 23896831f5SEd Cashin 24896831f5SEd Cashin static void ktcomplete(struct frame *, struct sk_buff *); 25bbb44e30SEd Cashin static int count_targets(struct aoedev *d, int *untainted); 26896831f5SEd Cashin 2769cf2d85SEd Cashin static struct buf *nextbuf(struct aoedev *); 2869cf2d85SEd Cashin 29b751e8b6SEd L. Cashin static int aoe_deadsecs = 60 * 3; 30b751e8b6SEd L. Cashin module_param(aoe_deadsecs, int, 0644); 31b751e8b6SEd L. Cashin MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); 321da177e4SLinus Torvalds 337b6ccc5fSEd Cashin static int aoe_maxout = 64; 347df620d8SEd L. Cashin module_param(aoe_maxout, int, 0644); 357df620d8SEd L. Cashin MODULE_PARM_DESC(aoe_maxout, 367df620d8SEd L. Cashin "Only aoe_maxout outstanding packets for every MAC on eX.Y."); 377df620d8SEd L. Cashin 38896831f5SEd Cashin static wait_queue_head_t ktiowq; 39896831f5SEd Cashin static struct ktstate kts; 40896831f5SEd Cashin 41896831f5SEd Cashin /* io completion queue */ 42896831f5SEd Cashin static struct { 43896831f5SEd Cashin struct list_head head; 44896831f5SEd Cashin spinlock_t lock; 45896831f5SEd Cashin } iocq; 46896831f5SEd Cashin 47bbb44e30SEd Cashin static struct page *empty_page; 48bbb44e30SEd Cashin 4968e0d42fSEd L. Cashin static struct sk_buff * 50e407a7f6SEd L. Cashin new_skb(ulong len) 511da177e4SLinus Torvalds { 521da177e4SLinus Torvalds struct sk_buff *skb; 531da177e4SLinus Torvalds 54*91c57464SEric Dumazet skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC); 551da177e4SLinus Torvalds if (skb) { 56*91c57464SEric Dumazet skb_reserve(skb, MAX_HEADER); 57459a98edSArnaldo Carvalho de Melo skb_reset_mac_header(skb); 58c1d2bbe1SArnaldo Carvalho de Melo skb_reset_network_header(skb); 591da177e4SLinus Torvalds skb->protocol = __constant_htons(ETH_P_AOE); 608babe8ccSEd Cashin skb_checksum_none_assert(skb); 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds return skb; 631da177e4SLinus Torvalds } 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds static struct frame * 663a0c40d2SEd Cashin getframe_deferred(struct aoedev *d, u32 tag) 673a0c40d2SEd Cashin { 683a0c40d2SEd Cashin struct list_head *head, *pos, *nx; 693a0c40d2SEd Cashin struct frame *f; 703a0c40d2SEd Cashin 713a0c40d2SEd Cashin head = &d->rexmitq; 723a0c40d2SEd Cashin list_for_each_safe(pos, nx, head) { 733a0c40d2SEd Cashin f = list_entry(pos, struct frame, head); 743a0c40d2SEd Cashin if (f->tag == tag) { 753a0c40d2SEd Cashin list_del(pos); 763a0c40d2SEd Cashin return f; 773a0c40d2SEd Cashin } 783a0c40d2SEd Cashin } 793a0c40d2SEd Cashin return NULL; 803a0c40d2SEd Cashin } 813a0c40d2SEd Cashin 823a0c40d2SEd Cashin static struct frame * 8364a80f5aSEd Cashin getframe(struct aoedev *d, u32 tag) 841da177e4SLinus Torvalds { 85896831f5SEd Cashin struct frame *f; 86896831f5SEd Cashin struct list_head *head, *pos, *nx; 87896831f5SEd Cashin u32 n; 881da177e4SLinus Torvalds 89896831f5SEd Cashin n = tag % NFACTIVE; 9064a80f5aSEd Cashin head = &d->factive[n]; 91896831f5SEd Cashin list_for_each_safe(pos, nx, head) { 92896831f5SEd Cashin f = list_entry(pos, struct frame, head); 93896831f5SEd Cashin if (f->tag == tag) { 94896831f5SEd Cashin list_del(pos); 951da177e4SLinus Torvalds return f; 96896831f5SEd Cashin } 97896831f5SEd Cashin } 981da177e4SLinus Torvalds return NULL; 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds /* 1021da177e4SLinus Torvalds * Leave the top bit clear so we have tagspace for userland. 1031da177e4SLinus Torvalds * The bottom 16 bits are the xmit tick for rexmit/rttavg processing. 1041da177e4SLinus Torvalds * This driver reserves tag -1 to mean "unused frame." 1051da177e4SLinus Torvalds */ 1061da177e4SLinus Torvalds static int 10764a80f5aSEd Cashin newtag(struct aoedev *d) 1081da177e4SLinus Torvalds { 1091da177e4SLinus Torvalds register ulong n; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds n = jiffies & 0xffff; 11264a80f5aSEd Cashin return n |= (++d->lasttag & 0x7fff) << 16; 1131da177e4SLinus Torvalds } 1141da177e4SLinus Torvalds 115896831f5SEd Cashin static u32 11668e0d42fSEd L. Cashin aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) 1171da177e4SLinus Torvalds { 11864a80f5aSEd Cashin u32 host_tag = newtag(d); 1191da177e4SLinus Torvalds 12068e0d42fSEd L. Cashin memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); 12168e0d42fSEd L. Cashin memcpy(h->dst, t->addr, sizeof h->dst); 12263e9cc5dSecashin@coraid.com h->type = __constant_cpu_to_be16(ETH_P_AOE); 1231da177e4SLinus Torvalds h->verfl = AOE_HVER; 12463e9cc5dSecashin@coraid.com h->major = cpu_to_be16(d->aoemajor); 1251da177e4SLinus Torvalds h->minor = d->aoeminor; 1261da177e4SLinus Torvalds h->cmd = AOECMD_ATA; 12763e9cc5dSecashin@coraid.com h->tag = cpu_to_be32(host_tag); 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds return host_tag; 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds 13219bf2635SEd L. Cashin static inline void 13319bf2635SEd L. Cashin put_lba(struct aoe_atahdr *ah, sector_t lba) 13419bf2635SEd L. Cashin { 13519bf2635SEd L. Cashin ah->lba0 = lba; 13619bf2635SEd L. Cashin ah->lba1 = lba >>= 8; 13719bf2635SEd L. Cashin ah->lba2 = lba >>= 8; 13819bf2635SEd L. Cashin ah->lba3 = lba >>= 8; 13919bf2635SEd L. Cashin ah->lba4 = lba >>= 8; 14019bf2635SEd L. Cashin ah->lba5 = lba >>= 8; 14119bf2635SEd L. Cashin } 14219bf2635SEd L. Cashin 1433f0f0133SEd Cashin static struct aoeif * 14468e0d42fSEd L. Cashin ifrotate(struct aoetgt *t) 1451da177e4SLinus Torvalds { 1463f0f0133SEd Cashin struct aoeif *ifp; 1473f0f0133SEd Cashin 1483f0f0133SEd Cashin ifp = t->ifp; 1493f0f0133SEd Cashin ifp++; 1503f0f0133SEd Cashin if (ifp >= &t->ifs[NAOEIFS] || ifp->nd == NULL) 1513f0f0133SEd Cashin ifp = t->ifs; 1523f0f0133SEd Cashin if (ifp->nd == NULL) 1533f0f0133SEd Cashin return NULL; 1543f0f0133SEd Cashin return t->ifp = ifp; 15568e0d42fSEd L. Cashin } 15668e0d42fSEd L. Cashin 1579bb237b6SEd L. Cashin static void 1589bb237b6SEd L. Cashin skb_pool_put(struct aoedev *d, struct sk_buff *skb) 1599bb237b6SEd L. Cashin { 160e9bb8fb0SDavid S. Miller __skb_queue_tail(&d->skbpool, skb); 1619bb237b6SEd L. Cashin } 1629bb237b6SEd L. Cashin 1639bb237b6SEd L. Cashin static struct sk_buff * 1649bb237b6SEd L. Cashin skb_pool_get(struct aoedev *d) 1659bb237b6SEd L. Cashin { 166e9bb8fb0SDavid S. Miller struct sk_buff *skb = skb_peek(&d->skbpool); 1679bb237b6SEd L. Cashin 1689bb237b6SEd L. Cashin if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) { 169e9bb8fb0SDavid S. Miller __skb_unlink(skb, &d->skbpool); 1709bb237b6SEd L. Cashin return skb; 1719bb237b6SEd L. Cashin } 172e9bb8fb0SDavid S. Miller if (skb_queue_len(&d->skbpool) < NSKBPOOLMAX && 173e9bb8fb0SDavid S. Miller (skb = new_skb(ETH_ZLEN))) 1749bb237b6SEd L. Cashin return skb; 175e9bb8fb0SDavid S. Miller 1769bb237b6SEd L. Cashin return NULL; 1779bb237b6SEd L. Cashin } 1789bb237b6SEd L. Cashin 179896831f5SEd Cashin void 180896831f5SEd Cashin aoe_freetframe(struct frame *f) 18168e0d42fSEd L. Cashin { 182896831f5SEd Cashin struct aoetgt *t; 183896831f5SEd Cashin 184896831f5SEd Cashin t = f->t; 185896831f5SEd Cashin f->buf = NULL; 186bbb44e30SEd Cashin f->lba = 0; 187896831f5SEd Cashin f->bv = NULL; 188896831f5SEd Cashin f->r_skb = NULL; 189bbb44e30SEd Cashin f->flags = 0; 190896831f5SEd Cashin list_add(&f->head, &t->ffree); 191896831f5SEd Cashin } 192896831f5SEd Cashin 193896831f5SEd Cashin static struct frame * 194896831f5SEd Cashin newtframe(struct aoedev *d, struct aoetgt *t) 195896831f5SEd Cashin { 196896831f5SEd Cashin struct frame *f; 1979bb237b6SEd L. Cashin struct sk_buff *skb; 198896831f5SEd Cashin struct list_head *pos; 199896831f5SEd Cashin 200896831f5SEd Cashin if (list_empty(&t->ffree)) { 201896831f5SEd Cashin if (t->falloc >= NSKBPOOLMAX*2) 202896831f5SEd Cashin return NULL; 203896831f5SEd Cashin f = kcalloc(1, sizeof(*f), GFP_ATOMIC); 204896831f5SEd Cashin if (f == NULL) 205896831f5SEd Cashin return NULL; 206896831f5SEd Cashin t->falloc++; 207896831f5SEd Cashin f->t = t; 208896831f5SEd Cashin } else { 209896831f5SEd Cashin pos = t->ffree.next; 210896831f5SEd Cashin list_del(pos); 211896831f5SEd Cashin f = list_entry(pos, struct frame, head); 212896831f5SEd Cashin } 213896831f5SEd Cashin 214896831f5SEd Cashin skb = f->skb; 215896831f5SEd Cashin if (skb == NULL) { 216896831f5SEd Cashin f->skb = skb = new_skb(ETH_ZLEN); 217896831f5SEd Cashin if (!skb) { 218896831f5SEd Cashin bail: aoe_freetframe(f); 219896831f5SEd Cashin return NULL; 220896831f5SEd Cashin } 221896831f5SEd Cashin } 222896831f5SEd Cashin 223896831f5SEd Cashin if (atomic_read(&skb_shinfo(skb)->dataref) != 1) { 224896831f5SEd Cashin skb = skb_pool_get(d); 225896831f5SEd Cashin if (skb == NULL) 226896831f5SEd Cashin goto bail; 227896831f5SEd Cashin skb_pool_put(d, f->skb); 228896831f5SEd Cashin f->skb = skb; 229896831f5SEd Cashin } 230896831f5SEd Cashin 231896831f5SEd Cashin skb->truesize -= skb->data_len; 232896831f5SEd Cashin skb_shinfo(skb)->nr_frags = skb->data_len = 0; 233896831f5SEd Cashin skb_trim(skb, 0); 234896831f5SEd Cashin return f; 235896831f5SEd Cashin } 236896831f5SEd Cashin 237896831f5SEd Cashin static struct frame * 238896831f5SEd Cashin newframe(struct aoedev *d) 239896831f5SEd Cashin { 240896831f5SEd Cashin struct frame *f; 241896831f5SEd Cashin struct aoetgt *t, **tt; 242896831f5SEd Cashin int totout = 0; 243bbb44e30SEd Cashin int use_tainted; 244bbb44e30SEd Cashin int has_untainted; 24568e0d42fSEd L. Cashin 24671114ec4SEd Cashin if (!d->targets || !d->targets[0]) { 24768e0d42fSEd L. Cashin printk(KERN_ERR "aoe: NULL TARGETS!\n"); 24868e0d42fSEd L. Cashin return NULL; 24968e0d42fSEd L. Cashin } 250896831f5SEd Cashin tt = d->tgt; /* last used target */ 251bbb44e30SEd Cashin for (use_tainted = 0, has_untainted = 0;;) { 252896831f5SEd Cashin tt++; 25371114ec4SEd Cashin if (tt >= &d->targets[d->ntargets] || !*tt) 254896831f5SEd Cashin tt = d->targets; 255896831f5SEd Cashin t = *tt; 256bbb44e30SEd Cashin if (!t->taint) { 257bbb44e30SEd Cashin has_untainted = 1; 258896831f5SEd Cashin totout += t->nout; 259bbb44e30SEd Cashin } 260896831f5SEd Cashin if (t->nout < t->maxout 261bbb44e30SEd Cashin && (use_tainted || !t->taint) 262896831f5SEd Cashin && t->ifp->nd) { 263896831f5SEd Cashin f = newtframe(d, t); 264896831f5SEd Cashin if (f) { 265896831f5SEd Cashin ifrotate(t); 2663f0f0133SEd Cashin d->tgt = tt; 26768e0d42fSEd L. Cashin return f; 26868e0d42fSEd L. Cashin } 2699bb237b6SEd L. Cashin } 270bbb44e30SEd Cashin if (tt == d->tgt) { /* we've looped and found nada */ 271bbb44e30SEd Cashin if (!use_tainted && !has_untainted) 272bbb44e30SEd Cashin use_tainted = 1; 273bbb44e30SEd Cashin else 2749bb237b6SEd L. Cashin break; 275896831f5SEd Cashin } 276bbb44e30SEd Cashin } 277896831f5SEd Cashin if (totout == 0) { 278896831f5SEd Cashin d->kicked++; 279896831f5SEd Cashin d->flags |= DEVFL_KICKME; 2809bb237b6SEd L. Cashin } 28168e0d42fSEd L. Cashin return NULL; 28268e0d42fSEd L. Cashin } 28368e0d42fSEd L. Cashin 2843d5b0605SEd Cashin static void 2853d5b0605SEd Cashin skb_fillup(struct sk_buff *skb, struct bio_vec *bv, ulong off, ulong cnt) 2863d5b0605SEd Cashin { 2873d5b0605SEd Cashin int frag = 0; 2883d5b0605SEd Cashin ulong fcnt; 2893d5b0605SEd Cashin loop: 2903d5b0605SEd Cashin fcnt = bv->bv_len - (off - bv->bv_offset); 2913d5b0605SEd Cashin if (fcnt > cnt) 2923d5b0605SEd Cashin fcnt = cnt; 2933d5b0605SEd Cashin skb_fill_page_desc(skb, frag++, bv->bv_page, off, fcnt); 2943d5b0605SEd Cashin cnt -= fcnt; 2953d5b0605SEd Cashin if (cnt <= 0) 2963d5b0605SEd Cashin return; 2973d5b0605SEd Cashin bv++; 2983d5b0605SEd Cashin off = bv->bv_offset; 2993d5b0605SEd Cashin goto loop; 3003d5b0605SEd Cashin } 3013d5b0605SEd Cashin 302896831f5SEd Cashin static void 303896831f5SEd Cashin fhash(struct frame *f) 304896831f5SEd Cashin { 30564a80f5aSEd Cashin struct aoedev *d = f->t->d; 306896831f5SEd Cashin u32 n; 307896831f5SEd Cashin 308896831f5SEd Cashin n = f->tag % NFACTIVE; 30964a80f5aSEd Cashin list_add_tail(&f->head, &d->factive[n]); 310896831f5SEd Cashin } 311896831f5SEd Cashin 312bbb44e30SEd Cashin static void 313bbb44e30SEd Cashin ata_rw_frameinit(struct frame *f) 314bbb44e30SEd Cashin { 315bbb44e30SEd Cashin struct aoetgt *t; 316bbb44e30SEd Cashin struct aoe_hdr *h; 317bbb44e30SEd Cashin struct aoe_atahdr *ah; 318bbb44e30SEd Cashin struct sk_buff *skb; 319bbb44e30SEd Cashin char writebit, extbit; 320bbb44e30SEd Cashin 321bbb44e30SEd Cashin skb = f->skb; 322bbb44e30SEd Cashin h = (struct aoe_hdr *) skb_mac_header(skb); 323bbb44e30SEd Cashin ah = (struct aoe_atahdr *) (h + 1); 324bbb44e30SEd Cashin skb_put(skb, sizeof(*h) + sizeof(*ah)); 325bbb44e30SEd Cashin memset(h, 0, skb->len); 326bbb44e30SEd Cashin 327bbb44e30SEd Cashin writebit = 0x10; 328bbb44e30SEd Cashin extbit = 0x4; 329bbb44e30SEd Cashin 330bbb44e30SEd Cashin t = f->t; 331bbb44e30SEd Cashin f->tag = aoehdr_atainit(t->d, t, h); 332bbb44e30SEd Cashin fhash(f); 333bbb44e30SEd Cashin t->nout++; 334bbb44e30SEd Cashin f->waited = 0; 335bbb44e30SEd Cashin f->waited_total = 0; 336bbb44e30SEd Cashin if (f->buf) 337bbb44e30SEd Cashin f->lba = f->buf->sector; 338bbb44e30SEd Cashin 339bbb44e30SEd Cashin /* set up ata header */ 340bbb44e30SEd Cashin ah->scnt = f->bcnt >> 9; 341bbb44e30SEd Cashin put_lba(ah, f->lba); 342bbb44e30SEd Cashin if (t->d->flags & DEVFL_EXT) { 343bbb44e30SEd Cashin ah->aflags |= AOEAFL_EXT; 344bbb44e30SEd Cashin } else { 345bbb44e30SEd Cashin extbit = 0; 346bbb44e30SEd Cashin ah->lba3 &= 0x0f; 347bbb44e30SEd Cashin ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ 348bbb44e30SEd Cashin } 349bbb44e30SEd Cashin if (f->buf && bio_data_dir(f->buf->bio) == WRITE) { 350bbb44e30SEd Cashin skb_fillup(skb, f->bv, f->bv_off, f->bcnt); 351bbb44e30SEd Cashin ah->aflags |= AOEAFL_WRITE; 352bbb44e30SEd Cashin skb->len += f->bcnt; 353bbb44e30SEd Cashin skb->data_len = f->bcnt; 354bbb44e30SEd Cashin skb->truesize += f->bcnt; 355bbb44e30SEd Cashin t->wpkts++; 356bbb44e30SEd Cashin } else { 357bbb44e30SEd Cashin t->rpkts++; 358bbb44e30SEd Cashin writebit = 0; 359bbb44e30SEd Cashin } 360bbb44e30SEd Cashin 361bbb44e30SEd Cashin ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; 362bbb44e30SEd Cashin skb->dev = t->ifp->nd; 363bbb44e30SEd Cashin } 364bbb44e30SEd Cashin 36568e0d42fSEd L. Cashin static int 36668e0d42fSEd L. Cashin aoecmd_ata_rw(struct aoedev *d) 36768e0d42fSEd L. Cashin { 36868e0d42fSEd L. Cashin struct frame *f; 3691da177e4SLinus Torvalds struct buf *buf; 37068e0d42fSEd L. Cashin struct aoetgt *t; 3711da177e4SLinus Torvalds struct sk_buff *skb; 37269cf2d85SEd Cashin struct sk_buff_head queue; 3733d5b0605SEd Cashin ulong bcnt, fbcnt; 3741da177e4SLinus Torvalds 37569cf2d85SEd Cashin buf = nextbuf(d); 37669cf2d85SEd Cashin if (buf == NULL) 37769cf2d85SEd Cashin return 0; 378896831f5SEd Cashin f = newframe(d); 37968e0d42fSEd L. Cashin if (f == NULL) 38068e0d42fSEd L. Cashin return 0; 38168e0d42fSEd L. Cashin t = *d->tgt; 3823f0f0133SEd Cashin bcnt = d->maxbcnt; 38368e0d42fSEd L. Cashin if (bcnt == 0) 38468e0d42fSEd L. Cashin bcnt = DEFAULTBCNT; 3853d5b0605SEd Cashin if (bcnt > buf->resid) 3863d5b0605SEd Cashin bcnt = buf->resid; 3873d5b0605SEd Cashin fbcnt = bcnt; 3883d5b0605SEd Cashin f->bv = buf->bv; 3893d5b0605SEd Cashin f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid); 3903d5b0605SEd Cashin do { 3913d5b0605SEd Cashin if (fbcnt < buf->bv_resid) { 3923d5b0605SEd Cashin buf->bv_resid -= fbcnt; 3933d5b0605SEd Cashin buf->resid -= fbcnt; 3943d5b0605SEd Cashin break; 3953d5b0605SEd Cashin } 3963d5b0605SEd Cashin fbcnt -= buf->bv_resid; 3973d5b0605SEd Cashin buf->resid -= buf->bv_resid; 3983d5b0605SEd Cashin if (buf->resid == 0) { 39969cf2d85SEd Cashin d->ip.buf = NULL; 4003d5b0605SEd Cashin break; 4013d5b0605SEd Cashin } 4023d5b0605SEd Cashin buf->bv++; 4033d5b0605SEd Cashin buf->bv_resid = buf->bv->bv_len; 4043d5b0605SEd Cashin WARN_ON(buf->bv_resid == 0); 4053d5b0605SEd Cashin } while (fbcnt); 4063d5b0605SEd Cashin 4071da177e4SLinus Torvalds /* initialize the headers & frame */ 4081da177e4SLinus Torvalds f->buf = buf; 40919bf2635SEd L. Cashin f->bcnt = bcnt; 410bbb44e30SEd Cashin ata_rw_frameinit(f); 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds /* mark all tracking fields and load out */ 4131da177e4SLinus Torvalds buf->nframesout += 1; 4141da177e4SLinus Torvalds buf->sector += bcnt >> 9; 4151da177e4SLinus Torvalds 416bbb44e30SEd Cashin skb = skb_clone(f->skb, GFP_ATOMIC); 41769cf2d85SEd Cashin if (skb) { 4185f0c9c48SEd Cashin do_gettimeofday(&f->sent); 4195f0c9c48SEd Cashin f->sent_jiffs = (u32) jiffies; 42069cf2d85SEd Cashin __skb_queue_head_init(&queue); 42169cf2d85SEd Cashin __skb_queue_tail(&queue, skb); 42269cf2d85SEd Cashin aoenet_xmit(&queue); 42369cf2d85SEd Cashin } 42468e0d42fSEd L. Cashin return 1; 42568e0d42fSEd L. Cashin } 4261da177e4SLinus Torvalds 4273ae1c24eSEd L. Cashin /* some callers cannot sleep, and they can call this function, 4283ae1c24eSEd L. Cashin * transmitting the packets later, when interrupts are on 4293ae1c24eSEd L. Cashin */ 430e9bb8fb0SDavid S. Miller static void 431e9bb8fb0SDavid S. Miller aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *queue) 4323ae1c24eSEd L. Cashin { 4333ae1c24eSEd L. Cashin struct aoe_hdr *h; 4343ae1c24eSEd L. Cashin struct aoe_cfghdr *ch; 435e9bb8fb0SDavid S. Miller struct sk_buff *skb; 4363ae1c24eSEd L. Cashin struct net_device *ifp; 4373ae1c24eSEd L. Cashin 438840a185dSEric Dumazet rcu_read_lock(); 439840a185dSEric Dumazet for_each_netdev_rcu(&init_net, ifp) { 4403ae1c24eSEd L. Cashin dev_hold(ifp); 4413ae1c24eSEd L. Cashin if (!is_aoe_netif(ifp)) 4427562f876SPavel Emelianov goto cont; 4433ae1c24eSEd L. Cashin 444e407a7f6SEd L. Cashin skb = new_skb(sizeof *h + sizeof *ch); 4453ae1c24eSEd L. Cashin if (skb == NULL) { 446a12c93f0SEd L. Cashin printk(KERN_INFO "aoe: skb alloc failure\n"); 4477562f876SPavel Emelianov goto cont; 4483ae1c24eSEd L. Cashin } 44919900cdeSEd L. Cashin skb_put(skb, sizeof *h + sizeof *ch); 450e407a7f6SEd L. Cashin skb->dev = ifp; 451e9bb8fb0SDavid S. Miller __skb_queue_tail(queue, skb); 452abdbf94dSEd L. Cashin h = (struct aoe_hdr *) skb_mac_header(skb); 4533ae1c24eSEd L. Cashin memset(h, 0, sizeof *h + sizeof *ch); 4543ae1c24eSEd L. Cashin 4553ae1c24eSEd L. Cashin memset(h->dst, 0xff, sizeof h->dst); 4563ae1c24eSEd L. Cashin memcpy(h->src, ifp->dev_addr, sizeof h->src); 4573ae1c24eSEd L. Cashin h->type = __constant_cpu_to_be16(ETH_P_AOE); 4583ae1c24eSEd L. Cashin h->verfl = AOE_HVER; 4593ae1c24eSEd L. Cashin h->major = cpu_to_be16(aoemajor); 4603ae1c24eSEd L. Cashin h->minor = aoeminor; 4613ae1c24eSEd L. Cashin h->cmd = AOECMD_CFG; 4623ae1c24eSEd L. Cashin 4637562f876SPavel Emelianov cont: 4647562f876SPavel Emelianov dev_put(ifp); 4653ae1c24eSEd L. Cashin } 466840a185dSEric Dumazet rcu_read_unlock(); 4673ae1c24eSEd L. Cashin } 4683ae1c24eSEd L. Cashin 4691da177e4SLinus Torvalds static void 470896831f5SEd Cashin resend(struct aoedev *d, struct frame *f) 4711da177e4SLinus Torvalds { 4721da177e4SLinus Torvalds struct sk_buff *skb; 47369cf2d85SEd Cashin struct sk_buff_head queue; 4741da177e4SLinus Torvalds struct aoe_hdr *h; 47519bf2635SEd L. Cashin struct aoe_atahdr *ah; 476896831f5SEd Cashin struct aoetgt *t; 4771da177e4SLinus Torvalds char buf[128]; 4781da177e4SLinus Torvalds u32 n; 4791da177e4SLinus Torvalds 480896831f5SEd Cashin t = f->t; 48164a80f5aSEd Cashin n = newtag(d); 482e407a7f6SEd L. Cashin skb = f->skb; 4833f0f0133SEd Cashin if (ifrotate(t) == NULL) { 4843f0f0133SEd Cashin /* probably can't happen, but set it up to fail anyway */ 4853f0f0133SEd Cashin pr_info("aoe: resend: no interfaces to rotate to.\n"); 4863f0f0133SEd Cashin ktcomplete(f, NULL); 4873f0f0133SEd Cashin return; 4883f0f0133SEd Cashin } 489abdbf94dSEd L. Cashin h = (struct aoe_hdr *) skb_mac_header(skb); 49019bf2635SEd L. Cashin ah = (struct aoe_atahdr *) (h+1); 49168e0d42fSEd L. Cashin 492bbb44e30SEd Cashin if (!(f->flags & FFL_PROBE)) { 493bbb44e30SEd Cashin snprintf(buf, sizeof(buf), 494411c41eeSHarvey Harrison "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", 495bbb44e30SEd Cashin "retransmit", d->aoemajor, d->aoeminor, 496bbb44e30SEd Cashin f->tag, jiffies, n, 497411c41eeSHarvey Harrison h->src, h->dst, t->nout); 49868e0d42fSEd L. Cashin aoechr_error(buf); 499bbb44e30SEd Cashin } 50068e0d42fSEd L. Cashin 5011da177e4SLinus Torvalds f->tag = n; 502896831f5SEd Cashin fhash(f); 50363e9cc5dSecashin@coraid.com h->tag = cpu_to_be32(n); 50468e0d42fSEd L. Cashin memcpy(h->dst, t->addr, sizeof h->dst); 50568e0d42fSEd L. Cashin memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); 5061da177e4SLinus Torvalds 50768e0d42fSEd L. Cashin skb->dev = t->ifp->nd; 5084f51dc5eSEd L. Cashin skb = skb_clone(skb, GFP_ATOMIC); 5094f51dc5eSEd L. Cashin if (skb == NULL) 5104f51dc5eSEd L. Cashin return; 5115f0c9c48SEd Cashin do_gettimeofday(&f->sent); 5125f0c9c48SEd Cashin f->sent_jiffs = (u32) jiffies; 51369cf2d85SEd Cashin __skb_queue_head_init(&queue); 51469cf2d85SEd Cashin __skb_queue_tail(&queue, skb); 51569cf2d85SEd Cashin aoenet_xmit(&queue); 5161da177e4SLinus Torvalds } 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds static int 5195f0c9c48SEd Cashin tsince_hr(struct frame *f) 5205f0c9c48SEd Cashin { 5215f0c9c48SEd Cashin struct timeval now; 5225f0c9c48SEd Cashin int n; 5235f0c9c48SEd Cashin 5245f0c9c48SEd Cashin do_gettimeofday(&now); 5255f0c9c48SEd Cashin n = now.tv_usec - f->sent.tv_usec; 5265f0c9c48SEd Cashin n += (now.tv_sec - f->sent.tv_sec) * USEC_PER_SEC; 5275f0c9c48SEd Cashin 5285f0c9c48SEd Cashin if (n < 0) 5295f0c9c48SEd Cashin n = -n; 5305f0c9c48SEd Cashin 5315f0c9c48SEd Cashin /* For relatively long periods, use jiffies to avoid 5325f0c9c48SEd Cashin * discrepancies caused by updates to the system time. 5335f0c9c48SEd Cashin * 5345f0c9c48SEd Cashin * On system with HZ of 1000, 32-bits is over 49 days 5355f0c9c48SEd Cashin * worth of jiffies, or over 71 minutes worth of usecs. 5365f0c9c48SEd Cashin * 5375f0c9c48SEd Cashin * Jiffies overflow is handled by subtraction of unsigned ints: 5385f0c9c48SEd Cashin * (gdb) print (unsigned) 2 - (unsigned) 0xfffffffe 5395f0c9c48SEd Cashin * $3 = 4 5405f0c9c48SEd Cashin * (gdb) 5415f0c9c48SEd Cashin */ 5425f0c9c48SEd Cashin if (n > USEC_PER_SEC / 4) { 5435f0c9c48SEd Cashin n = ((u32) jiffies) - f->sent_jiffs; 5445f0c9c48SEd Cashin n *= USEC_PER_SEC / HZ; 5455f0c9c48SEd Cashin } 5465f0c9c48SEd Cashin 5475f0c9c48SEd Cashin return n; 5485f0c9c48SEd Cashin } 5495f0c9c48SEd Cashin 5505f0c9c48SEd Cashin static int 551896831f5SEd Cashin tsince(u32 tag) 5521da177e4SLinus Torvalds { 5531da177e4SLinus Torvalds int n; 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds n = jiffies & 0xffff; 5561da177e4SLinus Torvalds n -= tag & 0xffff; 5571da177e4SLinus Torvalds if (n < 0) 5581da177e4SLinus Torvalds n += 1<<16; 5595f0c9c48SEd Cashin return jiffies_to_usecs(n + 1); 5601da177e4SLinus Torvalds } 5611da177e4SLinus Torvalds 56268e0d42fSEd L. Cashin static struct aoeif * 56368e0d42fSEd L. Cashin getif(struct aoetgt *t, struct net_device *nd) 56468e0d42fSEd L. Cashin { 56568e0d42fSEd L. Cashin struct aoeif *p, *e; 56668e0d42fSEd L. Cashin 56768e0d42fSEd L. Cashin p = t->ifs; 56868e0d42fSEd L. Cashin e = p + NAOEIFS; 56968e0d42fSEd L. Cashin for (; p < e; p++) 57068e0d42fSEd L. Cashin if (p->nd == nd) 57168e0d42fSEd L. Cashin return p; 57268e0d42fSEd L. Cashin return NULL; 57368e0d42fSEd L. Cashin } 57468e0d42fSEd L. Cashin 57568e0d42fSEd L. Cashin static void 57668e0d42fSEd L. Cashin ejectif(struct aoetgt *t, struct aoeif *ifp) 57768e0d42fSEd L. Cashin { 57868e0d42fSEd L. Cashin struct aoeif *e; 5791b86fda9SEd Cashin struct net_device *nd; 58068e0d42fSEd L. Cashin ulong n; 58168e0d42fSEd L. Cashin 5821b86fda9SEd Cashin nd = ifp->nd; 58368e0d42fSEd L. Cashin e = t->ifs + NAOEIFS - 1; 58468e0d42fSEd L. Cashin n = (e - ifp) * sizeof *ifp; 58568e0d42fSEd L. Cashin memmove(ifp, ifp+1, n); 58668e0d42fSEd L. Cashin e->nd = NULL; 5871b86fda9SEd Cashin dev_put(nd); 58868e0d42fSEd L. Cashin } 58968e0d42fSEd L. Cashin 5903fc9b032SEd Cashin static struct frame * 591bbb44e30SEd Cashin reassign_frame(struct frame *f) 59268e0d42fSEd L. Cashin { 5933fc9b032SEd Cashin struct frame *nf; 59468e0d42fSEd L. Cashin struct sk_buff *skb; 59568e0d42fSEd L. Cashin 5963fc9b032SEd Cashin nf = newframe(f->t->d); 59768e0d42fSEd L. Cashin if (!nf) 5983fc9b032SEd Cashin return NULL; 599bbb44e30SEd Cashin if (nf->t == f->t) { 600bbb44e30SEd Cashin aoe_freetframe(nf); 601bbb44e30SEd Cashin return NULL; 602bbb44e30SEd Cashin } 603896831f5SEd Cashin 60468e0d42fSEd L. Cashin skb = nf->skb; 605896831f5SEd Cashin nf->skb = f->skb; 606896831f5SEd Cashin nf->buf = f->buf; 607896831f5SEd Cashin nf->bcnt = f->bcnt; 608896831f5SEd Cashin nf->lba = f->lba; 609896831f5SEd Cashin nf->bv = f->bv; 610896831f5SEd Cashin nf->bv_off = f->bv_off; 61168e0d42fSEd L. Cashin nf->waited = 0; 6123fc9b032SEd Cashin nf->waited_total = f->waited_total; 6133fc9b032SEd Cashin nf->sent = f->sent; 614fe7252bfSEd Cashin nf->sent_jiffs = f->sent_jiffs; 615896831f5SEd Cashin f->skb = skb; 6163fc9b032SEd Cashin 6173fc9b032SEd Cashin return nf; 6183fc9b032SEd Cashin } 6193fc9b032SEd Cashin 620bbb44e30SEd Cashin static void 621bbb44e30SEd Cashin probe(struct aoetgt *t) 6223fc9b032SEd Cashin { 623bbb44e30SEd Cashin struct aoedev *d; 624bbb44e30SEd Cashin struct frame *f; 625bbb44e30SEd Cashin struct sk_buff *skb; 626bbb44e30SEd Cashin struct sk_buff_head queue; 627bbb44e30SEd Cashin size_t n, m; 628bbb44e30SEd Cashin int frag; 6293fc9b032SEd Cashin 630bbb44e30SEd Cashin d = t->d; 631bbb44e30SEd Cashin f = newtframe(d, t); 632bbb44e30SEd Cashin if (!f) { 633bbb44e30SEd Cashin pr_err("%s %pm for e%ld.%d: %s\n", 634bbb44e30SEd Cashin "aoe: cannot probe remote address", 635bbb44e30SEd Cashin t->addr, 636bbb44e30SEd Cashin (long) d->aoemajor, d->aoeminor, 637bbb44e30SEd Cashin "no frame available"); 638bbb44e30SEd Cashin return; 639bbb44e30SEd Cashin } 640bbb44e30SEd Cashin f->flags |= FFL_PROBE; 641bbb44e30SEd Cashin ifrotate(t); 642bbb44e30SEd Cashin f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT; 643bbb44e30SEd Cashin ata_rw_frameinit(f); 644bbb44e30SEd Cashin skb = f->skb; 645bbb44e30SEd Cashin for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) { 646bbb44e30SEd Cashin if (n < PAGE_SIZE) 647bbb44e30SEd Cashin m = n; 648bbb44e30SEd Cashin else 649bbb44e30SEd Cashin m = PAGE_SIZE; 650bbb44e30SEd Cashin skb_fill_page_desc(skb, frag, empty_page, 0, m); 651bbb44e30SEd Cashin } 652bbb44e30SEd Cashin skb->len += f->bcnt; 653bbb44e30SEd Cashin skb->data_len = f->bcnt; 654bbb44e30SEd Cashin skb->truesize += f->bcnt; 655bbb44e30SEd Cashin 656bbb44e30SEd Cashin skb = skb_clone(f->skb, GFP_ATOMIC); 657bbb44e30SEd Cashin if (skb) { 658bbb44e30SEd Cashin do_gettimeofday(&f->sent); 659bbb44e30SEd Cashin f->sent_jiffs = (u32) jiffies; 660bbb44e30SEd Cashin __skb_queue_head_init(&queue); 661bbb44e30SEd Cashin __skb_queue_tail(&queue, skb); 662bbb44e30SEd Cashin aoenet_xmit(&queue); 663896831f5SEd Cashin } 66468e0d42fSEd L. Cashin } 665bbb44e30SEd Cashin 666bbb44e30SEd Cashin static long 667bbb44e30SEd Cashin rto(struct aoedev *d) 668bbb44e30SEd Cashin { 669bbb44e30SEd Cashin long t; 670bbb44e30SEd Cashin 671bbb44e30SEd Cashin t = 2 * d->rttavg >> RTTSCALE; 672bbb44e30SEd Cashin t += 8 * d->rttdev >> RTTDSCALE; 673bbb44e30SEd Cashin if (t == 0) 674bbb44e30SEd Cashin t = 1; 675bbb44e30SEd Cashin 676bbb44e30SEd Cashin return t; 67768e0d42fSEd L. Cashin } 67868e0d42fSEd L. Cashin 6791da177e4SLinus Torvalds static void 6803a0c40d2SEd Cashin rexmit_deferred(struct aoedev *d) 6813a0c40d2SEd Cashin { 6823a0c40d2SEd Cashin struct aoetgt *t; 6833a0c40d2SEd Cashin struct frame *f; 684bbb44e30SEd Cashin struct frame *nf; 6853a0c40d2SEd Cashin struct list_head *pos, *nx, *head; 6863fc9b032SEd Cashin int since; 687bbb44e30SEd Cashin int untainted; 688bbb44e30SEd Cashin 689bbb44e30SEd Cashin count_targets(d, &untainted); 6903a0c40d2SEd Cashin 6913a0c40d2SEd Cashin head = &d->rexmitq; 6923a0c40d2SEd Cashin list_for_each_safe(pos, nx, head) { 6933a0c40d2SEd Cashin f = list_entry(pos, struct frame, head); 6943a0c40d2SEd Cashin t = f->t; 695bbb44e30SEd Cashin if (t->taint) { 696bbb44e30SEd Cashin if (!(f->flags & FFL_PROBE)) { 697bbb44e30SEd Cashin nf = reassign_frame(f); 698bbb44e30SEd Cashin if (nf) { 699bbb44e30SEd Cashin if (t->nout_probes == 0 700bbb44e30SEd Cashin && untainted > 0) { 701bbb44e30SEd Cashin probe(t); 702bbb44e30SEd Cashin t->nout_probes++; 703bbb44e30SEd Cashin } 704bbb44e30SEd Cashin list_replace(&f->head, &nf->head); 705bbb44e30SEd Cashin pos = &nf->head; 706bbb44e30SEd Cashin aoe_freetframe(f); 707bbb44e30SEd Cashin f = nf; 708bbb44e30SEd Cashin t = f->t; 709bbb44e30SEd Cashin } 710bbb44e30SEd Cashin } else if (untainted < 1) { 711bbb44e30SEd Cashin /* don't probe w/o other untainted aoetgts */ 712bbb44e30SEd Cashin goto stop_probe; 713bbb44e30SEd Cashin } else if (tsince_hr(f) < t->taint * rto(d)) { 714bbb44e30SEd Cashin /* reprobe slowly when taint is high */ 715bbb44e30SEd Cashin continue; 716bbb44e30SEd Cashin } 717bbb44e30SEd Cashin } else if (f->flags & FFL_PROBE) { 718bbb44e30SEd Cashin stop_probe: /* don't probe untainted aoetgts */ 719bbb44e30SEd Cashin list_del(pos); 720bbb44e30SEd Cashin aoe_freetframe(f); 721bbb44e30SEd Cashin /* leaving d->kicked, because this is routine */ 722bbb44e30SEd Cashin f->t->d->flags |= DEVFL_KICKME; 723bbb44e30SEd Cashin continue; 724bbb44e30SEd Cashin } 7253a0c40d2SEd Cashin if (t->nout >= t->maxout) 7263a0c40d2SEd Cashin continue; 7273a0c40d2SEd Cashin list_del(pos); 7283a0c40d2SEd Cashin t->nout++; 729bbb44e30SEd Cashin if (f->flags & FFL_PROBE) 730bbb44e30SEd Cashin t->nout_probes++; 7313fc9b032SEd Cashin since = tsince_hr(f); 7323fc9b032SEd Cashin f->waited += since; 7333fc9b032SEd Cashin f->waited_total += since; 7343a0c40d2SEd Cashin resend(d, f); 7353a0c40d2SEd Cashin } 7363a0c40d2SEd Cashin } 7373a0c40d2SEd Cashin 738bbb44e30SEd Cashin /* An aoetgt accumulates demerits quickly, and successful 739bbb44e30SEd Cashin * probing redeems the aoetgt slowly. 740bbb44e30SEd Cashin */ 741bbb44e30SEd Cashin static void 742bbb44e30SEd Cashin scorn(struct aoetgt *t) 743bbb44e30SEd Cashin { 744bbb44e30SEd Cashin int n; 745bbb44e30SEd Cashin 746bbb44e30SEd Cashin n = t->taint++; 747bbb44e30SEd Cashin t->taint += t->taint * 2; 748bbb44e30SEd Cashin if (n > t->taint) 749bbb44e30SEd Cashin t->taint = n; 750bbb44e30SEd Cashin if (t->taint > MAX_TAINT) 751bbb44e30SEd Cashin t->taint = MAX_TAINT; 752bbb44e30SEd Cashin } 753bbb44e30SEd Cashin 754bbb44e30SEd Cashin static int 755bbb44e30SEd Cashin count_targets(struct aoedev *d, int *untainted) 756bbb44e30SEd Cashin { 757bbb44e30SEd Cashin int i, good; 758bbb44e30SEd Cashin 759bbb44e30SEd Cashin for (i = good = 0; i < d->ntargets && d->targets[i]; ++i) 760bbb44e30SEd Cashin if (d->targets[i]->taint == 0) 761bbb44e30SEd Cashin good++; 762bbb44e30SEd Cashin 763bbb44e30SEd Cashin if (untainted) 764bbb44e30SEd Cashin *untainted = good; 765bbb44e30SEd Cashin return i; 766bbb44e30SEd Cashin } 767bbb44e30SEd Cashin 7683a0c40d2SEd Cashin static void 7691da177e4SLinus Torvalds rexmit_timer(ulong vp) 7701da177e4SLinus Torvalds { 7711da177e4SLinus Torvalds struct aoedev *d; 7723a0c40d2SEd Cashin struct aoetgt *t; 77368e0d42fSEd L. Cashin struct aoeif *ifp; 774896831f5SEd Cashin struct frame *f; 775896831f5SEd Cashin struct list_head *head, *pos, *nx; 776896831f5SEd Cashin LIST_HEAD(flist); 7771da177e4SLinus Torvalds register long timeout; 7781da177e4SLinus Torvalds ulong flags, n; 779896831f5SEd Cashin int i; 780bbb44e30SEd Cashin int utgts; /* number of aoetgt descriptors (not slots) */ 7813fc9b032SEd Cashin int since; 7821da177e4SLinus Torvalds 7831da177e4SLinus Torvalds d = (struct aoedev *) vp; 7841da177e4SLinus Torvalds 7850d555ecfSEd Cashin spin_lock_irqsave(&d->lock, flags); 7860d555ecfSEd Cashin 7873a0c40d2SEd Cashin /* timeout based on observed timings and variations */ 788bbb44e30SEd Cashin timeout = rto(d); 789bbb44e30SEd Cashin 790bbb44e30SEd Cashin utgts = count_targets(d, NULL); 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds if (d->flags & DEVFL_TKILL) { 7931c6f3fcaSEd L. Cashin spin_unlock_irqrestore(&d->lock, flags); 7941da177e4SLinus Torvalds return; 7951da177e4SLinus Torvalds } 796896831f5SEd Cashin 797896831f5SEd Cashin /* collect all frames to rexmit into flist */ 798896831f5SEd Cashin for (i = 0; i < NFACTIVE; i++) { 79964a80f5aSEd Cashin head = &d->factive[i]; 800896831f5SEd Cashin list_for_each_safe(pos, nx, head) { 801896831f5SEd Cashin f = list_entry(pos, struct frame, head); 8025f0c9c48SEd Cashin if (tsince_hr(f) < timeout) 80364a80f5aSEd Cashin break; /* end of expired frames */ 804896831f5SEd Cashin /* move to flist for later processing */ 805896831f5SEd Cashin list_move_tail(pos, &flist); 806896831f5SEd Cashin } 807896831f5SEd Cashin } 80869cf2d85SEd Cashin 809896831f5SEd Cashin /* process expired frames */ 810896831f5SEd Cashin while (!list_empty(&flist)) { 811896831f5SEd Cashin pos = flist.next; 812896831f5SEd Cashin f = list_entry(pos, struct frame, head); 8133fc9b032SEd Cashin since = tsince_hr(f); 8143fc9b032SEd Cashin n = f->waited_total + since; 8155f0c9c48SEd Cashin n /= USEC_PER_SEC; 816c450ba0fSEd Cashin if (aoe_deadsecs 817c450ba0fSEd Cashin && n > aoe_deadsecs 818c450ba0fSEd Cashin && !(f->flags & FFL_PROBE)) { 819896831f5SEd Cashin /* Waited too long. Device failure. 820896831f5SEd Cashin * Hang all frames on first hash bucket for downdev 821896831f5SEd Cashin * to clean up. 822896831f5SEd Cashin */ 82364a80f5aSEd Cashin list_splice(&flist, &d->factive[0]); 8241da177e4SLinus Torvalds aoedev_downdev(d); 8253a0c40d2SEd Cashin goto out; 8261da177e4SLinus Torvalds } 82768e0d42fSEd L. Cashin 828896831f5SEd Cashin t = f->t; 829bbb44e30SEd Cashin n = f->waited + since; 830bbb44e30SEd Cashin n /= USEC_PER_SEC; 831bbb44e30SEd Cashin if (aoe_deadsecs && utgts > 0 832bbb44e30SEd Cashin && (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS)) 833bbb44e30SEd Cashin scorn(t); /* avoid this target */ 834d54d35acSEd Cashin 8353a0c40d2SEd Cashin if (t->maxout != 1) { 8363a0c40d2SEd Cashin t->ssthresh = t->maxout / 2; 8373a0c40d2SEd Cashin t->maxout = 1; 83868e0d42fSEd L. Cashin } 83968e0d42fSEd L. Cashin 840bbb44e30SEd Cashin if (f->flags & FFL_PROBE) { 841bbb44e30SEd Cashin t->nout_probes--; 842bbb44e30SEd Cashin } else { 84368e0d42fSEd L. Cashin ifp = getif(t, f->skb->dev); 84468e0d42fSEd L. Cashin if (ifp && ++ifp->lost > (t->nframes << 1) 84568e0d42fSEd L. Cashin && (ifp != t->ifs || t->ifs[1].nd)) { 84668e0d42fSEd L. Cashin ejectif(t, ifp); 84768e0d42fSEd L. Cashin ifp = NULL; 84868e0d42fSEd L. Cashin } 849bbb44e30SEd Cashin } 8503a0c40d2SEd Cashin list_move_tail(pos, &d->rexmitq); 8513a0c40d2SEd Cashin t->nout--; 8521da177e4SLinus Torvalds } 8533a0c40d2SEd Cashin rexmit_deferred(d); 85468e0d42fSEd L. Cashin 8553a0c40d2SEd Cashin out: 856bbb44e30SEd Cashin if ((d->flags & DEVFL_KICKME) && d->blkq) { 8574f51dc5eSEd L. Cashin d->flags &= ~DEVFL_KICKME; 85869cf2d85SEd Cashin d->blkq->request_fn(d->blkq); 8594f51dc5eSEd L. Cashin } 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds d->timer.expires = jiffies + TIMERTICK; 8621da177e4SLinus Torvalds add_timer(&d->timer); 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 86569cf2d85SEd Cashin } 8661da177e4SLinus Torvalds 86769cf2d85SEd Cashin static unsigned long 86869cf2d85SEd Cashin rqbiocnt(struct request *r) 86969cf2d85SEd Cashin { 87069cf2d85SEd Cashin struct bio *bio; 87169cf2d85SEd Cashin unsigned long n = 0; 87269cf2d85SEd Cashin 87369cf2d85SEd Cashin __rq_for_each_bio(bio, r) 87469cf2d85SEd Cashin n++; 87569cf2d85SEd Cashin return n; 87669cf2d85SEd Cashin } 87769cf2d85SEd Cashin 87869cf2d85SEd Cashin /* This can be removed if we are certain that no users of the block 87969cf2d85SEd Cashin * layer will ever use zero-count pages in bios. Otherwise we have to 88069cf2d85SEd Cashin * protect against the put_page sometimes done by the network layer. 88169cf2d85SEd Cashin * 88269cf2d85SEd Cashin * See http://oss.sgi.com/archives/xfs/2007-01/msg00594.html for 88369cf2d85SEd Cashin * discussion. 88469cf2d85SEd Cashin * 88569cf2d85SEd Cashin * We cannot use get_page in the workaround, because it insists on a 88669cf2d85SEd Cashin * positive page count as a precondition. So we use _count directly. 88769cf2d85SEd Cashin */ 88869cf2d85SEd Cashin static void 88969cf2d85SEd Cashin bio_pageinc(struct bio *bio) 89069cf2d85SEd Cashin { 89169cf2d85SEd Cashin struct bio_vec *bv; 89269cf2d85SEd Cashin struct page *page; 89369cf2d85SEd Cashin int i; 89469cf2d85SEd Cashin 89569cf2d85SEd Cashin bio_for_each_segment(bv, bio, i) { 89669cf2d85SEd Cashin page = bv->bv_page; 89769cf2d85SEd Cashin /* Non-zero page count for non-head members of 89869cf2d85SEd Cashin * compound pages is no longer allowed by the kernel, 89969cf2d85SEd Cashin * but this has never been seen here. 90069cf2d85SEd Cashin */ 90169cf2d85SEd Cashin if (unlikely(PageCompound(page))) 90269cf2d85SEd Cashin if (compound_trans_head(page) != page) { 90369cf2d85SEd Cashin pr_crit("page tail used for block I/O\n"); 90469cf2d85SEd Cashin BUG(); 90569cf2d85SEd Cashin } 90669cf2d85SEd Cashin atomic_inc(&page->_count); 90769cf2d85SEd Cashin } 90869cf2d85SEd Cashin } 90969cf2d85SEd Cashin 91069cf2d85SEd Cashin static void 91169cf2d85SEd Cashin bio_pagedec(struct bio *bio) 91269cf2d85SEd Cashin { 91369cf2d85SEd Cashin struct bio_vec *bv; 91469cf2d85SEd Cashin int i; 91569cf2d85SEd Cashin 91669cf2d85SEd Cashin bio_for_each_segment(bv, bio, i) 91769cf2d85SEd Cashin atomic_dec(&bv->bv_page->_count); 91869cf2d85SEd Cashin } 91969cf2d85SEd Cashin 92069cf2d85SEd Cashin static void 92169cf2d85SEd Cashin bufinit(struct buf *buf, struct request *rq, struct bio *bio) 92269cf2d85SEd Cashin { 92369cf2d85SEd Cashin struct bio_vec *bv; 92469cf2d85SEd Cashin 92569cf2d85SEd Cashin memset(buf, 0, sizeof(*buf)); 92669cf2d85SEd Cashin buf->rq = rq; 92769cf2d85SEd Cashin buf->bio = bio; 92869cf2d85SEd Cashin buf->resid = bio->bi_size; 92969cf2d85SEd Cashin buf->sector = bio->bi_sector; 93069cf2d85SEd Cashin bio_pageinc(bio); 93169cf2d85SEd Cashin buf->bv = bv = &bio->bi_io_vec[bio->bi_idx]; 93269cf2d85SEd Cashin buf->bv_resid = bv->bv_len; 93369cf2d85SEd Cashin WARN_ON(buf->bv_resid == 0); 93469cf2d85SEd Cashin } 93569cf2d85SEd Cashin 93669cf2d85SEd Cashin static struct buf * 93769cf2d85SEd Cashin nextbuf(struct aoedev *d) 93869cf2d85SEd Cashin { 93969cf2d85SEd Cashin struct request *rq; 94069cf2d85SEd Cashin struct request_queue *q; 94169cf2d85SEd Cashin struct buf *buf; 94269cf2d85SEd Cashin struct bio *bio; 94369cf2d85SEd Cashin 94469cf2d85SEd Cashin q = d->blkq; 94569cf2d85SEd Cashin if (q == NULL) 94669cf2d85SEd Cashin return NULL; /* initializing */ 94769cf2d85SEd Cashin if (d->ip.buf) 94869cf2d85SEd Cashin return d->ip.buf; 94969cf2d85SEd Cashin rq = d->ip.rq; 95069cf2d85SEd Cashin if (rq == NULL) { 95169cf2d85SEd Cashin rq = blk_peek_request(q); 95269cf2d85SEd Cashin if (rq == NULL) 95369cf2d85SEd Cashin return NULL; 95469cf2d85SEd Cashin blk_start_request(rq); 95569cf2d85SEd Cashin d->ip.rq = rq; 95669cf2d85SEd Cashin d->ip.nxbio = rq->bio; 95769cf2d85SEd Cashin rq->special = (void *) rqbiocnt(rq); 95869cf2d85SEd Cashin } 95969cf2d85SEd Cashin buf = mempool_alloc(d->bufpool, GFP_ATOMIC); 96069cf2d85SEd Cashin if (buf == NULL) { 96169cf2d85SEd Cashin pr_err("aoe: nextbuf: unable to mempool_alloc!\n"); 96269cf2d85SEd Cashin return NULL; 96369cf2d85SEd Cashin } 96469cf2d85SEd Cashin bio = d->ip.nxbio; 96569cf2d85SEd Cashin bufinit(buf, rq, bio); 96669cf2d85SEd Cashin bio = bio->bi_next; 96769cf2d85SEd Cashin d->ip.nxbio = bio; 96869cf2d85SEd Cashin if (bio == NULL) 96969cf2d85SEd Cashin d->ip.rq = NULL; 97069cf2d85SEd Cashin return d->ip.buf = buf; 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds 97368e0d42fSEd L. Cashin /* enters with d->lock held */ 97468e0d42fSEd L. Cashin void 97568e0d42fSEd L. Cashin aoecmd_work(struct aoedev *d) 97668e0d42fSEd L. Cashin { 9773a0c40d2SEd Cashin rexmit_deferred(d); 97869cf2d85SEd Cashin while (aoecmd_ata_rw(d)) 97969cf2d85SEd Cashin ; 98068e0d42fSEd L. Cashin } 98168e0d42fSEd L. Cashin 9823ae1c24eSEd L. Cashin /* this function performs work that has been deferred until sleeping is OK 9833ae1c24eSEd L. Cashin */ 9843ae1c24eSEd L. Cashin void 985c4028958SDavid Howells aoecmd_sleepwork(struct work_struct *work) 9863ae1c24eSEd L. Cashin { 987c4028958SDavid Howells struct aoedev *d = container_of(work, struct aoedev, work); 988b21faa25SEd Cashin struct block_device *bd; 989b21faa25SEd Cashin u64 ssize; 9903ae1c24eSEd L. Cashin 9913ae1c24eSEd L. Cashin if (d->flags & DEVFL_GDALLOC) 9923ae1c24eSEd L. Cashin aoeblk_gdalloc(d); 9933ae1c24eSEd L. Cashin 9943ae1c24eSEd L. Cashin if (d->flags & DEVFL_NEWSIZE) { 99580795aefSTejun Heo ssize = get_capacity(d->gd); 9963ae1c24eSEd L. Cashin bd = bdget_disk(d->gd, 0); 9973ae1c24eSEd L. Cashin if (bd) { 9983ae1c24eSEd L. Cashin mutex_lock(&bd->bd_inode->i_mutex); 9993ae1c24eSEd L. Cashin i_size_write(bd->bd_inode, (loff_t)ssize<<9); 10003ae1c24eSEd L. Cashin mutex_unlock(&bd->bd_inode->i_mutex); 10013ae1c24eSEd L. Cashin bdput(bd); 10023ae1c24eSEd L. Cashin } 1003b21faa25SEd Cashin spin_lock_irq(&d->lock); 10043ae1c24eSEd L. Cashin d->flags |= DEVFL_UP; 10053ae1c24eSEd L. Cashin d->flags &= ~DEVFL_NEWSIZE; 1006b21faa25SEd Cashin spin_unlock_irq(&d->lock); 10073ae1c24eSEd L. Cashin } 10083ae1c24eSEd L. Cashin } 10093ae1c24eSEd L. Cashin 10101da177e4SLinus Torvalds static void 1011667be1e7SEd Cashin ata_ident_fixstring(u16 *id, int ns) 1012667be1e7SEd Cashin { 1013667be1e7SEd Cashin u16 s; 1014667be1e7SEd Cashin 1015667be1e7SEd Cashin while (ns-- > 0) { 1016667be1e7SEd Cashin s = *id; 1017667be1e7SEd Cashin *id++ = s >> 8 | s << 8; 1018667be1e7SEd Cashin } 1019667be1e7SEd Cashin } 1020667be1e7SEd Cashin 1021667be1e7SEd Cashin static void 102268e0d42fSEd L. Cashin ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) 10231da177e4SLinus Torvalds { 10241da177e4SLinus Torvalds u64 ssize; 10251da177e4SLinus Torvalds u16 n; 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds /* word 83: command set supported */ 1028f885f8d1SHarvey Harrison n = get_unaligned_le16(&id[83 << 1]); 10291da177e4SLinus Torvalds 10301da177e4SLinus Torvalds /* word 86: command set/feature enabled */ 1031f885f8d1SHarvey Harrison n |= get_unaligned_le16(&id[86 << 1]); 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds if (n & (1<<10)) { /* bit 10: LBA 48 */ 10341da177e4SLinus Torvalds d->flags |= DEVFL_EXT; 10351da177e4SLinus Torvalds 10361da177e4SLinus Torvalds /* word 100: number lba48 sectors */ 1037f885f8d1SHarvey Harrison ssize = get_unaligned_le64(&id[100 << 1]); 10381da177e4SLinus Torvalds 10391da177e4SLinus Torvalds /* set as in ide-disk.c:init_idedisk_capacity */ 10401da177e4SLinus Torvalds d->geo.cylinders = ssize; 10411da177e4SLinus Torvalds d->geo.cylinders /= (255 * 63); 10421da177e4SLinus Torvalds d->geo.heads = 255; 10431da177e4SLinus Torvalds d->geo.sectors = 63; 10441da177e4SLinus Torvalds } else { 10451da177e4SLinus Torvalds d->flags &= ~DEVFL_EXT; 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds /* number lba28 sectors */ 1048f885f8d1SHarvey Harrison ssize = get_unaligned_le32(&id[60 << 1]); 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds /* NOTE: obsolete in ATA 6 */ 1051f885f8d1SHarvey Harrison d->geo.cylinders = get_unaligned_le16(&id[54 << 1]); 1052f885f8d1SHarvey Harrison d->geo.heads = get_unaligned_le16(&id[55 << 1]); 1053f885f8d1SHarvey Harrison d->geo.sectors = get_unaligned_le16(&id[56 << 1]); 10541da177e4SLinus Torvalds } 10553ae1c24eSEd L. Cashin 1056667be1e7SEd Cashin ata_ident_fixstring((u16 *) &id[10<<1], 10); /* serial */ 1057667be1e7SEd Cashin ata_ident_fixstring((u16 *) &id[23<<1], 4); /* firmware */ 1058667be1e7SEd Cashin ata_ident_fixstring((u16 *) &id[27<<1], 20); /* model */ 1059667be1e7SEd Cashin memcpy(d->ident, id, sizeof(d->ident)); 1060667be1e7SEd Cashin 10613ae1c24eSEd L. Cashin if (d->ssize != ssize) 10621d75981aSEd L. Cashin printk(KERN_INFO 1063411c41eeSHarvey Harrison "aoe: %pm e%ld.%d v%04x has %llu sectors\n", 1064411c41eeSHarvey Harrison t->addr, 10653ae1c24eSEd L. Cashin d->aoemajor, d->aoeminor, 10663ae1c24eSEd L. Cashin d->fw_ver, (long long)ssize); 10671da177e4SLinus Torvalds d->ssize = ssize; 10681da177e4SLinus Torvalds d->geo.start = 0; 10696b9699bbSEd L. Cashin if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) 10706b9699bbSEd L. Cashin return; 10711da177e4SLinus Torvalds if (d->gd != NULL) { 107280795aefSTejun Heo set_capacity(d->gd, ssize); 10733ae1c24eSEd L. Cashin d->flags |= DEVFL_NEWSIZE; 107468e0d42fSEd L. Cashin } else 10753ae1c24eSEd L. Cashin d->flags |= DEVFL_GDALLOC; 10761da177e4SLinus Torvalds schedule_work(&d->work); 10771da177e4SLinus Torvalds } 10781da177e4SLinus Torvalds 10791da177e4SLinus Torvalds static void 10803a0c40d2SEd Cashin calc_rttavg(struct aoedev *d, struct aoetgt *t, int rtt) 10811da177e4SLinus Torvalds { 10821da177e4SLinus Torvalds register long n; 10831da177e4SLinus Torvalds 10841da177e4SLinus Torvalds n = rtt; 10851da177e4SLinus Torvalds 10863a0c40d2SEd Cashin /* cf. Congestion Avoidance and Control, Jacobson & Karels, 1988 */ 10873a0c40d2SEd Cashin n -= d->rttavg >> RTTSCALE; 10883a0c40d2SEd Cashin d->rttavg += n; 10893a0c40d2SEd Cashin if (n < 0) 10903a0c40d2SEd Cashin n = -n; 10913a0c40d2SEd Cashin n -= d->rttdev >> RTTDSCALE; 10923a0c40d2SEd Cashin d->rttdev += n; 10933a0c40d2SEd Cashin 10943a0c40d2SEd Cashin if (!t || t->maxout >= t->nframes) 10953a0c40d2SEd Cashin return; 10963a0c40d2SEd Cashin if (t->maxout < t->ssthresh) 10973a0c40d2SEd Cashin t->maxout += 1; 10983a0c40d2SEd Cashin else if (t->nout == t->maxout && t->next_cwnd-- == 0) { 10993a0c40d2SEd Cashin t->maxout += 1; 11003a0c40d2SEd Cashin t->next_cwnd = t->maxout; 11013a0c40d2SEd Cashin } 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds 110468e0d42fSEd L. Cashin static struct aoetgt * 110568e0d42fSEd L. Cashin gettgt(struct aoedev *d, char *addr) 110668e0d42fSEd L. Cashin { 110768e0d42fSEd L. Cashin struct aoetgt **t, **e; 110868e0d42fSEd L. Cashin 110968e0d42fSEd L. Cashin t = d->targets; 111071114ec4SEd Cashin e = t + d->ntargets; 111168e0d42fSEd L. Cashin for (; t < e && *t; t++) 111268e0d42fSEd L. Cashin if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) 111368e0d42fSEd L. Cashin return *t; 111468e0d42fSEd L. Cashin return NULL; 111568e0d42fSEd L. Cashin } 111668e0d42fSEd L. Cashin 11173d5b0605SEd Cashin static void 1118896831f5SEd Cashin bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt) 11193d5b0605SEd Cashin { 11203d5b0605SEd Cashin ulong fcnt; 11213d5b0605SEd Cashin char *p; 11223d5b0605SEd Cashin int soff = 0; 11233d5b0605SEd Cashin loop: 11243d5b0605SEd Cashin fcnt = bv->bv_len - (off - bv->bv_offset); 11253d5b0605SEd Cashin if (fcnt > cnt) 11263d5b0605SEd Cashin fcnt = cnt; 11273d5b0605SEd Cashin p = page_address(bv->bv_page) + off; 11283d5b0605SEd Cashin skb_copy_bits(skb, soff, p, fcnt); 11293d5b0605SEd Cashin soff += fcnt; 11303d5b0605SEd Cashin cnt -= fcnt; 11313d5b0605SEd Cashin if (cnt <= 0) 11323d5b0605SEd Cashin return; 11333d5b0605SEd Cashin bv++; 11343d5b0605SEd Cashin off = bv->bv_offset; 11353d5b0605SEd Cashin goto loop; 11363d5b0605SEd Cashin } 11373d5b0605SEd Cashin 113869cf2d85SEd Cashin void 113969cf2d85SEd Cashin aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) 114069cf2d85SEd Cashin { 114169cf2d85SEd Cashin struct bio *bio; 114269cf2d85SEd Cashin int bok; 114369cf2d85SEd Cashin struct request_queue *q; 114469cf2d85SEd Cashin 114569cf2d85SEd Cashin q = d->blkq; 114669cf2d85SEd Cashin if (rq == d->ip.rq) 114769cf2d85SEd Cashin d->ip.rq = NULL; 114869cf2d85SEd Cashin do { 114969cf2d85SEd Cashin bio = rq->bio; 115069cf2d85SEd Cashin bok = !fastfail && test_bit(BIO_UPTODATE, &bio->bi_flags); 115169cf2d85SEd Cashin } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_size)); 115269cf2d85SEd Cashin 115369cf2d85SEd Cashin /* cf. http://lkml.org/lkml/2006/10/31/28 */ 115469cf2d85SEd Cashin if (!fastfail) 115511cfb6ffSEd Cashin __blk_run_queue(q); 115669cf2d85SEd Cashin } 115769cf2d85SEd Cashin 115869cf2d85SEd Cashin static void 115969cf2d85SEd Cashin aoe_end_buf(struct aoedev *d, struct buf *buf) 116069cf2d85SEd Cashin { 116169cf2d85SEd Cashin struct request *rq; 116269cf2d85SEd Cashin unsigned long n; 116369cf2d85SEd Cashin 116469cf2d85SEd Cashin if (buf == d->ip.buf) 116569cf2d85SEd Cashin d->ip.buf = NULL; 116669cf2d85SEd Cashin rq = buf->rq; 116769cf2d85SEd Cashin bio_pagedec(buf->bio); 116869cf2d85SEd Cashin mempool_free(buf, d->bufpool); 116969cf2d85SEd Cashin n = (unsigned long) rq->special; 117069cf2d85SEd Cashin rq->special = (void *) --n; 117169cf2d85SEd Cashin if (n == 0) 117269cf2d85SEd Cashin aoe_end_request(d, rq, 0); 117369cf2d85SEd Cashin } 117469cf2d85SEd Cashin 11753d5b0605SEd Cashin static void 1176896831f5SEd Cashin ktiocomplete(struct frame *f) 11773d5b0605SEd Cashin { 1178ddec63e8SEd L. Cashin struct aoe_hdr *hin, *hout; 11791da177e4SLinus Torvalds struct aoe_atahdr *ahin, *ahout; 11801da177e4SLinus Torvalds struct buf *buf; 1181896831f5SEd Cashin struct sk_buff *skb; 118268e0d42fSEd L. Cashin struct aoetgt *t; 118368e0d42fSEd L. Cashin struct aoeif *ifp; 1184896831f5SEd Cashin struct aoedev *d; 1185896831f5SEd Cashin long n; 1186bbb44e30SEd Cashin int untainted; 1187896831f5SEd Cashin 1188896831f5SEd Cashin if (f == NULL) 1189896831f5SEd Cashin return; 1190896831f5SEd Cashin 1191896831f5SEd Cashin t = f->t; 1192896831f5SEd Cashin d = t->d; 1193bbb44e30SEd Cashin skb = f->r_skb; 1194bbb44e30SEd Cashin buf = f->buf; 1195bbb44e30SEd Cashin if (f->flags & FFL_PROBE) 1196bbb44e30SEd Cashin goto out; 1197bbb44e30SEd Cashin if (!skb) /* just fail the buf. */ 1198bbb44e30SEd Cashin goto noskb; 1199896831f5SEd Cashin 1200896831f5SEd Cashin hout = (struct aoe_hdr *) skb_mac_header(f->skb); 1201896831f5SEd Cashin ahout = (struct aoe_atahdr *) (hout+1); 1202896831f5SEd Cashin 1203896831f5SEd Cashin hin = (struct aoe_hdr *) skb->data; 1204896831f5SEd Cashin skb_pull(skb, sizeof(*hin)); 1205896831f5SEd Cashin ahin = (struct aoe_atahdr *) skb->data; 1206896831f5SEd Cashin skb_pull(skb, sizeof(*ahin)); 1207896831f5SEd Cashin if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ 1208896831f5SEd Cashin pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", 1209896831f5SEd Cashin ahout->cmdstat, ahin->cmdstat, 1210896831f5SEd Cashin d->aoemajor, d->aoeminor); 1211896831f5SEd Cashin noskb: if (buf) 121269cf2d85SEd Cashin clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); 1213bbb44e30SEd Cashin goto out; 1214896831f5SEd Cashin } 1215896831f5SEd Cashin 1216896831f5SEd Cashin n = ahout->scnt << 9; 1217896831f5SEd Cashin switch (ahout->cmdstat) { 1218896831f5SEd Cashin case ATA_CMD_PIO_READ: 1219896831f5SEd Cashin case ATA_CMD_PIO_READ_EXT: 1220896831f5SEd Cashin if (skb->len < n) { 1221bf29754aSEd Cashin pr_err("%s e%ld.%d. skb->len=%d need=%ld\n", 1222bf29754aSEd Cashin "aoe: runt data size in read from", 1223bf29754aSEd Cashin (long) d->aoemajor, d->aoeminor, 1224896831f5SEd Cashin skb->len, n); 122569cf2d85SEd Cashin clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); 1226896831f5SEd Cashin break; 1227896831f5SEd Cashin } 1228896831f5SEd Cashin bvcpy(f->bv, f->bv_off, skb, n); 1229896831f5SEd Cashin case ATA_CMD_PIO_WRITE: 1230896831f5SEd Cashin case ATA_CMD_PIO_WRITE_EXT: 1231896831f5SEd Cashin spin_lock_irq(&d->lock); 1232896831f5SEd Cashin ifp = getif(t, skb->dev); 12333f0f0133SEd Cashin if (ifp) 1234896831f5SEd Cashin ifp->lost = 0; 1235896831f5SEd Cashin spin_unlock_irq(&d->lock); 1236896831f5SEd Cashin break; 1237896831f5SEd Cashin case ATA_CMD_ID_ATA: 1238896831f5SEd Cashin if (skb->len < 512) { 1239bf29754aSEd Cashin pr_info("%s e%ld.%d. skb->len=%d need=512\n", 1240bf29754aSEd Cashin "aoe: runt data size in ataid from", 1241bf29754aSEd Cashin (long) d->aoemajor, d->aoeminor, 1242896831f5SEd Cashin skb->len); 1243896831f5SEd Cashin break; 1244896831f5SEd Cashin } 1245896831f5SEd Cashin if (skb_linearize(skb)) 1246896831f5SEd Cashin break; 1247896831f5SEd Cashin spin_lock_irq(&d->lock); 1248896831f5SEd Cashin ataid_complete(d, t, skb->data); 1249896831f5SEd Cashin spin_unlock_irq(&d->lock); 1250896831f5SEd Cashin break; 1251896831f5SEd Cashin default: 1252896831f5SEd Cashin pr_info("aoe: unrecognized ata command %2.2Xh for %d.%d\n", 1253896831f5SEd Cashin ahout->cmdstat, 1254896831f5SEd Cashin be16_to_cpu(get_unaligned(&hin->major)), 1255896831f5SEd Cashin hin->minor); 1256896831f5SEd Cashin } 1257bbb44e30SEd Cashin out: 1258896831f5SEd Cashin spin_lock_irq(&d->lock); 1259bbb44e30SEd Cashin if (t->taint > 0 1260bbb44e30SEd Cashin && --t->taint > 0 1261bbb44e30SEd Cashin && t->nout_probes == 0) { 1262bbb44e30SEd Cashin count_targets(d, &untainted); 1263bbb44e30SEd Cashin if (untainted > 0) { 1264bbb44e30SEd Cashin probe(t); 1265bbb44e30SEd Cashin t->nout_probes++; 1266bbb44e30SEd Cashin } 1267bbb44e30SEd Cashin } 1268896831f5SEd Cashin 1269896831f5SEd Cashin aoe_freetframe(f); 1270896831f5SEd Cashin 127169cf2d85SEd Cashin if (buf && --buf->nframesout == 0 && buf->resid == 0) 127269cf2d85SEd Cashin aoe_end_buf(d, buf); 1273896831f5SEd Cashin 1274896831f5SEd Cashin spin_unlock_irq(&d->lock); 127569cf2d85SEd Cashin aoedev_put(d); 1276896831f5SEd Cashin dev_kfree_skb(skb); 1277896831f5SEd Cashin } 1278896831f5SEd Cashin 1279896831f5SEd Cashin /* Enters with iocq.lock held. 1280896831f5SEd Cashin * Returns true iff responses needing processing remain. 1281896831f5SEd Cashin */ 1282896831f5SEd Cashin static int 1283896831f5SEd Cashin ktio(void) 1284896831f5SEd Cashin { 1285896831f5SEd Cashin struct frame *f; 1286896831f5SEd Cashin struct list_head *pos; 1287896831f5SEd Cashin int i; 1288896831f5SEd Cashin 1289896831f5SEd Cashin for (i = 0; ; ++i) { 1290896831f5SEd Cashin if (i == MAXIOC) 1291896831f5SEd Cashin return 1; 1292896831f5SEd Cashin if (list_empty(&iocq.head)) 1293896831f5SEd Cashin return 0; 1294896831f5SEd Cashin pos = iocq.head.next; 1295896831f5SEd Cashin list_del(pos); 1296896831f5SEd Cashin spin_unlock_irq(&iocq.lock); 1297896831f5SEd Cashin f = list_entry(pos, struct frame, head); 1298896831f5SEd Cashin ktiocomplete(f); 1299896831f5SEd Cashin spin_lock_irq(&iocq.lock); 1300896831f5SEd Cashin } 1301896831f5SEd Cashin } 1302896831f5SEd Cashin 1303896831f5SEd Cashin static int 1304896831f5SEd Cashin kthread(void *vp) 1305896831f5SEd Cashin { 1306896831f5SEd Cashin struct ktstate *k; 1307896831f5SEd Cashin DECLARE_WAITQUEUE(wait, current); 1308896831f5SEd Cashin int more; 1309896831f5SEd Cashin 1310896831f5SEd Cashin k = vp; 1311896831f5SEd Cashin current->flags |= PF_NOFREEZE; 1312896831f5SEd Cashin set_user_nice(current, -10); 1313896831f5SEd Cashin complete(&k->rendez); /* tell spawner we're running */ 1314896831f5SEd Cashin do { 1315896831f5SEd Cashin spin_lock_irq(k->lock); 1316896831f5SEd Cashin more = k->fn(); 1317896831f5SEd Cashin if (!more) { 1318896831f5SEd Cashin add_wait_queue(k->waitq, &wait); 1319896831f5SEd Cashin __set_current_state(TASK_INTERRUPTIBLE); 1320896831f5SEd Cashin } 1321896831f5SEd Cashin spin_unlock_irq(k->lock); 1322896831f5SEd Cashin if (!more) { 1323896831f5SEd Cashin schedule(); 1324896831f5SEd Cashin remove_wait_queue(k->waitq, &wait); 1325896831f5SEd Cashin } else 1326896831f5SEd Cashin cond_resched(); 1327896831f5SEd Cashin } while (!kthread_should_stop()); 1328896831f5SEd Cashin complete(&k->rendez); /* tell spawner we're stopping */ 1329896831f5SEd Cashin return 0; 1330896831f5SEd Cashin } 1331896831f5SEd Cashin 1332eb086ec5SEd Cashin void 1333896831f5SEd Cashin aoe_ktstop(struct ktstate *k) 1334896831f5SEd Cashin { 1335896831f5SEd Cashin kthread_stop(k->task); 1336896831f5SEd Cashin wait_for_completion(&k->rendez); 1337896831f5SEd Cashin } 1338896831f5SEd Cashin 1339eb086ec5SEd Cashin int 1340896831f5SEd Cashin aoe_ktstart(struct ktstate *k) 1341896831f5SEd Cashin { 1342896831f5SEd Cashin struct task_struct *task; 1343896831f5SEd Cashin 1344896831f5SEd Cashin init_completion(&k->rendez); 1345896831f5SEd Cashin task = kthread_run(kthread, k, k->name); 1346896831f5SEd Cashin if (task == NULL || IS_ERR(task)) 1347896831f5SEd Cashin return -ENOMEM; 1348896831f5SEd Cashin k->task = task; 1349896831f5SEd Cashin wait_for_completion(&k->rendez); /* allow kthread to start */ 1350896831f5SEd Cashin init_completion(&k->rendez); /* for waiting for exit later */ 1351896831f5SEd Cashin return 0; 1352896831f5SEd Cashin } 1353896831f5SEd Cashin 1354896831f5SEd Cashin /* pass it off to kthreads for processing */ 1355896831f5SEd Cashin static void 1356896831f5SEd Cashin ktcomplete(struct frame *f, struct sk_buff *skb) 1357896831f5SEd Cashin { 1358896831f5SEd Cashin ulong flags; 1359896831f5SEd Cashin 1360896831f5SEd Cashin f->r_skb = skb; 1361896831f5SEd Cashin spin_lock_irqsave(&iocq.lock, flags); 1362896831f5SEd Cashin list_add_tail(&f->head, &iocq.head); 1363896831f5SEd Cashin spin_unlock_irqrestore(&iocq.lock, flags); 1364896831f5SEd Cashin wake_up(&ktiowq); 1365896831f5SEd Cashin } 1366896831f5SEd Cashin 1367896831f5SEd Cashin struct sk_buff * 1368896831f5SEd Cashin aoecmd_ata_rsp(struct sk_buff *skb) 1369896831f5SEd Cashin { 1370896831f5SEd Cashin struct aoedev *d; 1371896831f5SEd Cashin struct aoe_hdr *h; 1372896831f5SEd Cashin struct frame *f; 1373896831f5SEd Cashin u32 n; 13741da177e4SLinus Torvalds ulong flags; 13751da177e4SLinus Torvalds char ebuf[128]; 137632465c65Secashin@coraid.com u16 aoemajor; 13771da177e4SLinus Torvalds 1378896831f5SEd Cashin h = (struct aoe_hdr *) skb->data; 1379896831f5SEd Cashin aoemajor = be16_to_cpu(get_unaligned(&h->major)); 13800c966214SEd Cashin d = aoedev_by_aoeaddr(aoemajor, h->minor, 0); 13811da177e4SLinus Torvalds if (d == NULL) { 13821da177e4SLinus Torvalds snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response " 13831da177e4SLinus Torvalds "for unknown device %d.%d\n", 1384896831f5SEd Cashin aoemajor, h->minor); 13851da177e4SLinus Torvalds aoechr_error(ebuf); 1386896831f5SEd Cashin return skb; 13871da177e4SLinus Torvalds } 13881da177e4SLinus Torvalds 13891da177e4SLinus Torvalds spin_lock_irqsave(&d->lock, flags); 13901da177e4SLinus Torvalds 1391896831f5SEd Cashin n = be32_to_cpu(get_unaligned(&h->tag)); 139264a80f5aSEd Cashin f = getframe(d, n); 13933a0c40d2SEd Cashin if (f) { 13945f0c9c48SEd Cashin calc_rttavg(d, f->t, tsince_hr(f)); 13953a0c40d2SEd Cashin f->t->nout--; 1396bbb44e30SEd Cashin if (f->flags & FFL_PROBE) 1397bbb44e30SEd Cashin f->t->nout_probes--; 13983a0c40d2SEd Cashin } else { 13993a0c40d2SEd Cashin f = getframe_deferred(d, n); 14003a0c40d2SEd Cashin if (f) { 14015f0c9c48SEd Cashin calc_rttavg(d, NULL, tsince_hr(f)); 14023a0c40d2SEd Cashin } else { 14033a0c40d2SEd Cashin calc_rttavg(d, NULL, tsince(n)); 14041da177e4SLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 140569cf2d85SEd Cashin aoedev_put(d); 14063a0c40d2SEd Cashin snprintf(ebuf, sizeof(ebuf), 14072292a7e1SEd Cashin "%15s e%d.%d tag=%08x@%08lx s=%pm d=%pm\n", 14081da177e4SLinus Torvalds "unexpected rsp", 1409896831f5SEd Cashin get_unaligned_be16(&h->major), 1410896831f5SEd Cashin h->minor, 1411896831f5SEd Cashin get_unaligned_be32(&h->tag), 14122292a7e1SEd Cashin jiffies, 14132292a7e1SEd Cashin h->src, 14142292a7e1SEd Cashin h->dst); 14151da177e4SLinus Torvalds aoechr_error(ebuf); 1416896831f5SEd Cashin return skb; 14171da177e4SLinus Torvalds } 14183a0c40d2SEd Cashin } 14191da177e4SLinus Torvalds aoecmd_work(d); 14201da177e4SLinus Torvalds 14211da177e4SLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1422896831f5SEd Cashin 1423896831f5SEd Cashin ktcomplete(f, skb); 1424896831f5SEd Cashin 1425896831f5SEd Cashin /* 1426896831f5SEd Cashin * Note here that we do not perform an aoedev_put, as we are 1427896831f5SEd Cashin * leaving this reference for the ktio to release. 1428896831f5SEd Cashin */ 1429896831f5SEd Cashin return NULL; 14301da177e4SLinus Torvalds } 14311da177e4SLinus Torvalds 14321da177e4SLinus Torvalds void 14331da177e4SLinus Torvalds aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) 14341da177e4SLinus Torvalds { 1435e9bb8fb0SDavid S. Miller struct sk_buff_head queue; 14361da177e4SLinus Torvalds 1437e9bb8fb0SDavid S. Miller __skb_queue_head_init(&queue); 1438e9bb8fb0SDavid S. Miller aoecmd_cfg_pkts(aoemajor, aoeminor, &queue); 1439e9bb8fb0SDavid S. Miller aoenet_xmit(&queue); 14401da177e4SLinus Torvalds } 14411da177e4SLinus Torvalds 144268e0d42fSEd L. Cashin struct sk_buff * 14431da177e4SLinus Torvalds aoecmd_ata_id(struct aoedev *d) 14441da177e4SLinus Torvalds { 14451da177e4SLinus Torvalds struct aoe_hdr *h; 14461da177e4SLinus Torvalds struct aoe_atahdr *ah; 14471da177e4SLinus Torvalds struct frame *f; 14481da177e4SLinus Torvalds struct sk_buff *skb; 144968e0d42fSEd L. Cashin struct aoetgt *t; 14501da177e4SLinus Torvalds 1451896831f5SEd Cashin f = newframe(d); 145268e0d42fSEd L. Cashin if (f == NULL) 14531da177e4SLinus Torvalds return NULL; 145468e0d42fSEd L. Cashin 145568e0d42fSEd L. Cashin t = *d->tgt; 14561da177e4SLinus Torvalds 14571da177e4SLinus Torvalds /* initialize the headers & frame */ 1458e407a7f6SEd L. Cashin skb = f->skb; 1459abdbf94dSEd L. Cashin h = (struct aoe_hdr *) skb_mac_header(skb); 14601da177e4SLinus Torvalds ah = (struct aoe_atahdr *) (h+1); 146119900cdeSEd L. Cashin skb_put(skb, sizeof *h + sizeof *ah); 146219900cdeSEd L. Cashin memset(h, 0, skb->len); 146368e0d42fSEd L. Cashin f->tag = aoehdr_atainit(d, t, h); 1464896831f5SEd Cashin fhash(f); 146568e0d42fSEd L. Cashin t->nout++; 14661da177e4SLinus Torvalds f->waited = 0; 14673fc9b032SEd Cashin f->waited_total = 0; 14681da177e4SLinus Torvalds 14691da177e4SLinus Torvalds /* set up ata header */ 14701da177e4SLinus Torvalds ah->scnt = 1; 147104b3ab52SBartlomiej Zolnierkiewicz ah->cmdstat = ATA_CMD_ID_ATA; 14721da177e4SLinus Torvalds ah->lba3 = 0xa0; 14731da177e4SLinus Torvalds 147468e0d42fSEd L. Cashin skb->dev = t->ifp->nd; 14751da177e4SLinus Torvalds 14763a0c40d2SEd Cashin d->rttavg = RTTAVG_INIT; 14773a0c40d2SEd Cashin d->rttdev = RTTDEV_INIT; 14781da177e4SLinus Torvalds d->timer.function = rexmit_timer; 14791da177e4SLinus Torvalds 14805f0c9c48SEd Cashin skb = skb_clone(skb, GFP_ATOMIC); 14815f0c9c48SEd Cashin if (skb) { 14825f0c9c48SEd Cashin do_gettimeofday(&f->sent); 14835f0c9c48SEd Cashin f->sent_jiffs = (u32) jiffies; 14845f0c9c48SEd Cashin } 14855f0c9c48SEd Cashin 14865f0c9c48SEd Cashin return skb; 14871da177e4SLinus Torvalds } 14881da177e4SLinus Torvalds 148971114ec4SEd Cashin static struct aoetgt ** 149071114ec4SEd Cashin grow_targets(struct aoedev *d) 149171114ec4SEd Cashin { 149271114ec4SEd Cashin ulong oldn, newn; 149371114ec4SEd Cashin struct aoetgt **tt; 149471114ec4SEd Cashin 149571114ec4SEd Cashin oldn = d->ntargets; 149671114ec4SEd Cashin newn = oldn * 2; 149771114ec4SEd Cashin tt = kcalloc(newn, sizeof(*d->targets), GFP_ATOMIC); 149871114ec4SEd Cashin if (!tt) 149971114ec4SEd Cashin return NULL; 150071114ec4SEd Cashin memmove(tt, d->targets, sizeof(*d->targets) * oldn); 150171114ec4SEd Cashin d->tgt = tt + (d->tgt - d->targets); 150271114ec4SEd Cashin kfree(d->targets); 150371114ec4SEd Cashin d->targets = tt; 150471114ec4SEd Cashin d->ntargets = newn; 150571114ec4SEd Cashin 150671114ec4SEd Cashin return &d->targets[oldn]; 150771114ec4SEd Cashin } 150871114ec4SEd Cashin 150968e0d42fSEd L. Cashin static struct aoetgt * 151068e0d42fSEd L. Cashin addtgt(struct aoedev *d, char *addr, ulong nframes) 151168e0d42fSEd L. Cashin { 151268e0d42fSEd L. Cashin struct aoetgt *t, **tt, **te; 151368e0d42fSEd L. Cashin 151468e0d42fSEd L. Cashin tt = d->targets; 151571114ec4SEd Cashin te = tt + d->ntargets; 151668e0d42fSEd L. Cashin for (; tt < te && *tt; tt++) 151768e0d42fSEd L. Cashin ; 151868e0d42fSEd L. Cashin 1519578c4aa0SEd L. Cashin if (tt == te) { 152071114ec4SEd Cashin tt = grow_targets(d); 152171114ec4SEd Cashin if (!tt) 152271114ec4SEd Cashin goto nomem; 1523578c4aa0SEd L. Cashin } 1524896831f5SEd Cashin t = kzalloc(sizeof(*t), GFP_ATOMIC); 152571114ec4SEd Cashin if (!t) 152671114ec4SEd Cashin goto nomem; 152768e0d42fSEd L. Cashin t->nframes = nframes; 1528896831f5SEd Cashin t->d = d; 152968e0d42fSEd L. Cashin memcpy(t->addr, addr, sizeof t->addr); 153068e0d42fSEd L. Cashin t->ifp = t->ifs; 15313a0c40d2SEd Cashin aoecmd_wreset(t); 1532bbb44e30SEd Cashin t->maxout = t->nframes / 2; 1533896831f5SEd Cashin INIT_LIST_HEAD(&t->ffree); 153468e0d42fSEd L. Cashin return *tt = t; 153571114ec4SEd Cashin 153671114ec4SEd Cashin nomem: 153771114ec4SEd Cashin pr_info("aoe: cannot allocate memory to add target\n"); 153871114ec4SEd Cashin return NULL; 153968e0d42fSEd L. Cashin } 154068e0d42fSEd L. Cashin 15413f0f0133SEd Cashin static void 15423f0f0133SEd Cashin setdbcnt(struct aoedev *d) 15433f0f0133SEd Cashin { 15443f0f0133SEd Cashin struct aoetgt **t, **e; 15453f0f0133SEd Cashin int bcnt = 0; 15463f0f0133SEd Cashin 15473f0f0133SEd Cashin t = d->targets; 154871114ec4SEd Cashin e = t + d->ntargets; 15493f0f0133SEd Cashin for (; t < e && *t; t++) 15503f0f0133SEd Cashin if (bcnt == 0 || bcnt > (*t)->minbcnt) 15513f0f0133SEd Cashin bcnt = (*t)->minbcnt; 15523f0f0133SEd Cashin if (bcnt != d->maxbcnt) { 15533f0f0133SEd Cashin d->maxbcnt = bcnt; 15543f0f0133SEd Cashin pr_info("aoe: e%ld.%d: setting %d byte data frames\n", 15553f0f0133SEd Cashin d->aoemajor, d->aoeminor, bcnt); 15563f0f0133SEd Cashin } 15573f0f0133SEd Cashin } 15583f0f0133SEd Cashin 15593f0f0133SEd Cashin static void 15603f0f0133SEd Cashin setifbcnt(struct aoetgt *t, struct net_device *nd, int bcnt) 15613f0f0133SEd Cashin { 15623f0f0133SEd Cashin struct aoedev *d; 15633f0f0133SEd Cashin struct aoeif *p, *e; 15643f0f0133SEd Cashin int minbcnt; 15653f0f0133SEd Cashin 15663f0f0133SEd Cashin d = t->d; 15673f0f0133SEd Cashin minbcnt = bcnt; 15683f0f0133SEd Cashin p = t->ifs; 15693f0f0133SEd Cashin e = p + NAOEIFS; 15703f0f0133SEd Cashin for (; p < e; p++) { 15713f0f0133SEd Cashin if (p->nd == NULL) 15723f0f0133SEd Cashin break; /* end of the valid interfaces */ 15733f0f0133SEd Cashin if (p->nd == nd) { 15743f0f0133SEd Cashin p->bcnt = bcnt; /* we're updating */ 15753f0f0133SEd Cashin nd = NULL; 15763f0f0133SEd Cashin } else if (minbcnt > p->bcnt) 15773f0f0133SEd Cashin minbcnt = p->bcnt; /* find the min interface */ 15783f0f0133SEd Cashin } 15793f0f0133SEd Cashin if (nd) { 15803f0f0133SEd Cashin if (p == e) { 15813f0f0133SEd Cashin pr_err("aoe: device setifbcnt failure; too many interfaces.\n"); 15823f0f0133SEd Cashin return; 15833f0f0133SEd Cashin } 15841b86fda9SEd Cashin dev_hold(nd); 15853f0f0133SEd Cashin p->nd = nd; 15863f0f0133SEd Cashin p->bcnt = bcnt; 15873f0f0133SEd Cashin } 15883f0f0133SEd Cashin t->minbcnt = minbcnt; 15893f0f0133SEd Cashin setdbcnt(d); 15903f0f0133SEd Cashin } 15913f0f0133SEd Cashin 15921da177e4SLinus Torvalds void 15931da177e4SLinus Torvalds aoecmd_cfg_rsp(struct sk_buff *skb) 15941da177e4SLinus Torvalds { 15951da177e4SLinus Torvalds struct aoedev *d; 15961da177e4SLinus Torvalds struct aoe_hdr *h; 15971da177e4SLinus Torvalds struct aoe_cfghdr *ch; 159868e0d42fSEd L. Cashin struct aoetgt *t; 15990c966214SEd Cashin ulong flags, aoemajor; 16001da177e4SLinus Torvalds struct sk_buff *sl; 160169cf2d85SEd Cashin struct sk_buff_head queue; 160219bf2635SEd L. Cashin u16 n; 16031da177e4SLinus Torvalds 160469cf2d85SEd Cashin sl = NULL; 1605abdbf94dSEd L. Cashin h = (struct aoe_hdr *) skb_mac_header(skb); 16061da177e4SLinus Torvalds ch = (struct aoe_cfghdr *) (h+1); 16071da177e4SLinus Torvalds 16081da177e4SLinus Torvalds /* 16091da177e4SLinus Torvalds * Enough people have their dip switches set backwards to 16101da177e4SLinus Torvalds * warrant a loud message for this special case. 16111da177e4SLinus Torvalds */ 1612823ed72eSHarvey Harrison aoemajor = get_unaligned_be16(&h->major); 16131da177e4SLinus Torvalds if (aoemajor == 0xfff) { 1614a12c93f0SEd L. Cashin printk(KERN_ERR "aoe: Warning: shelf address is all ones. " 16156bb6285fSEd L. Cashin "Check shelf dip switches.\n"); 16161da177e4SLinus Torvalds return; 16171da177e4SLinus Torvalds } 16187159e969SEd Cashin if (aoemajor == 0xffff) { 16197159e969SEd Cashin pr_info("aoe: e%ld.%d: broadcast shelf number invalid\n", 16200c966214SEd Cashin aoemajor, (int) h->minor); 16216583303cSEd Cashin return; 16226583303cSEd Cashin } 16237159e969SEd Cashin if (h->minor == 0xff) { 16247159e969SEd Cashin pr_info("aoe: e%ld.%d: broadcast slot number invalid\n", 16257159e969SEd Cashin aoemajor, (int) h->minor); 16261da177e4SLinus Torvalds return; 16271da177e4SLinus Torvalds } 16281da177e4SLinus Torvalds 162919bf2635SEd L. Cashin n = be16_to_cpu(ch->bufcnt); 16307df620d8SEd L. Cashin if (n > aoe_maxout) /* keep it reasonable */ 16317df620d8SEd L. Cashin n = aoe_maxout; 16321da177e4SLinus Torvalds 16337159e969SEd Cashin d = aoedev_by_aoeaddr(aoemajor, h->minor, 1); 16347159e969SEd Cashin if (d == NULL) { 16357159e969SEd Cashin pr_info("aoe: device allocation failure\n"); 16367159e969SEd Cashin return; 16377159e969SEd Cashin } 16387159e969SEd Cashin 16391da177e4SLinus Torvalds spin_lock_irqsave(&d->lock, flags); 16401da177e4SLinus Torvalds 164168e0d42fSEd L. Cashin t = gettgt(d, h->src); 16421b8a1636SEd Cashin if (t) { 16431b8a1636SEd Cashin t->nframes = n; 16441b8a1636SEd Cashin if (n < t->maxout) 16453a0c40d2SEd Cashin aoecmd_wreset(t); 16461b8a1636SEd Cashin } else { 164768e0d42fSEd L. Cashin t = addtgt(d, h->src, n); 164869cf2d85SEd Cashin if (!t) 164969cf2d85SEd Cashin goto bail; 165068e0d42fSEd L. Cashin } 16513f0f0133SEd Cashin n = skb->dev->mtu; 165219bf2635SEd L. Cashin n -= sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr); 165319bf2635SEd L. Cashin n /= 512; 165419bf2635SEd L. Cashin if (n > ch->scnt) 165519bf2635SEd L. Cashin n = ch->scnt; 16564f51dc5eSEd L. Cashin n = n ? n * 512 : DEFAULTBCNT; 16573f0f0133SEd Cashin setifbcnt(t, skb->dev, n); 16583ae1c24eSEd L. Cashin 16593ae1c24eSEd L. Cashin /* don't change users' perspective */ 166069cf2d85SEd Cashin if (d->nopen == 0) { 166163e9cc5dSecashin@coraid.com d->fw_ver = be16_to_cpu(ch->fwver); 166268e0d42fSEd L. Cashin sl = aoecmd_ata_id(d); 166369cf2d85SEd Cashin } 166469cf2d85SEd Cashin bail: 16651da177e4SLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 166669cf2d85SEd Cashin aoedev_put(d); 1667e9bb8fb0SDavid S. Miller if (sl) { 1668e9bb8fb0SDavid S. Miller __skb_queue_head_init(&queue); 1669e9bb8fb0SDavid S. Miller __skb_queue_tail(&queue, sl); 1670e9bb8fb0SDavid S. Miller aoenet_xmit(&queue); 1671e9bb8fb0SDavid S. Miller } 16721da177e4SLinus Torvalds } 16731da177e4SLinus Torvalds 167468e0d42fSEd L. Cashin void 16753a0c40d2SEd Cashin aoecmd_wreset(struct aoetgt *t) 16763a0c40d2SEd Cashin { 16773a0c40d2SEd Cashin t->maxout = 1; 16783a0c40d2SEd Cashin t->ssthresh = t->nframes / 2; 16793a0c40d2SEd Cashin t->next_cwnd = t->nframes; 16803a0c40d2SEd Cashin } 16813a0c40d2SEd Cashin 16823a0c40d2SEd Cashin void 168368e0d42fSEd L. Cashin aoecmd_cleanslate(struct aoedev *d) 168468e0d42fSEd L. Cashin { 168568e0d42fSEd L. Cashin struct aoetgt **t, **te; 168668e0d42fSEd L. Cashin 16873a0c40d2SEd Cashin d->rttavg = RTTAVG_INIT; 16883a0c40d2SEd Cashin d->rttdev = RTTDEV_INIT; 16893f0f0133SEd Cashin d->maxbcnt = 0; 169068e0d42fSEd L. Cashin 169168e0d42fSEd L. Cashin t = d->targets; 169271114ec4SEd Cashin te = t + d->ntargets; 16933f0f0133SEd Cashin for (; t < te && *t; t++) 16943a0c40d2SEd Cashin aoecmd_wreset(*t); 169568e0d42fSEd L. Cashin } 1696896831f5SEd Cashin 169769cf2d85SEd Cashin void 169869cf2d85SEd Cashin aoe_failbuf(struct aoedev *d, struct buf *buf) 169969cf2d85SEd Cashin { 170069cf2d85SEd Cashin if (buf == NULL) 170169cf2d85SEd Cashin return; 170269cf2d85SEd Cashin buf->resid = 0; 170369cf2d85SEd Cashin clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); 170469cf2d85SEd Cashin if (buf->nframesout == 0) 170569cf2d85SEd Cashin aoe_end_buf(d, buf); 170669cf2d85SEd Cashin } 170769cf2d85SEd Cashin 170869cf2d85SEd Cashin void 170969cf2d85SEd Cashin aoe_flush_iocq(void) 1710896831f5SEd Cashin { 1711896831f5SEd Cashin struct frame *f; 1712896831f5SEd Cashin struct aoedev *d; 1713896831f5SEd Cashin LIST_HEAD(flist); 1714896831f5SEd Cashin struct list_head *pos; 1715896831f5SEd Cashin struct sk_buff *skb; 1716896831f5SEd Cashin ulong flags; 1717896831f5SEd Cashin 1718896831f5SEd Cashin spin_lock_irqsave(&iocq.lock, flags); 1719896831f5SEd Cashin list_splice_init(&iocq.head, &flist); 1720896831f5SEd Cashin spin_unlock_irqrestore(&iocq.lock, flags); 1721896831f5SEd Cashin while (!list_empty(&flist)) { 1722896831f5SEd Cashin pos = flist.next; 1723896831f5SEd Cashin list_del(pos); 1724896831f5SEd Cashin f = list_entry(pos, struct frame, head); 1725896831f5SEd Cashin d = f->t->d; 1726896831f5SEd Cashin skb = f->r_skb; 1727896831f5SEd Cashin spin_lock_irqsave(&d->lock, flags); 1728896831f5SEd Cashin if (f->buf) { 1729896831f5SEd Cashin f->buf->nframesout--; 1730896831f5SEd Cashin aoe_failbuf(d, f->buf); 1731896831f5SEd Cashin } 1732896831f5SEd Cashin aoe_freetframe(f); 1733896831f5SEd Cashin spin_unlock_irqrestore(&d->lock, flags); 1734896831f5SEd Cashin dev_kfree_skb(skb); 173569cf2d85SEd Cashin aoedev_put(d); 1736896831f5SEd Cashin } 1737896831f5SEd Cashin } 1738896831f5SEd Cashin 1739896831f5SEd Cashin int __init 1740896831f5SEd Cashin aoecmd_init(void) 1741896831f5SEd Cashin { 1742bbb44e30SEd Cashin void *p; 1743bbb44e30SEd Cashin 1744bbb44e30SEd Cashin /* get_zeroed_page returns page with ref count 1 */ 1745bbb44e30SEd Cashin p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); 1746bbb44e30SEd Cashin if (!p) 1747bbb44e30SEd Cashin return -ENOMEM; 1748bbb44e30SEd Cashin empty_page = virt_to_page(p); 1749bbb44e30SEd Cashin 1750896831f5SEd Cashin INIT_LIST_HEAD(&iocq.head); 1751896831f5SEd Cashin spin_lock_init(&iocq.lock); 1752896831f5SEd Cashin init_waitqueue_head(&ktiowq); 1753896831f5SEd Cashin kts.name = "aoe_ktio"; 1754896831f5SEd Cashin kts.fn = ktio; 1755896831f5SEd Cashin kts.waitq = &ktiowq; 1756896831f5SEd Cashin kts.lock = &iocq.lock; 1757896831f5SEd Cashin return aoe_ktstart(&kts); 1758896831f5SEd Cashin } 1759896831f5SEd Cashin 1760896831f5SEd Cashin void 1761896831f5SEd Cashin aoecmd_exit(void) 1762896831f5SEd Cashin { 1763896831f5SEd Cashin aoe_ktstop(&kts); 176469cf2d85SEd Cashin aoe_flush_iocq(); 1765bbb44e30SEd Cashin 1766bbb44e30SEd Cashin free_page((unsigned long) page_address(empty_page)); 1767bbb44e30SEd Cashin empty_page = NULL; 1768896831f5SEd Cashin } 1769