Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / drivers / block / aoe / aoecmd.c
index 621fdbb..8d17d8d 100644 (file)
 #define TIMERTICK (HZ / 10)
 #define MINTIMER (2 * TIMERTICK)
 #define MAXTIMER (HZ << 1)
-#define MAXWAIT (60 * 3)       /* After MAXWAIT seconds, give up and fail dev */
+
+static int aoe_deadsecs = 60 * 3;
+module_param(aoe_deadsecs, int, 0644);
+MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
 
 struct sk_buff *
 new_skb(ulong len)
@@ -27,8 +30,6 @@ new_skb(ulong len)
                skb->nh.raw = skb->mac.raw = skb->data;
                skb->protocol = __constant_htons(ETH_P_AOE);
                skb->priority = 0;
-               skb_put(skb, len);
-               memset(skb->head, 0, len);
                skb->next = skb->prev = NULL;
 
                /* tell the network layer not to perform IP checksums
@@ -119,7 +120,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
        skb = f->skb;
        h = (struct aoe_hdr *) skb->mac.raw;
        ah = (struct aoe_atahdr *) (h+1);
-       skb->len = sizeof *h + sizeof *ah;
+       skb_put(skb, sizeof *h + sizeof *ah);
        memset(h, 0, skb->len);
        f->tag = aoehdr_atainit(d, h);
        f->waited = 0;
@@ -143,9 +144,9 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
                skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
                        offset_in_page(f->bufaddr), bcnt);
                ah->aflags |= AOEAFL_WRITE;
+               skb->len += bcnt;
+               skb->data_len = bcnt;
        } else {
-               skb_shinfo(skb)->nr_frags = 0;
-               skb->len = ETH_ZLEN;
                writebit = 0;
        }
 
@@ -155,20 +156,22 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
        buf->nframesout += 1;
        buf->bufaddr += bcnt;
        buf->bv_resid -= bcnt;
-/* dprintk("bv_resid=%ld\n", buf->bv_resid); */
+/* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */
        buf->resid -= bcnt;
        buf->sector += bcnt >> 9;
        if (buf->resid == 0) {
                d->inprocess = NULL;
        } else if (buf->bv_resid == 0) {
                buf->bv++;
+               WARN_ON(buf->bv->bv_len == 0);
                buf->bv_resid = buf->bv->bv_len;
                buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
        }
 
        skb->dev = d->ifp;
-       skb_get(skb);
-       skb->next = NULL;
+       skb = skb_clone(skb, GFP_ATOMIC);
+       if (skb == NULL)
+               return;
        if (d->sendq_hd)
                d->sendq_tl->next = skb;
        else
@@ -197,9 +200,10 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
 
                skb = new_skb(sizeof *h + sizeof *ch);
                if (skb == NULL) {
-                       iprintk("skb alloc failure\n");
+                       printk(KERN_INFO "aoe: skb alloc failure\n");
                        continue;
                }
+               skb_put(skb, sizeof *h + sizeof *ch);
                skb->dev = ifp;
                if (sl_tail == NULL)
                        sl_tail = skb;
@@ -224,6 +228,30 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
        return sl;
 }
 
+static struct frame *
+freeframe(struct aoedev *d)
+{
+       struct frame *f, *e;
+       int n = 0;
+
+       f = d->frames;
+       e = f + d->nframes;
+       for (; f<e; f++) {
+               if (f->tag != FREETAG)
+                       continue;
+               if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) {
+                       skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
+                       skb_trim(f->skb, 0);
+                       return f;
+               }
+               n++;
+       }
+       if (n == d->nframes)    /* wait for network layer */
+               d->flags |= DEVFL_KICKME;
+
+       return NULL;
+}
+
 /* enters with d->lock held */
 void
 aoecmd_work(struct aoedev *d)
@@ -239,7 +267,7 @@ aoecmd_work(struct aoedev *d)
        }
 
 loop:
