diff options
| -rw-r--r-- | drivers/block/aoe/aoe.h | 30 | ||||
| -rw-r--r-- | drivers/block/aoe/aoeblk.c | 44 | ||||
| -rw-r--r-- | drivers/block/aoe/aoechr.c | 18 | ||||
| -rw-r--r-- | drivers/block/aoe/aoecmd.c | 303 | ||||
| -rw-r--r-- | drivers/block/aoe/aoedev.c | 52 | ||||
| -rw-r--r-- | drivers/block/aoe/aoemain.c | 10 | ||||
| -rw-r--r-- | drivers/block/aoe/aoenet.c | 9 |
7 files changed, 287 insertions, 179 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 6eebcb7be97e..6d111228cfac 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | #define VERSION "22" | 2 | #define VERSION "32" |
| 3 | #define AOE_MAJOR 152 | 3 | #define AOE_MAJOR 152 |
| 4 | #define DEVICE_NAME "aoe" | 4 | #define DEVICE_NAME "aoe" |
| 5 | 5 | ||
| @@ -65,7 +65,7 @@ struct aoe_atahdr { | |||
| 65 | struct aoe_cfghdr { | 65 | struct aoe_cfghdr { |
| 66 | __be16 bufcnt; | 66 | __be16 bufcnt; |
| 67 | __be16 fwver; | 67 | __be16 fwver; |
| 68 | unsigned char res; | 68 | unsigned char scnt; |
| 69 | unsigned char aoeccmd; | 69 | unsigned char aoeccmd; |
| 70 | unsigned char cslen[2]; | 70 | unsigned char cslen[2]; |
| 71 | }; | 71 | }; |
| @@ -78,12 +78,14 @@ enum { | |||
| 78 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ | 78 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ |
| 79 | DEVFL_PAUSE = (1<<5), | 79 | DEVFL_PAUSE = (1<<5), |
| 80 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ | 80 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ |
| 81 | DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */ | ||
| 82 | DEVFL_KICKME = (1<<8), | ||
| 81 | 83 | ||
| 82 | BUFFL_FAIL = 1, | 84 | BUFFL_FAIL = 1, |
| 83 | }; | 85 | }; |
| 84 | 86 | ||
| 85 | enum { | 87 | enum { |
| 86 | MAXATADATA = 1024, | 88 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ |
| 87 | NPERSHELF = 16, /* number of slots per shelf address */ | 89 | NPERSHELF = 16, /* number of slots per shelf address */ |
| 88 | FREETAG = -1, | 90 | FREETAG = -1, |
| 89 | MIN_BUFS = 8, | 91 | MIN_BUFS = 8, |
| @@ -107,11 +109,9 @@ struct frame { | |||
| 107 | ulong waited; | 109 | ulong waited; |
| 108 | struct buf *buf; | 110 | struct buf *buf; |
| 109 | char *bufaddr; | 111 | char *bufaddr; |
| 110 | int writedatalen; | 112 | ulong bcnt; |
| 111 | int ndata; | 113 | sector_t lba; |
| 112 | 114 | struct sk_buff *skb; | |
| 113 | /* largest possible */ | ||
| 114 | unsigned char data[sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr)]; | ||
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | struct aoedev { | 117 | struct aoedev { |
| @@ -121,9 +121,12 @@ struct aoedev { | |||
| 121 | ulong sysminor; | 121 | ulong sysminor; |
| 122 | ulong aoemajor; | 122 | ulong aoemajor; |
| 123 | ulong aoeminor; | 123 | ulong aoeminor; |
| 124 | ulong nopen; /* (bd_openers isn't available without sleeping) */ | 124 | u16 nopen; /* (bd_openers isn't available without sleeping) */ |
| 125 | ulong rttavg; /* round trip average of requests/responses */ | 125 | u16 lasttag; /* last tag sent */ |
| 126 | u16 rttavg; /* round trip average of requests/responses */ | ||
| 127 | u16 mintimer; | ||
| 126 | u16 fw_ver; /* version of blade's firmware */ | 128 | u16 fw_ver; /* version of blade's firmware */ |
| 129 | u16 maxbcnt; | ||
| 127 | struct work_struct work;/* disk create work struct */ | 130 | struct work_struct work;/* disk create work struct */ |
| 128 | struct gendisk *gd; | 131 | struct gendisk *gd; |
| 129 | request_queue_t blkq; | 132 | request_queue_t blkq; |
| @@ -137,8 +140,8 @@ struct aoedev { | |||
| 137 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ | 140 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ |
| 138 | struct list_head bufq; /* queue of bios to work on */ | 141 | struct list_head bufq; /* queue of bios to work on */ |
| 139 | struct buf *inprocess; /* the one we're currently working on */ | 142 | struct buf *inprocess; /* the one we're currently working on */ |
| 140 | ulong lasttag; /* last tag sent */ | 143 | ushort lostjumbo; |
| 141 | ulong nframes; /* number of frames below */ | 144 | ushort nframes; /* number of frames below */ |
| 142 | struct frame *frames; | 145 | struct frame *frames; |
| 143 | }; | 146 | }; |
| 144 | 147 | ||
| @@ -157,6 +160,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | |||
| 157 | void aoecmd_ata_rsp(struct sk_buff *); | 160 | void aoecmd_ata_rsp(struct sk_buff *); |
| 158 | void aoecmd_cfg_rsp(struct sk_buff *); | 161 | void aoecmd_cfg_rsp(struct sk_buff *); |
| 159 | void aoecmd_sleepwork(void *vp); | 162 | void aoecmd_sleepwork(void *vp); |
| 163 | struct sk_buff *new_skb(ulong); | ||
| 160 | 164 | ||
| 161 | int aoedev_init(void); | 165 | int aoedev_init(void); |
| 162 | void aoedev_exit(void); | 166 | void aoedev_exit(void); |
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 393b86a3dbf8..d433f27e0ce2 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoeblk.c | 3 | * aoeblk.c |
| 4 | * block device routines | 4 | * block device routines |
| @@ -14,7 +14,6 @@ | |||
| 14 | 14 | ||
| 15 | static kmem_cache_t *buf_pool_cache; | 15 | static kmem_cache_t *buf_pool_cache; |
| 16 | 16 | ||
| 17 | /* add attributes for our block devices in sysfs */ | ||
| 18 | static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) | 17 | static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) |
| 19 | { | 18 | { |
| 20 | struct aoedev *d = disk->private_data; | 19 | struct aoedev *d = disk->private_data; |
| @@ -64,21 +63,26 @@ static struct disk_attribute disk_attr_fwver = { | |||
| 64 | .show = aoedisk_show_fwver | 63 | .show = aoedisk_show_fwver |
| 65 | }; | 64 | }; |
| 66 | 65 | ||
| 67 | static void | 66 | static struct attribute *aoe_attrs[] = { |
| 67 | &disk_attr_state.attr, | ||
| 68 | &disk_attr_mac.attr, | ||
| 69 | &disk_attr_netif.attr, | ||
| 70 | &disk_attr_fwver.attr, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static const struct attribute_group attr_group = { | ||
| 74 | .attrs = aoe_attrs, | ||
| 75 | }; | ||
| 76 | |||
| 77 | static int | ||
| 68 | aoedisk_add_sysfs(struct aoedev *d) | 78 | aoedisk_add_sysfs(struct aoedev *d) |
| 69 | { | 79 | { |
| 70 | sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr); | 80 | return sysfs_create_group(&d->gd->kobj, &attr_group); |
| 71 | sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr); | ||
| 72 | sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr); | ||
| 73 | sysfs_create_file(&d->gd->kobj, &disk_attr_fwver.attr); | ||
| 74 | } | 81 | } |
| 75 | void | 82 | void |
| 76 | aoedisk_rm_sysfs(struct aoedev *d) | 83 | aoedisk_rm_sysfs(struct aoedev *d) |
| 77 | { | 84 | { |
| 78 | sysfs_remove_link(&d->gd->kobj, "state"); | 85 | sysfs_remove_group(&d->gd->kobj, &attr_group); |
| 79 | sysfs_remove_link(&d->gd->kobj, "mac"); | ||
| 80 | sysfs_remove_link(&d->gd->kobj, "netif"); | ||
| 81 | sysfs_remove_link(&d->gd->kobj, "firmware-version"); | ||
| 82 | } | 86 | } |
| 83 | 87 | ||
| 84 | static int | 88 | static int |
| @@ -132,8 +136,7 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) | |||
| 132 | d = bio->bi_bdev->bd_disk->private_data; | 136 | d = bio->bi_bdev->bd_disk->private_data; |
| 133 | buf = mempool_alloc(d->bufpool, GFP_NOIO); | 137 | buf = mempool_alloc(d->bufpool, GFP_NOIO); |
| 134 | if (buf == NULL) { | 138 | if (buf == NULL) { |
| 135 | printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation " | 139 | printk(KERN_INFO "aoe: buf allocation failure\n"); |
| 136 | "failure\n"); | ||
| 137 | bio_endio(bio, bio->bi_size, -ENOMEM); | 140 | bio_endio(bio, bio->bi_size, -ENOMEM); |
| 138 | return 0; | 141 | return 0; |
| 139 | } | 142 | } |
| @@ -143,14 +146,15 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) | |||
| 143 | buf->bio = bio; | 146 | buf->bio = bio; |
| 144 | buf->resid = bio->bi_size; | 147 | buf->resid = bio->bi_size; |
| 145 | buf->sector = bio->bi_sector; | 148 | buf->sector = bio->bi_sector; |
| 146 | buf->bv = buf->bio->bi_io_vec; | 149 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; |
| 150 | WARN_ON(buf->bv->bv_len == 0); | ||
| 147 | buf->bv_resid = buf->bv->bv_len; | 151 | buf->bv_resid = buf->bv->bv_len; |
| 148 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 152 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; |
| 149 | 153 | ||
| 150 | spin_lock_irqsave(&d->lock, flags); | 154 | spin_lock_irqsave(&d->lock, flags); |
| 151 | 155 | ||
| 152 | if ((d->flags & DEVFL_UP) == 0) { | 156 | if ((d->flags & DEVFL_UP) == 0) { |
| 153 | printk(KERN_INFO "aoe: aoeblk_make_request: device %ld.%ld is not up\n", | 157 | printk(KERN_INFO "aoe: device %ld.%ld is not up\n", |
| 154 | d->aoemajor, d->aoeminor); | 158 | d->aoemajor, d->aoeminor); |
| 155 | spin_unlock_irqrestore(&d->lock, flags); | 159 | spin_unlock_irqrestore(&d->lock, flags); |
| 156 | mempool_free(buf, d->bufpool); | 160 | mempool_free(buf, d->bufpool); |
| @@ -176,7 +180,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
| 176 | struct aoedev *d = bdev->bd_disk->private_data; | 180 | struct aoedev *d = bdev->bd_disk->private_data; |
| 177 | 181 | ||
| 178 | if ((d->flags & DEVFL_UP) == 0) { | 182 | if ((d->flags & DEVFL_UP) == 0) { |
| 179 | printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); | 183 | printk(KERN_ERR "aoe: disk not up\n"); |
| 180 | return -ENODEV; | 184 | return -ENODEV; |
| 181 | } | 185 | } |
| 182 | 186 | ||
| @@ -203,8 +207,8 @@ aoeblk_gdalloc(void *vp) | |||
| 203 | 207 | ||
| 204 | gd = alloc_disk(AOE_PARTITIONS); | 208 | gd = alloc_disk(AOE_PARTITIONS); |
| 205 | if (gd == NULL) { | 209 | if (gd == NULL) { |
| 206 | printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk " | 210 | printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n", |
| 207 | "structure for %ld.%ld\n", d->aoemajor, d->aoeminor); | 211 | d->aoemajor, d->aoeminor); |
| 208 | spin_lock_irqsave(&d->lock, flags); | 212 | spin_lock_irqsave(&d->lock, flags); |
| 209 | d->flags &= ~DEVFL_GDALLOC; | 213 | d->flags &= ~DEVFL_GDALLOC; |
| 210 | spin_unlock_irqrestore(&d->lock, flags); | 214 | spin_unlock_irqrestore(&d->lock, flags); |
| @@ -213,8 +217,8 @@ aoeblk_gdalloc(void *vp) | |||
| 213 | 217 | ||
| 214 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); | 218 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); |
| 215 | if (d->bufpool == NULL) { | 219 | if (d->bufpool == NULL) { |
| 216 | printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool " | 220 | printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n", |
| 217 | "for %ld.%ld\n", d->aoemajor, d->aoeminor); | 221 | d->aoemajor, d->aoeminor); |
| 218 | put_disk(gd); | 222 | put_disk(gd); |
| 219 | spin_lock_irqsave(&d->lock, flags); | 223 | spin_lock_irqsave(&d->lock, flags); |
| 220 | d->flags &= ~DEVFL_GDALLOC; | 224 | d->flags &= ~DEVFL_GDALLOC; |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 1bc1cf9603f1..e22b4c9520a9 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoechr.c | 3 | * aoechr.c |
| 4 | * AoE character device driver | 4 | * AoE character device driver |
| @@ -15,7 +15,6 @@ enum { | |||
| 15 | MINOR_INTERFACES, | 15 | MINOR_INTERFACES, |
| 16 | MINOR_REVALIDATE, | 16 | MINOR_REVALIDATE, |
| 17 | MSGSZ = 2048, | 17 | MSGSZ = 2048, |
| 18 | NARGS = 10, | ||
| 19 | NMSG = 100, /* message backlog to retain */ | 18 | NMSG = 100, /* message backlog to retain */ |
| 20 | }; | 19 | }; |
| 21 | 20 | ||
| @@ -56,9 +55,8 @@ static int | |||
| 56 | interfaces(const char __user *str, size_t size) | 55 | interfaces(const char __user *str, size_t size) |
| 57 | { | 56 | { |
| 58 | if (set_aoe_iflist(str, size)) { | 57 | if (set_aoe_iflist(str, size)) { |
| 59 | printk(KERN_CRIT | 58 | printk(KERN_ERR |
| 60 | "%s: could not set interface list: %s\n", | 59 | "aoe: could not set interface list: too many interfaces\n"); |
| 61 | __FUNCTION__, "too many interfaces"); | ||
| 62 | return -EINVAL; | 60 | return -EINVAL; |
| 63 | } | 61 | } |
| 64 | return 0; | 62 | return 0; |
| @@ -81,8 +79,7 @@ revalidate(const char __user *str, size_t size) | |||
| 81 | /* should be e%d.%d format */ | 79 | /* should be e%d.%d format */ |
| 82 | n = sscanf(buf, "e%d.%d", &major, &minor); | 80 | n = sscanf(buf, "e%d.%d", &major, &minor); |
| 83 | if (n != 2) { | 81 | if (n != 2) { |
| 84 | printk(KERN_ERR "aoe: %s: invalid device specification\n", | 82 | printk(KERN_ERR "aoe: invalid device specification\n"); |
| 85 | __FUNCTION__); | ||
| 86 | return -EINVAL; | 83 | return -EINVAL; |
| 87 | } | 84 | } |
| 88 | d = aoedev_by_aoeaddr(major, minor); | 85 | d = aoedev_by_aoeaddr(major, minor); |
| @@ -90,6 +87,7 @@ revalidate(const char __user *str, size_t size) | |||
| 90 | return -EINVAL; | 87 | return -EINVAL; |
| 91 | 88 | ||
| 92 | spin_lock_irqsave(&d->lock, flags); | 89 | spin_lock_irqsave(&d->lock, flags); |
| 90 | d->flags &= ~DEVFL_MAXBCNT; | ||
| 93 | d->flags |= DEVFL_PAUSE; | 91 | d->flags |= DEVFL_PAUSE; |
| 94 | spin_unlock_irqrestore(&d->lock, flags); | 92 | spin_unlock_irqrestore(&d->lock, flags); |
| 95 | aoecmd_cfg(major, minor); | 93 | aoecmd_cfg(major, minor); |
| @@ -116,7 +114,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags); | |||
| 116 | 114 | ||
| 117 | mp = kmalloc(n, GFP_ATOMIC); | 115 | mp = kmalloc(n, GFP_ATOMIC); |
| 118 | if (mp == NULL) { | 116 | if (mp == NULL) { |
| 119 | printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n); | 117 | printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n); |
| 120 | goto bail; | 118 | goto bail; |
| 121 | } | 119 | } |
| 122 | 120 | ||
| @@ -141,7 +139,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp | |||
| 141 | 139 | ||
| 142 | switch ((unsigned long) filp->private_data) { | 140 | switch ((unsigned long) filp->private_data) { |
| 143 | default: | 141 | default: |
| 144 | printk(KERN_INFO "aoe: aoechr_write: can't write to that file.\n"); | 142 | printk(KERN_INFO "aoe: can't write to that file.\n"); |
| 145 | break; | 143 | break; |
| 146 | case MINOR_DISCOVER: | 144 | case MINOR_DISCOVER: |
| 147 | ret = discover(); | 145 | ret = discover(); |
| @@ -250,7 +248,7 @@ aoechr_init(void) | |||
| 250 | 248 | ||
| 251 | n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); | 249 | n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); |
| 252 | if (n < 0) { | 250 | if (n < 0) { |
| 253 | printk(KERN_ERR "aoe: aoechr_init: can't register char device\n"); | 251 | printk(KERN_ERR "aoe: can't register char device\n"); |
| 254 | return n; | 252 | return n; |
| 255 | } | 253 | } |
| 256 | sema_init(&emsgs_sema, 0); | 254 | sema_init(&emsgs_sema, 0); |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 39da28d344fe..8a13b1af8bab 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoecmd.c | 3 | * aoecmd.c |
| 4 | * Filesystem request handling methods | 4 | * Filesystem request handling methods |
| @@ -15,17 +15,19 @@ | |||
| 15 | #define TIMERTICK (HZ / 10) | 15 | #define TIMERTICK (HZ / 10) |
| 16 | #define MINTIMER (2 * TIMERTICK) | 16 | #define MINTIMER (2 * TIMERTICK) |
| 17 | #define MAXTIMER (HZ << 1) | 17 | #define MAXTIMER (HZ << 1) |
| 18 | #define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */ | ||
| 19 | 18 | ||
| 20 | static struct sk_buff * | 19 | static int aoe_deadsecs = 60 * 3; |
| 21 | new_skb(struct net_device *if_dev, ulong len) | 20 | module_param(aoe_deadsecs, int, 0644); |
| 21 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | ||
| 22 | |||
| 23 | struct sk_buff * | ||
| 24 | new_skb(ulong len) | ||
| 22 | { | 25 | { |
| 23 | struct sk_buff *skb; | 26 | struct sk_buff *skb; |
| 24 | 27 | ||
| 25 | skb = alloc_skb(len, GFP_ATOMIC); | 28 | skb = alloc_skb(len, GFP_ATOMIC); |
| 26 | if (skb) { | 29 | if (skb) { |
| 27 | skb->nh.raw = skb->mac.raw = skb->data; | 30 | skb->nh.raw = skb->mac.raw = skb->data; |
| 28 | skb->dev = if_dev; | ||
| 29 | skb->protocol = __constant_htons(ETH_P_AOE); | 31 | skb->protocol = __constant_htons(ETH_P_AOE); |
| 30 | skb->priority = 0; | 32 | skb->priority = 0; |
| 31 | skb_put(skb, len); | 33 | skb_put(skb, len); |
| @@ -40,29 +42,6 @@ new_skb(struct net_device *if_dev, ulong len) | |||
| 40 | return skb; | 42 | return skb; |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | static struct sk_buff * | ||
| 44 | skb_prepare(struct aoedev *d, struct frame *f) | ||
| 45 | { | ||
| 46 | struct sk_buff *skb; | ||
| 47 | char *p; | ||
| 48 | |||
| 49 | skb = new_skb(d->ifp, f->ndata + f->writedatalen); | ||
| 50 | if (!skb) { | ||
| 51 | printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n"); | ||
| 52 | return NULL; | ||
| 53 | } | ||
| 54 | |||
| 55 | p = skb->mac.raw; | ||
| 56 | memcpy(p, f->data, f->ndata); | ||
| 57 | |||
| 58 | if (f->writedatalen) { | ||
| 59 | p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr); | ||
| 60 | memcpy(p, f->bufaddr, f->writedatalen); | ||
| 61 | } | ||
| 62 | |||
| 63 | return skb; | ||
| 64 | } | ||
| 65 | |||
| 66 | static struct frame * | 45 | static struct frame * |
| 67 | getframe(struct aoedev *d, int tag) | 46 | getframe(struct aoedev *d, int tag) |
| 68 | { | 47 | { |
| @@ -107,6 +86,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) | |||
| 107 | return host_tag; | 86 | return host_tag; |
| 108 | } | 87 | } |
| 109 | 88 | ||
| 89 | static inline void | ||
| 90 | put_lba(struct aoe_atahdr *ah, sector_t lba) | ||
| 91 | { | ||
| 92 | ah->lba0 = lba; | ||
| 93 | ah->lba1 = lba >>= 8; | ||
| 94 | ah->lba2 = lba >>= 8; | ||
| 95 | ah->lba3 = lba >>= 8; | ||
| 96 | ah->lba4 = lba >>= 8; | ||
| 97 | ah->lba5 = lba >>= 8; | ||
| 98 | } | ||
| 99 | |||
| 110 | static void | 100 | static void |
| 111 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 101 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) |
| 112 | { | 102 | { |
| @@ -125,29 +115,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
| 125 | 115 | ||
| 126 | sector = buf->sector; | 116 | sector = buf->sector; |
| 127 | bcnt = buf->bv_resid; | 117 | bcnt = buf->bv_resid; |
| 128 | if (bcnt > MAXATADATA) | 118 | if (bcnt > d->maxbcnt) |
| 129 | bcnt = MAXATADATA; | 119 | bcnt = d->maxbcnt; |
| 130 | 120 | ||
| 131 | /* initialize the headers & frame */ | 121 | /* initialize the headers & frame */ |
| 132 | h = (struct aoe_hdr *) f->data; | 122 | skb = f->skb; |
| 123 | h = (struct aoe_hdr *) skb->mac.raw; | ||
| 133 | ah = (struct aoe_atahdr *) (h+1); | 124 | ah = (struct aoe_atahdr *) (h+1); |
| 134 | f->ndata = sizeof *h + sizeof *ah; | 125 | skb->len = sizeof *h + sizeof *ah; |
| 135 | memset(h, 0, f->ndata); | 126 | memset(h, 0, ETH_ZLEN); |
| 136 | f->tag = aoehdr_atainit(d, h); | 127 | f->tag = aoehdr_atainit(d, h); |
| 137 | f->waited = 0; | 128 | f->waited = 0; |
| 138 | f->buf = buf; | 129 | f->buf = buf; |
| 139 | f->bufaddr = buf->bufaddr; | 130 | f->bufaddr = buf->bufaddr; |
| 131 | f->bcnt = bcnt; | ||
| 132 | f->lba = sector; | ||
| 140 | 133 | ||
| 141 | /* set up ata header */ | 134 | /* set up ata header */ |
| 142 | ah->scnt = bcnt >> 9; | 135 | ah->scnt = bcnt >> 9; |
| 143 | ah->lba0 = sector; | 136 | put_lba(ah, sector); |
| 144 | ah->lba1 = sector >>= 8; | ||
| 145 | ah->lba2 = sector >>= 8; | ||
| 146 | ah->lba3 = sector >>= 8; | ||
| 147 | if (d->flags & DEVFL_EXT) { | 137 | if (d->flags & DEVFL_EXT) { |
| 148 | ah->aflags |= AOEAFL_EXT; | 138 | ah->aflags |= AOEAFL_EXT; |
| 149 | ah->lba4 = sector >>= 8; | ||
| 150 | ah->lba5 = sector >>= 8; | ||
| 151 | } else { | 139 | } else { |
| 152 | extbit = 0; | 140 | extbit = 0; |
| 153 | ah->lba3 &= 0x0f; | 141 | ah->lba3 &= 0x0f; |
| @@ -155,11 +143,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
| 155 | } | 143 | } |
| 156 | 144 | ||
| 157 | if (bio_data_dir(buf->bio) == WRITE) { | 145 | if (bio_data_dir(buf->bio) == WRITE) { |
| 146 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | ||
| 147 | offset_in_page(f->bufaddr), bcnt); | ||
| 158 | ah->aflags |= AOEAFL_WRITE; | 148 | ah->aflags |= AOEAFL_WRITE; |
| 159 | f->writedatalen = bcnt; | 149 | skb->len += bcnt; |
| 150 | skb->data_len = bcnt; | ||
| 160 | } else { | 151 | } else { |
| 152 | skb->len = ETH_ZLEN; | ||
| 161 | writebit = 0; | 153 | writebit = 0; |
| 162 | f->writedatalen = 0; | ||
| 163 | } | 154 | } |
| 164 | 155 | ||
| 165 | ah->cmdstat = WIN_READ | writebit | extbit; | 156 | ah->cmdstat = WIN_READ | writebit | extbit; |
| @@ -168,26 +159,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
| 168 | buf->nframesout += 1; | 159 | buf->nframesout += 1; |
| 169 | buf->bufaddr += bcnt; | 160 | buf->bufaddr += bcnt; |
| 170 | buf->bv_resid -= bcnt; | 161 | buf->bv_resid -= bcnt; |
| 171 | /* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */ | 162 | /* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ |
| 172 | buf->resid -= bcnt; | 163 | buf->resid -= bcnt; |
| 173 | buf->sector += bcnt >> 9; | 164 | buf->sector += bcnt >> 9; |
| 174 | if (buf->resid == 0) { | 165 | if (buf->resid == 0) { |
| 175 | d->inprocess = NULL; | 166 | d->inprocess = NULL; |
| 176 | } else if (buf->bv_resid == 0) { | 167 | } else if (buf->bv_resid == 0) { |
| 177 | buf->bv++; | 168 | buf->bv++; |
| 169 | WARN_ON(buf->bv->bv_len == 0); | ||
| 178 | buf->bv_resid = buf->bv->bv_len; | 170 | buf->bv_resid = buf->bv->bv_len; |
| 179 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 171 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; |
| 180 | } | 172 | } |
| 181 | 173 | ||
| 182 | skb = skb_prepare(d, f); | 174 | skb->dev = d->ifp; |
| 183 | if (skb) { | 175 | skb = skb_clone(skb, GFP_ATOMIC); |
| 184 | skb->next = NULL; | 176 | if (skb == NULL) |
| 185 | if (d->sendq_hd) | 177 | return; |
| 186 | d->sendq_tl->next = skb; | 178 | if (d->sendq_hd) |
| 187 | else | 179 | d->sendq_tl->next = skb; |
| 188 | d->sendq_hd = skb; | 180 | else |
| 189 | d->sendq_tl = skb; | 181 | d->sendq_hd = skb; |
| 190 | } | 182 | d->sendq_tl = skb; |
| 191 | } | 183 | } |
| 192 | 184 | ||
| 193 | /* some callers cannot sleep, and they can call this function, | 185 | /* some callers cannot sleep, and they can call this function, |
| @@ -209,11 +201,12 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) | |||
| 209 | if (!is_aoe_netif(ifp)) | 201 | if (!is_aoe_netif(ifp)) |
| 210 | continue; | 202 | continue; |
| 211 | 203 | ||
| 212 | skb = new_skb(ifp, sizeof *h + sizeof *ch); | 204 | skb = new_skb(sizeof *h + sizeof *ch); |
| 213 | if (skb == NULL) { | 205 | if (skb == NULL) { |
| 214 | printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); | 206 | printk(KERN_INFO "aoe: skb alloc failure\n"); |
| 215 | continue; | 207 | continue; |
| 216 | } | 208 | } |
| 209 | skb->dev = ifp; | ||
| 217 | if (sl_tail == NULL) | 210 | if (sl_tail == NULL) |
| 218 | sl_tail = skb; | 211 | sl_tail = skb; |
| 219 | h = (struct aoe_hdr *) skb->mac.raw; | 212 | h = (struct aoe_hdr *) skb->mac.raw; |
| @@ -237,6 +230,29 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) | |||
| 237 | return sl; | 230 | return sl; |
| 238 | } | 231 | } |
| 239 | 232 | ||
| 233 | static struct frame * | ||
| 234 | freeframe(struct aoedev *d) | ||
| 235 | { | ||
| 236 | struct frame *f, *e; | ||
| 237 | int n = 0; | ||
| 238 | |||
| 239 | f = d->frames; | ||
| 240 | e = f + d->nframes; | ||
| 241 | for (; f<e; f++) { | ||
| 242 | if (f->tag != FREETAG) | ||
| 243 | continue; | ||
| 244 | if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) { | ||
| 245 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
| 246 | return f; | ||
| 247 | } | ||
| 248 | n++; | ||
| 249 | } | ||
| 250 | if (n == d->nframes) /* wait for network layer */ | ||
| 251 | d->flags |= DEVFL_KICKME; | ||
| 252 | |||
| 253 | return NULL; | ||
| 254 | } | ||
| 255 | |||
| 240 | /* enters with d->lock held */ | 256 | /* enters with d->lock held */ |
| 241 | void | 257 | void |
| 242 | aoecmd_work(struct aoedev *d) | 258 | aoecmd_work(struct aoedev *d) |
| @@ -252,7 +268,7 @@ aoecmd_work(struct aoedev *d) | |||
| 252 | } | 268 | } |
| 253 | 269 | ||
| 254 | loop: | 270 | loop: |
| 255 | f = getframe(d, FREETAG); | 271 | f = freeframe(d); |
| 256 | if (f == NULL) | 272 | if (f == NULL) |
| 257 | return; | 273 | return; |
| 258 | if (d->inprocess == NULL) { | 274 | if (d->inprocess == NULL) { |
| @@ -260,7 +276,7 @@ loop: | |||
| 260 | return; | 276 | return; |
| 261 | buf = container_of(d->bufq.next, struct buf, bufs); | 277 | buf = container_of(d->bufq.next, struct buf, bufs); |
| 262 | list_del(d->bufq.next); | 278 | list_del(d->bufq.next); |
| 263 | /*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */ | 279 | /*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */ |
| 264 | d->inprocess = buf; | 280 | d->inprocess = buf; |
| 265 | } | 281 | } |
| 266 | aoecmd_ata_rw(d, f); | 282 | aoecmd_ata_rw(d, f); |
| @@ -272,6 +288,7 @@ rexmit(struct aoedev *d, struct frame *f) | |||
| 272 | { | 288 | { |
| 273 | struct sk_buff *skb; | 289 | struct sk_buff *skb; |
| 274 | struct aoe_hdr *h; | 290 | struct aoe_hdr *h; |
| 291 | struct aoe_atahdr *ah; | ||
| 275 | char buf[128]; | 292 | char buf[128]; |
| 276 | u32 n; | 293 | u32 n; |
| 277 | 294 | ||
| @@ -283,21 +300,41 @@ rexmit(struct aoedev *d, struct frame *f) | |||
| 283 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); | 300 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); |
| 284 | aoechr_error(buf); | 301 | aoechr_error(buf); |
| 285 | 302 | ||
| 286 | h = (struct aoe_hdr *) f->data; | 303 | skb = f->skb; |
| 304 | h = (struct aoe_hdr *) skb->mac.raw; | ||
| 305 | ah = (struct aoe_atahdr *) (h+1); | ||
| 287 | f->tag = n; | 306 | f->tag = n; |
| 288 | h->tag = cpu_to_be32(n); | 307 | h->tag = cpu_to_be32(n); |
| 289 | memcpy(h->dst, d->addr, sizeof h->dst); | 308 | memcpy(h->dst, d->addr, sizeof h->dst); |
| 290 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 309 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); |
| 291 | 310 | ||
| 292 | skb = skb_prepare(d, f); | 311 | n = DEFAULTBCNT / 512; |
| 293 | if (skb) { | 312 | if (ah->scnt > n) { |
| 294 | skb->next = NULL; | 313 | ah->scnt = n; |
| 295 | if (d->sendq_hd) | 314 | if (ah->aflags & AOEAFL_WRITE) { |
| 296 | d->sendq_tl->next = skb; | 315 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), |
| 297 | else | 316 | offset_in_page(f->bufaddr), DEFAULTBCNT); |
| 298 | d->sendq_hd = skb; | 317 | skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; |
| 299 | d->sendq_tl = skb; | 318 | skb->data_len = DEFAULTBCNT; |
| 319 | } | ||
| 320 | if (++d->lostjumbo > (d->nframes << 1)) | ||
| 321 | if (d->maxbcnt != DEFAULTBCNT) { | ||
| 322 | printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", | ||
| 323 | d->aoemajor, d->aoeminor, d->ifp->name); | ||
| 324 | d->maxbcnt = DEFAULTBCNT; | ||
| 325 | d->flags |= DEVFL_MAXBCNT; | ||
| 326 | } | ||
| 300 | } | 327 | } |
| 328 | |||
| 329 | skb->dev = d->ifp; | ||
| 330 | skb = skb_clone(skb, GFP_ATOMIC); | ||
| 331 | if (skb == NULL) | ||
| 332 | return; | ||
| 333 | if (d->sendq_hd) | ||
| 334 | d->sendq_tl->next = skb; | ||
| 335 | else | ||
| 336 | d->sendq_hd = skb; | ||
| 337 | d->sendq_tl = skb; | ||
| 301 | } | 338 | } |
| 302 | 339 | ||
| 303 | static int | 340 | static int |
| @@ -340,13 +377,17 @@ rexmit_timer(ulong vp) | |||
| 340 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { | 377 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { |
| 341 | n = f->waited += timeout; | 378 | n = f->waited += timeout; |
| 342 | n /= HZ; | 379 | n /= HZ; |
| 343 | if (n > MAXWAIT) { /* waited too long. device failure. */ | 380 | if (n > aoe_deadsecs) { /* waited too long for response */ |
| 344 | aoedev_downdev(d); | 381 | aoedev_downdev(d); |
| 345 | break; | 382 | break; |
| 346 | } | 383 | } |
| 347 | rexmit(d, f); | 384 | rexmit(d, f); |
| 348 | } | 385 | } |
| 349 | } | 386 | } |
| 387 | if (d->flags & DEVFL_KICKME) { | ||
| 388 | d->flags &= ~DEVFL_KICKME; | ||
| 389 | aoecmd_work(d); | ||
| 390 | } | ||
| 350 | 391 | ||
| 351 | sl = d->sendq_hd; | 392 | sl = d->sendq_hd; |
| 352 | d->sendq_hd = d->sendq_tl = NULL; | 393 | d->sendq_hd = d->sendq_tl = NULL; |
| @@ -431,8 +472,8 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
| 431 | } | 472 | } |
| 432 | 473 | ||
| 433 | if (d->ssize != ssize) | 474 | if (d->ssize != ssize) |
| 434 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu " | 475 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", |
| 435 | "sectors\n", (unsigned long long)mac_addr(d->addr), | 476 | (unsigned long long)mac_addr(d->addr), |
| 436 | d->aoemajor, d->aoeminor, | 477 | d->aoemajor, d->aoeminor, |
| 437 | d->fw_ver, (long long)ssize); | 478 | d->fw_ver, (long long)ssize); |
| 438 | d->ssize = ssize; | 479 | d->ssize = ssize; |
| @@ -442,11 +483,9 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
| 442 | d->flags |= DEVFL_NEWSIZE; | 483 | d->flags |= DEVFL_NEWSIZE; |
| 443 | } else { | 484 | } else { |
| 444 | if (d->flags & DEVFL_GDALLOC) { | 485 | if (d->flags & DEVFL_GDALLOC) { |
| 445 | printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n", | 486 | printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n", |
| 446 | __FUNCTION__, | ||
| 447 | "can't schedule work for", | ||
| 448 | d->aoemajor, d->aoeminor, | 487 | d->aoemajor, d->aoeminor, |
| 449 | "it's already on! (This really shouldn't happen).\n"); | 488 | "it's already on! This shouldn't happen.\n"); |
| 450 | return; | 489 | return; |
| 451 | } | 490 | } |
| 452 | d->flags |= DEVFL_GDALLOC; | 491 | d->flags |= DEVFL_GDALLOC; |
| @@ -460,8 +499,15 @@ calc_rttavg(struct aoedev *d, int rtt) | |||
| 460 | register long n; | 499 | register long n; |
| 461 | 500 | ||
| 462 | n = rtt; | 501 | n = rtt; |
| 463 | if (n < MINTIMER) | 502 | if (n < 0) { |
| 464 | n = MINTIMER; | 503 | n = -rtt; |
| 504 | if (n < MINTIMER) | ||
| 505 | n = MINTIMER; | ||
| 506 | else if (n > MAXTIMER) | ||
| 507 | n = MAXTIMER; | ||
| 508 | d->mintimer += (n - d->mintimer) >> 1; | ||
| 509 | } else if (n < d->mintimer) | ||
| 510 | n = d->mintimer; | ||
| 465 | else if (n > MAXTIMER) | 511 | else if (n > MAXTIMER) |
| 466 | n = MAXTIMER; | 512 | n = MAXTIMER; |
| 467 | 513 | ||
| @@ -474,7 +520,7 @@ void | |||
| 474 | aoecmd_ata_rsp(struct sk_buff *skb) | 520 | aoecmd_ata_rsp(struct sk_buff *skb) |
| 475 | { | 521 | { |
| 476 | struct aoedev *d; | 522 | struct aoedev *d; |
| 477 | struct aoe_hdr *hin; | 523 | struct aoe_hdr *hin, *hout; |
| 478 | struct aoe_atahdr *ahin, *ahout; | 524 | struct aoe_atahdr *ahin, *ahout; |
| 479 | struct frame *f; | 525 | struct frame *f; |
| 480 | struct buf *buf; | 526 | struct buf *buf; |
| @@ -497,8 +543,10 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
| 497 | 543 | ||
| 498 | spin_lock_irqsave(&d->lock, flags); | 544 | spin_lock_irqsave(&d->lock, flags); |
| 499 | 545 | ||
| 500 | f = getframe(d, be32_to_cpu(hin->tag)); | 546 | n = be32_to_cpu(hin->tag); |
| 547 | f = getframe(d, n); | ||
| 501 | if (f == NULL) { | 548 | if (f == NULL) { |
| 549 | calc_rttavg(d, -tsince(n)); | ||
| 502 | spin_unlock_irqrestore(&d->lock, flags); | 550 | spin_unlock_irqrestore(&d->lock, flags); |
| 503 | snprintf(ebuf, sizeof ebuf, | 551 | snprintf(ebuf, sizeof ebuf, |
| 504 | "%15s e%d.%d tag=%08x@%08lx\n", | 552 | "%15s e%d.%d tag=%08x@%08lx\n", |
| @@ -514,26 +562,27 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
| 514 | calc_rttavg(d, tsince(f->tag)); | 562 | calc_rttavg(d, tsince(f->tag)); |
| 515 | 563 | ||
| 516 | ahin = (struct aoe_atahdr *) (hin+1); | 564 | ahin = (struct aoe_atahdr *) (hin+1); |
| 517 | ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr)); | 565 | hout = (struct aoe_hdr *) f->skb->mac.raw; |
| 566 | ahout = (struct aoe_atahdr *) (hout+1); | ||
| 518 | buf = f->buf; | 567 | buf = f->buf; |
| 519 | 568 | ||
| 520 | if (ahout->cmdstat == WIN_IDENTIFY) | 569 | if (ahout->cmdstat == WIN_IDENTIFY) |
| 521 | d->flags &= ~DEVFL_PAUSE; | 570 | d->flags &= ~DEVFL_PAUSE; |
| 522 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | 571 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ |
| 523 | printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh " | 572 | printk(KERN_ERR |
| 524 | "stat=%2.2Xh from e%ld.%ld\n", | 573 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", |
| 525 | ahout->cmdstat, ahin->cmdstat, | 574 | ahout->cmdstat, ahin->cmdstat, |
| 526 | d->aoemajor, d->aoeminor); | 575 | d->aoemajor, d->aoeminor); |
| 527 | if (buf) | 576 | if (buf) |
| 528 | buf->flags |= BUFFL_FAIL; | 577 | buf->flags |= BUFFL_FAIL; |
| 529 | } else { | 578 | } else { |
| 579 | n = ahout->scnt << 9; | ||
| 530 | switch (ahout->cmdstat) { | 580 | switch (ahout->cmdstat) { |
| 531 | case WIN_READ: | 581 | case WIN_READ: |
| 532 | case WIN_READ_EXT: | 582 | case WIN_READ_EXT: |
| 533 | n = ahout->scnt << 9; | ||
| 534 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | 583 | if (skb->len - sizeof *hin - sizeof *ahin < n) { |
| 535 | printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " | 584 | printk(KERN_ERR |
| 536 | "ata data size in read. skb->len=%d\n", | 585 | "aoe: runt data size in read. skb->len=%d\n", |
| 537 | skb->len); | 586 | skb->len); |
| 538 | /* fail frame f? just returning will rexmit. */ | 587 | /* fail frame f? just returning will rexmit. */ |
| 539 | spin_unlock_irqrestore(&d->lock, flags); | 588 | spin_unlock_irqrestore(&d->lock, flags); |
| @@ -542,22 +591,49 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
| 542 | memcpy(f->bufaddr, ahin+1, n); | 591 | memcpy(f->bufaddr, ahin+1, n); |
| 543 | case WIN_WRITE: | 592 | case WIN_WRITE: |
| 544 | case WIN_WRITE_EXT: | 593 | case WIN_WRITE_EXT: |
| 594 | if (f->bcnt -= n) { | ||
| 595 | skb = f->skb; | ||
| 596 | f->bufaddr += n; | ||
| 597 | put_lba(ahout, f->lba += ahout->scnt); | ||
| 598 | n = f->bcnt; | ||
| 599 | if (n > DEFAULTBCNT) | ||
| 600 | n = DEFAULTBCNT; | ||
| 601 | ahout->scnt = n >> 9; | ||
| 602 | if (ahout->aflags & AOEAFL_WRITE) { | ||
| 603 | skb_fill_page_desc(skb, 0, | ||
| 604 | virt_to_page(f->bufaddr), | ||
| 605 | offset_in_page(f->bufaddr), n); | ||
| 606 | skb->len = sizeof *hout + sizeof *ahout + n; | ||
| 607 | skb->data_len = n; | ||
| 608 | } | ||
| 609 | f->tag = newtag(d); | ||
| 610 | hout->tag = cpu_to_be32(f->tag); | ||
| 611 | skb->dev = d->ifp; | ||
| 612 | skb = skb_clone(skb, GFP_ATOMIC); | ||
| 613 | spin_unlock_irqrestore(&d->lock, flags); | ||
| 614 | if (skb) | ||
| 615 | aoenet_xmit(skb); | ||
| 616 | return; | ||
| 617 | } | ||
| 618 | if (n > DEFAULTBCNT) | ||
| 619 | d->lostjumbo = 0; | ||
| 545 | break; | 620 | break; |
| 546 | case WIN_IDENTIFY: | 621 | case WIN_IDENTIFY: |
| 547 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | 622 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { |
| 548 | printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size " | 623 | printk(KERN_INFO |
| 549 | "in ataid. skb->len=%d\n", skb->len); | 624 | "aoe: runt data size in ataid. skb->len=%d\n", |
| 625 | skb->len); | ||
| 550 | spin_unlock_irqrestore(&d->lock, flags); | 626 | spin_unlock_irqrestore(&d->lock, flags); |
| 551 | return; | 627 | return; |
| 552 | } | 628 | } |
| 553 | ataid_complete(d, (char *) (ahin+1)); | 629 | ataid_complete(d, (char *) (ahin+1)); |
| 554 | break; | 630 | break; |
| 555 | default: | 631 | default: |
| 556 | printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized " | 632 | printk(KERN_INFO |
| 557 | "outbound ata command %2.2Xh for %d.%d\n", | 633 | "aoe: unrecognized ata command %2.2Xh for %d.%d\n", |
| 558 | ahout->cmdstat, | 634 | ahout->cmdstat, |
| 559 | be16_to_cpu(hin->major), | 635 | be16_to_cpu(hin->major), |
| 560 | hin->minor); | 636 | hin->minor); |
| 561 | } | 637 | } |
| 562 | } | 638 | } |
| 563 | 639 | ||
| @@ -612,33 +688,32 @@ aoecmd_ata_id(struct aoedev *d) | |||
| 612 | struct frame *f; | 688 | struct frame *f; |
| 613 | struct sk_buff *skb; | 689 | struct sk_buff *skb; |
| 614 | 690 | ||
| 615 | f = getframe(d, FREETAG); | 691 | f = freeframe(d); |
| 616 | if (f == NULL) { | 692 | if (f == NULL) { |
| 617 | printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame. " | 693 | printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); |
| 618 | "This shouldn't happen.\n"); | ||
| 619 | return NULL; | 694 | return NULL; |
| 620 | } | 695 | } |
| 621 | 696 | ||
| 622 | /* initialize the headers & frame */ | 697 | /* initialize the headers & frame */ |
| 623 | h = (struct aoe_hdr *) f->data; | 698 | skb = f->skb; |
| 699 | h = (struct aoe_hdr *) skb->mac.raw; | ||
| 624 | ah = (struct aoe_atahdr *) (h+1); | 700 | ah = (struct aoe_atahdr *) (h+1); |
| 625 | f->ndata = sizeof *h + sizeof *ah; | 701 | skb->len = ETH_ZLEN; |
| 626 | memset(h, 0, f->ndata); | 702 | memset(h, 0, ETH_ZLEN); |
| 627 | f->tag = aoehdr_atainit(d, h); | 703 | f->tag = aoehdr_atainit(d, h); |
| 628 | f->waited = 0; | 704 | f->waited = 0; |
| 629 | f->writedatalen = 0; | ||
| 630 | 705 | ||
| 631 | /* set up ata header */ | 706 | /* set up ata header */ |
| 632 | ah->scnt = 1; | 707 | ah->scnt = 1; |
| 633 | ah->cmdstat = WIN_IDENTIFY; | 708 | ah->cmdstat = WIN_IDENTIFY; |
| 634 | ah->lba3 = 0xa0; | 709 | ah->lba3 = 0xa0; |
| 635 | 710 | ||
| 636 | skb = skb_prepare(d, f); | 711 | skb->dev = d->ifp; |
| 637 | 712 | ||
| 638 | d->rttavg = MAXTIMER; | 713 | d->rttavg = MAXTIMER; |
| 639 | d->timer.function = rexmit_timer; | 714 | d->timer.function = rexmit_timer; |
| 640 | 715 | ||
| 641 | return skb; | 716 | return skb_clone(skb, GFP_ATOMIC); |
| 642 | } | 717 | } |
| 643 | 718 | ||
| 644 | void | 719 | void |
| @@ -648,9 +723,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 648 | struct aoe_hdr *h; | 723 | struct aoe_hdr *h; |
| 649 | struct aoe_cfghdr *ch; | 724 | struct aoe_cfghdr *ch; |
| 650 | ulong flags, sysminor, aoemajor; | 725 | ulong flags, sysminor, aoemajor; |
| 651 | u16 bufcnt; | ||
| 652 | struct sk_buff *sl; | 726 | struct sk_buff *sl; |
| 653 | enum { MAXFRAMES = 16 }; | 727 | enum { MAXFRAMES = 16 }; |
| 728 | u16 n; | ||
| 654 | 729 | ||
| 655 | h = (struct aoe_hdr *) skb->mac.raw; | 730 | h = (struct aoe_hdr *) skb->mac.raw; |
| 656 | ch = (struct aoe_cfghdr *) (h+1); | 731 | ch = (struct aoe_cfghdr *) (h+1); |
| @@ -661,26 +736,25 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 661 | */ | 736 | */ |
| 662 | aoemajor = be16_to_cpu(h->major); | 737 | aoemajor = be16_to_cpu(h->major); |
| 663 | if (aoemajor == 0xfff) { | 738 | if (aoemajor == 0xfff) { |
| 664 | printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf " | 739 | printk(KERN_ERR "aoe: Warning: shelf address is all ones. " |
| 665 | "address is all ones. Check shelf dip switches\n"); | 740 | "Check shelf dip switches.\n"); |
| 666 | return; | 741 | return; |
| 667 | } | 742 | } |
| 668 | 743 | ||
| 669 | sysminor = SYSMINOR(aoemajor, h->minor); | 744 | sysminor = SYSMINOR(aoemajor, h->minor); |
| 670 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { | 745 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { |
| 671 | printk(KERN_INFO | 746 | printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n", |
| 672 | "aoe: e%ld.%d: minor number too large\n", | ||
| 673 | aoemajor, (int) h->minor); | 747 | aoemajor, (int) h->minor); |
| 674 | return; | 748 | return; |
| 675 | } | 749 | } |
| 676 | 750 | ||
| 677 | bufcnt = be16_to_cpu(ch->bufcnt); | 751 | n = be16_to_cpu(ch->bufcnt); |
| 678 | if (bufcnt > MAXFRAMES) /* keep it reasonable */ | 752 | if (n > MAXFRAMES) /* keep it reasonable */ |
| 679 | bufcnt = MAXFRAMES; | 753 | n = MAXFRAMES; |
| 680 | 754 | ||
| 681 | d = aoedev_by_sysminor_m(sysminor, bufcnt); | 755 | d = aoedev_by_sysminor_m(sysminor, n); |
| 682 | if (d == NULL) { | 756 | if (d == NULL) { |
| 683 | printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); | 757 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); |
| 684 | return; | 758 | return; |
| 685 | } | 759 | } |
| 686 | 760 | ||
| @@ -689,6 +763,20 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 689 | /* permit device to migrate mac and network interface */ | 763 | /* permit device to migrate mac and network interface */ |
| 690 | d->ifp = skb->dev; | 764 | d->ifp = skb->dev; |
| 691 | memcpy(d->addr, h->src, sizeof d->addr); | 765 | memcpy(d->addr, h->src, sizeof d->addr); |
| 766 | if (!(d->flags & DEVFL_MAXBCNT)) { | ||
| 767 | n = d->ifp->mtu; | ||
| 768 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | ||
| 769 | n /= 512; | ||
| 770 | if (n > ch->scnt) | ||
| 771 | n = ch->scnt; | ||
| 772 | n = n ? n * 512 : DEFAULTBCNT; | ||
| 773 | if (n != d->maxbcnt) { | ||
| 774 | printk(KERN_INFO | ||
| 775 | "aoe: e%ld.%ld: setting %d byte data frames on %s\n", | ||
| 776 | d->aoemajor, d->aoeminor, n, d->ifp->name); | ||
| 777 | d->maxbcnt = n; | ||
| 778 | } | ||
| 779 | } | ||
| 692 | 780 | ||
| 693 | /* don't change users' perspective */ | 781 | /* don't change users' perspective */ |
| 694 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { | 782 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { |
| @@ -696,6 +784,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 696 | return; | 784 | return; |
| 697 | } | 785 | } |
| 698 | d->flags |= DEVFL_PAUSE; /* force pause */ | 786 | d->flags |= DEVFL_PAUSE; /* force pause */ |
| 787 | d->mintimer = MINTIMER; | ||
| 699 | d->fw_ver = be16_to_cpu(ch->fwver); | 788 | d->fw_ver = be16_to_cpu(ch->fwver); |
| 700 | 789 | ||
| 701 | /* check for already outstanding ataid */ | 790 | /* check for already outstanding ataid */ |
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index ed4258a62df5..6125921bbec4 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoedev.c | 3 | * aoedev.c |
| 4 | * AoE device utility functions; maintains device list. | 4 | * AoE device utility functions; maintains device list. |
| @@ -20,11 +20,8 @@ aoedev_isbusy(struct aoedev *d) | |||
| 20 | f = d->frames; | 20 | f = d->frames; |
| 21 | e = f + d->nframes; | 21 | e = f + d->nframes; |
| 22 | do { | 22 | do { |
| 23 | if (f->tag != FREETAG) { | 23 | if (f->tag != FREETAG) |
| 24 | printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n", | ||
| 25 | d->aoemajor, d->aoeminor); | ||
| 26 | return 1; | 24 | return 1; |
| 27 | } | ||
| 28 | } while (++f < e); | 25 | } while (++f < e); |
| 29 | 26 | ||
| 30 | return 0; | 27 | return 0; |
| @@ -66,22 +63,32 @@ aoedev_newdev(ulong nframes) | |||
| 66 | struct frame *f, *e; | 63 | struct frame *f, *e; |
| 67 | 64 | ||
| 68 | d = kzalloc(sizeof *d, GFP_ATOMIC); | 65 | d = kzalloc(sizeof *d, GFP_ATOMIC); |
| 69 | if (d == NULL) | ||
| 70 | return NULL; | ||
| 71 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | 66 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); |
| 72 | if (f == NULL) { | 67 | switch (!d || !f) { |
| 73 | kfree(d); | 68 | case 0: |
| 69 | d->nframes = nframes; | ||
| 70 | d->frames = f; | ||
| 71 | e = f + nframes; | ||
| 72 | for (; f<e; f++) { | ||
| 73 | f->tag = FREETAG; | ||
| 74 | f->skb = new_skb(ETH_ZLEN); | ||
| 75 | if (!f->skb) | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | if (f == e) | ||
| 79 | break; | ||
| 80 | while (f > d->frames) { | ||
| 81 | f--; | ||
| 82 | dev_kfree_skb(f->skb); | ||
| 83 | } | ||
| 84 | default: | ||
| 85 | if (f) | ||
| 86 | kfree(f); | ||
| 87 | if (d) | ||
| 88 | kfree(d); | ||
| 74 | return NULL; | 89 | return NULL; |
| 75 | } | 90 | } |
| 76 | |||
| 77 | INIT_WORK(&d->work, aoecmd_sleepwork, d); | 91 | INIT_WORK(&d->work, aoecmd_sleepwork, d); |
| 78 | |||
| 79 | d->nframes = nframes; | ||
| 80 | d->frames = f; | ||
| 81 | e = f + nframes; | ||
| 82 | for (; f<e; f++) | ||
| 83 | f->tag = FREETAG; | ||
| 84 | |||
| 85 | spin_lock_init(&d->lock); | 92 | spin_lock_init(&d->lock); |
| 86 | init_timer(&d->timer); | 93 | init_timer(&d->timer); |
| 87 | d->timer.data = (ulong) d; | 94 | d->timer.data = (ulong) d; |
| @@ -114,6 +121,7 @@ aoedev_downdev(struct aoedev *d) | |||
| 114 | mempool_free(buf, d->bufpool); | 121 | mempool_free(buf, d->bufpool); |
| 115 | bio_endio(bio, bio->bi_size, -EIO); | 122 | bio_endio(bio, bio->bi_size, -EIO); |
| 116 | } | 123 | } |
| 124 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
| 117 | } | 125 | } |
| 118 | d->inprocess = NULL; | 126 | d->inprocess = NULL; |
| 119 | 127 | ||
| @@ -148,7 +156,7 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
| 148 | d = aoedev_newdev(bufcnt); | 156 | d = aoedev_newdev(bufcnt); |
| 149 | if (d == NULL) { | 157 | if (d == NULL) { |
| 150 | spin_unlock_irqrestore(&devlist_lock, flags); | 158 | spin_unlock_irqrestore(&devlist_lock, flags); |
| 151 | printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); | 159 | printk(KERN_INFO "aoe: aoedev_newdev failure.\n"); |
| 152 | return NULL; | 160 | return NULL; |
| 153 | } | 161 | } |
| 154 | d->sysminor = sysminor; | 162 | d->sysminor = sysminor; |
| @@ -163,11 +171,19 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
| 163 | static void | 171 | static void |
| 164 | aoedev_freedev(struct aoedev *d) | 172 | aoedev_freedev(struct aoedev *d) |
| 165 | { | 173 | { |
| 174 | struct frame *f, *e; | ||
| 175 | |||
| 166 | if (d->gd) { | 176 | if (d->gd) { |
| 167 | aoedisk_rm_sysfs(d); | 177 | aoedisk_rm_sysfs(d); |
| 168 | del_gendisk(d->gd); | 178 | del_gendisk(d->gd); |
| 169 | put_disk(d->gd); | 179 | put_disk(d->gd); |
| 170 | } | 180 | } |
| 181 | f = d->frames; | ||
| 182 | e = f + d->nframes; | ||
| 183 | for (; f<e; f++) { | ||
| 184 | skb_shinfo(f->skb)->nr_frags = 0; | ||
| 185 | dev_kfree_skb(f->skb); | ||
| 186 | } | ||
| 171 | kfree(d->frames); | 187 | kfree(d->frames); |
| 172 | if (d->bufpool) | 188 | if (d->bufpool) |
| 173 | mempool_destroy(d->bufpool); | 189 | mempool_destroy(d->bufpool); |
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index de08491ebe66..a04b7d613299 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoemain.c | 3 | * aoemain.c |
| 4 | * Module initialization routines, discover timer | 4 | * Module initialization routines, discover timer |
| @@ -84,13 +84,11 @@ aoe_init(void) | |||
| 84 | goto net_fail; | 84 | goto net_fail; |
| 85 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); | 85 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); |
| 86 | if (ret < 0) { | 86 | if (ret < 0) { |
| 87 | printk(KERN_ERR "aoe: aoeblk_init: can't register major\n"); | 87 | printk(KERN_ERR "aoe: can't register major\n"); |
| 88 | goto blkreg_fail; | 88 | goto blkreg_fail; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | printk(KERN_INFO | 91 | printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); |
| 92 | "aoe: aoe_init: AoE v%s initialised.\n", | ||
| 93 | VERSION); | ||
| 94 | discover_timer(TINIT); | 92 | discover_timer(TINIT); |
| 95 | return 0; | 93 | return 0; |
| 96 | 94 | ||
| @@ -103,7 +101,7 @@ aoe_init(void) | |||
| 103 | chr_fail: | 101 | chr_fail: |
| 104 | aoedev_exit(); | 102 | aoedev_exit(); |
| 105 | 103 | ||
| 106 | printk(KERN_INFO "aoe: aoe_init: initialisation failure.\n"); | 104 | printk(KERN_INFO "aoe: initialisation failure.\n"); |
| 107 | return ret; | 105 | return ret; |
| 108 | } | 106 | } |
| 109 | 107 | ||
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index c1434ed11880..9626e0f5da9d 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoenet.c | 3 | * aoenet.c |
| 4 | * Ethernet portion of AoE driver | 4 | * Ethernet portion of AoE driver |
| @@ -74,7 +74,7 @@ set_aoe_iflist(const char __user *user_str, size_t size) | |||
| 74 | return -EINVAL; | 74 | return -EINVAL; |
| 75 | 75 | ||
| 76 | if (copy_from_user(aoe_iflist, user_str, size)) { | 76 | if (copy_from_user(aoe_iflist, user_str, size)) { |
| 77 | printk(KERN_INFO "aoe: %s: copy from user failed\n", __FUNCTION__); | 77 | printk(KERN_INFO "aoe: copy from user failed\n"); |
| 78 | return -EFAULT; | 78 | return -EFAULT; |
| 79 | } | 79 | } |
| 80 | aoe_iflist[size] = 0x00; | 80 | aoe_iflist[size] = 0x00; |
| @@ -132,8 +132,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
| 132 | if (n > NECODES) | 132 | if (n > NECODES) |
| 133 | n = 0; | 133 | n = 0; |
| 134 | if (net_ratelimit()) | 134 | if (net_ratelimit()) |
| 135 | printk(KERN_ERR "aoe: aoenet_rcv: error packet from %d.%d; " | 135 | printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n", |
| 136 | "ecode=%d '%s'\n", | ||
| 137 | be16_to_cpu(h->major), h->minor, | 136 | be16_to_cpu(h->major), h->minor, |
| 138 | h->err, aoe_errlist[n]); | 137 | h->err, aoe_errlist[n]); |
| 139 | goto exit; | 138 | goto exit; |
| @@ -147,7 +146,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
| 147 | aoecmd_cfg_rsp(skb); | 146 | aoecmd_cfg_rsp(skb); |
| 148 | break; | 147 | break; |
| 149 | default: | 148 | default: |
| 150 | printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %d\n", h->cmd); | 149 | printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd); |
| 151 | } | 150 | } |
| 152 | exit: | 151 | exit: |
| 153 | dev_kfree_skb(skb); | 152 | dev_kfree_skb(skb); |
