rd: support XIP
[powerpc.git] / drivers / block / aoe / aoedev.c
index c7e05ed..51f5071 100644 (file)
@@ -63,22 +63,32 @@ aoedev_newdev(ulong nframes)
        struct frame *f, *e;
 
        d = kzalloc(sizeof *d, GFP_ATOMIC);
-       if (d == NULL)
-               return NULL;
        f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
-       if (f == NULL) {
-               kfree(d);
+       switch (!d || !f) {
+       case 0:
+               d->nframes = nframes;
+               d->frames = f;
+               e = f + nframes;
+               for (; f<e; f++) {
+                       f->tag = FREETAG;
+                       f->skb = new_skb(ETH_ZLEN);
+                       if (!f->skb)
+                               break;
+               }
+               if (f == e)
+                       break;
+               while (f > d->frames) {
+                       f--;
+                       dev_kfree_skb(f->skb);
+               }
+       default:
+               if (f)
+                       kfree(f);
+               if (d)
+                       kfree(d);
                return NULL;
        }
-
-       INIT_WORK(&d->work, aoecmd_sleepwork, d);
-
-       d->nframes = nframes;
-       d->frames = f;
-       e = f + nframes;
-       for (; f<e; f++)
-               f->tag = FREETAG;
-
+       INIT_WORK(&d->work, aoecmd_sleepwork);
        spin_lock_init(&d->lock);
        init_timer(&d->timer);
        d->timer.data = (ulong) d;
@@ -109,8 +119,9 @@ aoedev_downdev(struct aoedev *d)
                bio = buf->bio;
                if (--buf->nframesout == 0) {
                        mempool_free(buf, d->bufpool);
-                       bio_endio(bio, bio->bi_size, -EIO);
+                       bio_endio(bio, -EIO);
                }
+               skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
        }
        d->inprocess = NULL;
 
@@ -119,7 +130,7 @@ aoedev_downdev(struct aoedev *d)
                list_del(d->bufq.next);
                bio = buf->bio;
                mempool_free(buf, d->bufpool);
-               bio_endio(bio, bio->bi_size, -EIO);
+               bio_endio(bio, -EIO);
        }
 
        if (d->gd)
@@ -145,7 +156,7 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
                d = aoedev_newdev(bufcnt);
                if (d == NULL) {
                        spin_unlock_irqrestore(&devlist_lock, flags);
-                       printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
+                       printk(KERN_INFO "aoe: aoedev_newdev failure.\n");
                        return NULL;
                }
                d->sysminor = sysminor;
@@ -160,11 +171,19 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
 static void
 aoedev_freedev(struct aoedev *d)
 {
+       struct frame *f, *e;
+
        if (d->gd) {
                aoedisk_rm_sysfs(d);
                del_gendisk(d->gd);
                put_disk(d->gd);
        }
+       f = d->frames;
+       e = f + d->nframes;
+       for (; f<e; f++) {
+               skb_shinfo(f->skb)->nr_frags = 0;
+               dev_kfree_skb(f->skb);
+       }
        kfree(d->frames);
        if (d->bufpool)
                mempool_destroy(d->bufpool);