-       f = getframe(d, FREETAG);
+       f = freeframe(d);
        if (f == NULL)
                return;
        if (d->inprocess == NULL) {
@@ -247,7 +275,7 @@ loop:
                        return;
                buf = container_of(d->bufq.next, struct buf, bufs);
                list_del(d->bufq.next);
-/*dprintk("bi_size=%ld\n", buf->bio->bi_size); */
+/*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */
                d->inprocess = buf;
        }
        aoecmd_ata_rw(d, f);
@@ -282,20 +310,25 @@ rexmit(struct aoedev *d, struct frame *f)
        n = DEFAULTBCNT / 512;
        if (ah->scnt > n) {
                ah->scnt = n;
-               if (ah->aflags & AOEAFL_WRITE)
+               if (ah->aflags & AOEAFL_WRITE) {
                        skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
                                offset_in_page(f->bufaddr), DEFAULTBCNT);
+                       skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT;
+                       skb->data_len = DEFAULTBCNT;
+               }
                if (++d->lostjumbo > (d->nframes << 1))
                if (d->maxbcnt != DEFAULTBCNT) {
-                       iprintk("too many lost jumbo - using 1KB frames.\n");
+                       printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n",
+                               d->aoemajor, d->aoeminor, d->ifp->name);
                        d->maxbcnt = DEFAULTBCNT;
                        d->flags |= DEVFL_MAXBCNT;
                }
        }
 
        skb->dev = d->ifp;
-       skb_get(skb);
-       skb->next = NULL;
+       skb = skb_clone(skb, GFP_ATOMIC);
+       if (skb == NULL)
+               return;
        if (d->sendq_hd)
                d->sendq_tl->next = skb;
        else
@@ -343,13 +376,17 @@ rexmit_timer(ulong vp)
                if (f->tag != FREETAG && tsince(f->tag) >= timeout) {
                        n = f->waited += timeout;
                        n /= HZ;
-                       if (n > MAXWAIT) { /* waited too long.  device failure. */
+                       if (n > aoe_deadsecs) { /* waited too long for response */
                                aoedev_downdev(d);
                                break;
                        }
                        rexmit(d, f);
                }
        }
+       if (d->flags & DEVFL_KICKME) {
+               d->flags &= ~DEVFL_KICKME;
+               aoecmd_work(d);
+       }
 
        sl = d->sendq_hd;
        d->sendq_hd = d->sendq_tl = NULL;
@@ -370,9 +407,9 @@ rexmit_timer(ulong vp)
 /* this function performs work that has been deferred until sleeping is OK
  */
 void
-aoecmd_sleepwork(void *vp)
+aoecmd_sleepwork(struct work_struct *work)
 {
-       struct aoedev *d = (struct aoedev *) vp;
+       struct aoedev *d = container_of(work, struct aoedev, work);
 
        if (d->flags & DEVFL_GDALLOC)
                aoeblk_gdalloc(d);
@@ -434,7 +471,7 @@ ataid_complete(struct aoedev *d, unsigned char *id)
        }
 
        if (d->ssize != ssize)
-               iprintk("%012llx e%lu.%lu v%04x has %llu sectors\n",
+               printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n",
                        (unsigned long long)mac_addr(d->addr),
                        d->aoemajor, d->aoeminor,
                        d->fw_ver, (long long)ssize);
@@ -445,7 +482,7 @@ ataid_complete(struct aoedev *d, unsigned char *id)
                d->flags |= DEVFL_NEWSIZE;
        } else {
                if (d->flags & DEVFL_GDALLOC) {
-                       eprintk("can't schedule work for e%lu.%lu, %s\n",
+                       printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n",
                               d->aoemajor, d->aoeminor,
                               "it's already on!  This shouldn't happen.\n");
                        return;
@@ -461,8 +498,15 @@ calc_rttavg(struct aoedev *d, int rtt)
        register long n;
 
        n = rtt;
-       if (n < MINTIMER)
-               n = MINTIMER;
+       if (n < 0) {
+               n = -rtt;
+               if (n < MINTIMER)
+                       n = MINTIMER;
+               else if (n > MAXTIMER)
+                       n = MAXTIMER;
+               d->mintimer += (n - d->mintimer) >> 1;
+       } else if (n < d->mintimer)
+               n = d->mintimer;
        else if (n > MAXTIMER)
                n = MAXTIMER;
 
@@ -486,7 +530,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
        u16 aoemajor;
 
        hin = (struct aoe_hdr *) skb->mac.raw;
-       aoemajor = be16_to_cpu(hin->major);
+       aoemajor = be16_to_cpu(get_unaligned(&hin->major));
        d = aoedev_by_aoeaddr(aoemajor, hin->minor);
        if (d == NULL) {
                snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
@@ -498,15 +542,17 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 
        spin_lock_irqsave(&d->lock, flags);
 
-       f = getframe(d, be32_to_cpu(hin->tag));
+       n = be32_to_cpu(get_unaligned(&hin->tag));
+       f = getframe(d, n);
        if (f == NULL) {
+               calc_rttavg(d, -tsince(n));
                spin_unlock_irqrestore(&d->lock, flags);
                snprintf(ebuf, sizeof ebuf,
                        "%15s e%d.%d    tag=%08x@%08lx\n",
                        "unexpected rsp",
-                       be16_to_cpu(hin->major),
+                       be16_to_cpu(get_unaligned(&hin->major)),
                        hin->minor,
-                       be32_to_cpu(hin->tag),
+                       be32_to_cpu(get_unaligned(&hin->tag)),
                        jiffies);
                aoechr_error(ebuf);
                return;
@@ -522,7 +568,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)
        if (ahout->cmdstat == WIN_IDENTIFY)
                d->flags &= ~DEVFL_PAUSE;
        if (ahin->cmdstat & 0xa9) {     /* these bits cleared on success */
-               eprintk("ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n",
+               printk(KERN_ERR
+                       "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n",
                        ahout->cmdstat, ahin->cmdstat,
                        d->aoemajor, d->aoeminor);
                if (buf)
@@ -533,7 +580,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                case WIN_READ:
                case WIN_READ_EXT:
                        if (skb->len - sizeof *hin - sizeof *ahin < n) {
-                               eprintk("runt data size in read.  skb->len=%d\n",
+                               printk(KERN_ERR
+                                       "aoe: runt data size in read.  skb->len=%d\n",
                                        skb->len);
                                /* fail frame f?  just returning will rexmit. */
                                spin_unlock_irqrestore(&d->lock, flags);
@@ -543,23 +591,27 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                case WIN_WRITE:
                case WIN_WRITE_EXT:
                        if (f->bcnt -= n) {
+                               skb = f->skb;
                                f->bufaddr += n;
                                put_lba(ahout, f->lba += ahout->scnt);
                                n = f->bcnt;
                                if (n > DEFAULTBCNT)
                                        n = DEFAULTBCNT;
                                ahout->scnt = n >> 9;
-                               if (ahout->aflags & AOEAFL_WRITE)
-                                       skb_fill_page_desc(f->skb, 0,
+                               if (ahout->aflags & AOEAFL_WRITE) {
+                                       skb_fill_page_desc(skb, 0,
                                                virt_to_page(f->bufaddr),
                                                offset_in_page(f->bufaddr), n);
+                                       skb->len = sizeof *hout + sizeof *ahout + n;
+                                       skb->data_len = n;
+                               }
                                f->tag = newtag(d);
                                hout->tag = cpu_to_be32(f->tag);
                                skb->dev = d->ifp;
-                               skb_get(f->skb);
-                               f->skb->next = NULL;
+                               skb = skb_clone(skb, GFP_ATOMIC);
                                spin_unlock_irqrestore(&d->lock, flags);
-                               aoenet_xmit(f->skb);
+                               if (skb)
+                                       aoenet_xmit(skb);
                                return;
                        }
                        if (n > DEFAULTBCNT)
@@ -567,7 +619,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                        break;
                case WIN_IDENTIFY:
                        if (skb->len - sizeof *hin - sizeof *ahin < 512) {
-                               iprintk("runt data size in ataid.  skb->len=%d\n",
+                               printk(KERN_INFO
+                                       "aoe: runt data size in ataid.  skb->len=%d\n",
                                        skb->len);
                                spin_unlock_irqrestore(&d->lock, flags);
                                return;
@@ -575,9 +628,10 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                        ataid_complete(d, (char *) (ahin+1));
                        break;
                default:
-                       iprintk("unrecognized ata command %2.2Xh for %d.%d\n",
+                       printk(KERN_INFO
+                               "aoe: unrecognized ata command %2.2Xh for %d.%d\n",
                                ahout->cmdstat,
-                               be16_to_cpu(hin->major),
+                               be16_to_cpu(get_unaligned(&hin->major)),
                                hin->minor);
                }
        }
@@ -633,9 +687,9 @@ aoecmd_ata_id(struct aoedev *d)
        struct frame *f;
        struct sk_buff *skb;
 
-       f = getframe(d, FREETAG);
+       f = freeframe(d);
        if (f == NULL) {
-               eprintk("can't get a frame. This shouldn't happen.\n");
+               printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n");
                return NULL;
        }
 
@@ -643,7 +697,7 @@ aoecmd_ata_id(struct aoedev *d)
        skb = f->skb;
        h = (struct aoe_hdr *) skb->mac.raw;
        ah = (struct aoe_atahdr *) (h+1);
-       skb->len = sizeof *h + sizeof *ah;
+       skb_put(skb, sizeof *h + sizeof *ah);
        memset(h, 0, skb->len);
        f->tag = aoehdr_atainit(d, h);
        f->waited = 0;
@@ -654,12 +708,11 @@ aoecmd_ata_id(struct aoedev *d)
        ah->lba3 = 0xa0;
 
        skb->dev = d->ifp;
-       skb_get(skb);
 
        d->rttavg = MAXTIMER;
        d->timer.function = rexmit_timer;
 
-       return skb;
+       return skb_clone(skb, GFP_ATOMIC);
 }
  
 void
@@ -680,16 +733,16 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
         * Enough people have their dip switches set backwards to
         * warrant a loud message for this special case.
         */
-       aoemajor = be16_to_cpu(h->major);
+       aoemajor = be16_to_cpu(get_unaligned(&h->major));
        if (aoemajor == 0xfff) {
-               eprintk("Warning: shelf address is all ones.  "
+               printk(KERN_ERR "aoe: Warning: shelf address is all ones.  "
                        "Check shelf dip switches.\n");
                return;
        }
 
        sysminor = SYSMINOR(aoemajor, h->minor);
        if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) {
-               iprintk("e%ld.%d: minor number too large\n",
+               printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n",
                        aoemajor, (int) h->minor);
                return;
        }
@@ -700,7 +753,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
 
        d = aoedev_by_sysminor_m(sysminor, n);
        if (d == NULL) {
-               iprintk("device sysminor_m failure\n");
+               printk(KERN_INFO "aoe: device sysminor_m failure\n");
                return;
        }
 
@@ -715,7 +768,13 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
                n /= 512;
                if (n > ch->scnt)
                        n = ch->scnt;
-               d->maxbcnt = n ? n * 512 : DEFAULTBCNT;
+               n = n ? n * 512 : DEFAULTBCNT;
+               if (n != d->maxbcnt) {
+                       printk(KERN_INFO
+                               "aoe: e%ld.%ld: setting %d byte data frames on %s\n",
+                               d->aoemajor, d->aoeminor, n, d->ifp->name);
+                       d->maxbcnt = n;
+               }
        }
 
        /* don't change users' perspective */
@@ -724,6 +783,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
                return;
        }
        d->flags |= DEVFL_PAUSE;        /* force pause */
+       d->mintimer = MINTIMER;
        d->fw_ver = be16_to_cpu(ch->fwver);
 
        /* check for already outstanding ataid */