diff options
Diffstat (limited to 'drivers/block/aoe')
-rw-r--r-- | drivers/block/aoe/aoe.h | 69 | ||||
-rw-r--r-- | drivers/block/aoe/aoeblk.c | 72 | ||||
-rw-r--r-- | drivers/block/aoe/aoechr.c | 93 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 742 | ||||
-rw-r--r-- | drivers/block/aoe/aoedev.c | 277 | ||||
-rw-r--r-- | drivers/block/aoe/aoemain.c | 2 | ||||
-rw-r--r-- | drivers/block/aoe/aoenet.c | 15 |
7 files changed, 869 insertions, 401 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 07f02f855ab5..280e71ee744c 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ |
2 | #define VERSION "32" | 2 | #define VERSION "47" |
3 | #define AOE_MAJOR 152 | 3 | #define AOE_MAJOR 152 |
4 | #define DEVICE_NAME "aoe" | 4 | #define DEVICE_NAME "aoe" |
5 | 5 | ||
@@ -76,10 +76,8 @@ enum { | |||
76 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ | 76 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ |
77 | DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */ | 77 | DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */ |
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_KICKME = (1<<5), /* slow polling network card catch */ |
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), | ||
83 | 81 | ||
84 | BUFFL_FAIL = 1, | 82 | BUFFL_FAIL = 1, |
85 | }; | 83 | }; |
@@ -88,17 +86,25 @@ enum { | |||
88 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ | 86 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ |
89 | NPERSHELF = 16, /* number of slots per shelf address */ | 87 | NPERSHELF = 16, /* number of slots per shelf address */ |
90 | FREETAG = -1, | 88 | FREETAG = -1, |
91 | MIN_BUFS = 8, | 89 | MIN_BUFS = 16, |
90 | NTARGETS = 8, | ||
91 | NAOEIFS = 8, | ||
92 | NSKBPOOLMAX = 128, | ||
93 | |||
94 | TIMERTICK = HZ / 10, | ||
95 | MINTIMER = HZ >> 2, | ||
96 | MAXTIMER = HZ << 1, | ||
97 | HELPWAIT = 20, | ||
92 | }; | 98 | }; |
93 | 99 | ||
94 | struct buf { | 100 | struct buf { |
95 | struct list_head bufs; | 101 | struct list_head bufs; |
96 | ulong start_time; /* for disk stats */ | 102 | ulong stime; /* for disk stats */ |
97 | ulong flags; | 103 | ulong flags; |
98 | ulong nframesout; | 104 | ulong nframesout; |
99 | char *bufaddr; | ||
100 | ulong resid; | 105 | ulong resid; |
101 | ulong bv_resid; | 106 | ulong bv_resid; |
107 | ulong bv_off; | ||
102 | sector_t sector; | 108 | sector_t sector; |
103 | struct bio *bio; | 109 | struct bio *bio; |
104 | struct bio_vec *bv; | 110 | struct bio_vec *bv; |
@@ -114,19 +120,38 @@ struct frame { | |||
114 | struct sk_buff *skb; | 120 | struct sk_buff *skb; |
115 | }; | 121 | }; |
116 | 122 | ||
123 | struct aoeif { | ||
124 | struct net_device *nd; | ||
125 | unsigned char lost; | ||
126 | unsigned char lostjumbo; | ||
127 | ushort maxbcnt; | ||
128 | }; | ||
129 | |||
130 | struct aoetgt { | ||
131 | unsigned char addr[6]; | ||
132 | ushort nframes; | ||
133 | struct frame *frames; | ||
134 | struct aoeif ifs[NAOEIFS]; | ||
135 | struct aoeif *ifp; /* current aoeif in use */ | ||
136 | ushort nout; | ||
137 | ushort maxout; | ||
138 | u16 lasttag; /* last tag sent */ | ||
139 | u16 useme; | ||
140 | ulong lastwadj; /* last window adjustment */ | ||
141 | int wpkts, rpkts; | ||
142 | int dataref; | ||
143 | }; | ||
144 | |||
117 | struct aoedev { | 145 | struct aoedev { |
118 | struct aoedev *next; | 146 | struct aoedev *next; |
119 | unsigned char addr[6]; /* remote mac addr */ | ||
120 | ushort flags; | ||
121 | ulong sysminor; | 147 | ulong sysminor; |
122 | ulong aoemajor; | 148 | ulong aoemajor; |
123 | ulong aoeminor; | 149 | u16 aoeminor; |
150 | u16 flags; | ||
124 | u16 nopen; /* (bd_openers isn't available without sleeping) */ | 151 | u16 nopen; /* (bd_openers isn't available without sleeping) */ |
125 | u16 lasttag; /* last tag sent */ | ||
126 | u16 rttavg; /* round trip average of requests/responses */ | 152 | u16 rttavg; /* round trip average of requests/responses */ |
127 | u16 mintimer; | 153 | u16 mintimer; |
128 | u16 fw_ver; /* version of blade's firmware */ | 154 | u16 fw_ver; /* version of blade's firmware */ |
129 | u16 maxbcnt; | ||
130 | struct work_struct work;/* disk create work struct */ | 155 | struct work_struct work;/* disk create work struct */ |
131 | struct gendisk *gd; | 156 | struct gendisk *gd; |
132 | struct request_queue blkq; | 157 | struct request_queue blkq; |
@@ -134,15 +159,17 @@ struct aoedev { | |||
134 | sector_t ssize; | 159 | sector_t ssize; |
135 | struct timer_list timer; | 160 | struct timer_list timer; |
136 | spinlock_t lock; | 161 | spinlock_t lock; |
137 | struct net_device *ifp; /* interface ed is attached to */ | ||
138 | struct sk_buff *sendq_hd; /* packets needing to be sent, list head */ | 162 | struct sk_buff *sendq_hd; /* packets needing to be sent, list head */ |
139 | struct sk_buff *sendq_tl; | 163 | struct sk_buff *sendq_tl; |
164 | struct sk_buff *skbpool_hd; | ||
165 | struct sk_buff *skbpool_tl; | ||
166 | int nskbpool; | ||
140 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ | 167 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ |
141 | struct list_head bufq; /* queue of bios to work on */ | 168 | struct list_head bufq; /* queue of bios to work on */ |
142 | struct buf *inprocess; /* the one we're currently working on */ | 169 | struct buf *inprocess; /* the one we're currently working on */ |
143 | ushort lostjumbo; | 170 | struct aoetgt *targets[NTARGETS]; |
144 | ushort nframes; /* number of frames below */ | 171 | struct aoetgt **tgt; /* target in use when working */ |
145 | struct frame *frames; | 172 | struct aoetgt **htgt; /* target needing rexmit assistance */ |
146 | }; | 173 | }; |
147 | 174 | ||
148 | 175 | ||
@@ -160,14 +187,16 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | |||
160 | void aoecmd_ata_rsp(struct sk_buff *); | 187 | void aoecmd_ata_rsp(struct sk_buff *); |
161 | void aoecmd_cfg_rsp(struct sk_buff *); | 188 | void aoecmd_cfg_rsp(struct sk_buff *); |
162 | void aoecmd_sleepwork(struct work_struct *); | 189 | void aoecmd_sleepwork(struct work_struct *); |
163 | struct sk_buff *new_skb(ulong); | 190 | void aoecmd_cleanslate(struct aoedev *); |
191 | struct sk_buff *aoecmd_ata_id(struct aoedev *); | ||
164 | 192 | ||
165 | int aoedev_init(void); | 193 | int aoedev_init(void); |
166 | void aoedev_exit(void); | 194 | void aoedev_exit(void); |
167 | struct aoedev *aoedev_by_aoeaddr(int maj, int min); | 195 | struct aoedev *aoedev_by_aoeaddr(int maj, int min); |
168 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt); | 196 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); |
169 | void aoedev_downdev(struct aoedev *d); | 197 | void aoedev_downdev(struct aoedev *d); |
170 | int aoedev_isbusy(struct aoedev *d); | 198 | int aoedev_isbusy(struct aoedev *d); |
199 | int aoedev_flush(const char __user *str, size_t size); | ||
171 | 200 | ||
172 | int aoenet_init(void); | 201 | int aoenet_init(void); |
173 | void aoenet_exit(void); | 202 | void aoenet_exit(void); |
@@ -175,4 +204,4 @@ void aoenet_xmit(struct sk_buff *); | |||
175 | int is_aoe_netif(struct net_device *ifp); | 204 | int is_aoe_netif(struct net_device *ifp); |
176 | int set_aoe_iflist(const char __user *str, size_t size); | 205 | int set_aoe_iflist(const char __user *str, size_t size); |
177 | 206 | ||
178 | u64 mac_addr(char addr[6]); | 207 | unsigned long long mac_addr(char addr[6]); |
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 826d12381e21..0c39782b2660 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoeblk.c | 3 | * aoeblk.c |
4 | * block device routines | 4 | * block device routines |
@@ -24,7 +24,7 @@ static ssize_t aoedisk_show_state(struct device *dev, | |||
24 | return snprintf(page, PAGE_SIZE, | 24 | return snprintf(page, PAGE_SIZE, |
25 | "%s%s\n", | 25 | "%s%s\n", |
26 | (d->flags & DEVFL_UP) ? "up" : "down", | 26 | (d->flags & DEVFL_UP) ? "up" : "down", |
27 | (d->flags & DEVFL_PAUSE) ? ",paused" : | 27 | (d->flags & DEVFL_KICKME) ? ",kickme" : |
28 | (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); | 28 | (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); |
29 | /* I'd rather see nopen exported so we can ditch closewait */ | 29 | /* I'd rather see nopen exported so we can ditch closewait */ |
30 | } | 30 | } |
@@ -33,17 +33,48 @@ static ssize_t aoedisk_show_mac(struct device *dev, | |||
33 | { | 33 | { |
34 | struct gendisk *disk = dev_to_disk(dev); | 34 | struct gendisk *disk = dev_to_disk(dev); |
35 | struct aoedev *d = disk->private_data; | 35 | struct aoedev *d = disk->private_data; |
36 | struct aoetgt *t = d->targets[0]; | ||
36 | 37 | ||
37 | return snprintf(page, PAGE_SIZE, "%012llx\n", | 38 | if (t == NULL) |
38 | (unsigned long long)mac_addr(d->addr)); | 39 | return snprintf(page, PAGE_SIZE, "none\n"); |
40 | return snprintf(page, PAGE_SIZE, "%012llx\n", mac_addr(t->addr)); | ||
39 | } | 41 | } |
40 | static ssize_t aoedisk_show_netif(struct device *dev, | 42 | static ssize_t aoedisk_show_netif(struct device *dev, |
41 | struct device_attribute *attr, char *page) | 43 | struct device_attribute *attr, char *page) |
42 | { | 44 | { |
43 | struct gendisk *disk = dev_to_disk(dev); | 45 | struct gendisk *disk = dev_to_disk(dev); |
44 | struct aoedev *d = disk->private_data; | 46 | struct aoedev *d = disk->private_data; |
47 | struct net_device *nds[8], **nd, **nnd, **ne; | ||
48 | struct aoetgt **t, **te; | ||
49 | struct aoeif *ifp, *e; | ||
50 | char *p; | ||
51 | |||
52 | memset(nds, 0, sizeof nds); | ||
53 | nd = nds; | ||
54 | ne = nd + ARRAY_SIZE(nds); | ||
55 | t = d->targets; | ||
56 | te = t + NTARGETS; | ||
57 | for (; t < te && *t; t++) { | ||
58 | ifp = (*t)->ifs; | ||
59 | e = ifp + NAOEIFS; | ||
60 | for (; ifp < e && ifp->nd; ifp++) { | ||
61 | for (nnd = nds; nnd < nd; nnd++) | ||
62 | if (*nnd == ifp->nd) | ||
63 | break; | ||
64 | if (nnd == nd && nd != ne) | ||
65 | *nd++ = ifp->nd; | ||
66 | } | ||
67 | } | ||
45 | 68 | ||
46 | return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name); | 69 | ne = nd; |
70 | nd = nds; | ||
71 | if (*nd == NULL) | ||
72 | return snprintf(page, PAGE_SIZE, "none\n"); | ||
73 | for (p = page; nd < ne; nd++) | ||
74 | p += snprintf(p, PAGE_SIZE - (p-page), "%s%s", | ||
75 | p == page ? "" : ",", (*nd)->name); | ||
76 | p += snprintf(p, PAGE_SIZE - (p-page), "\n"); | ||
77 | return p-page; | ||
47 | } | 78 | } |
48 | /* firmware version */ | 79 | /* firmware version */ |
49 | static ssize_t aoedisk_show_fwver(struct device *dev, | 80 | static ssize_t aoedisk_show_fwver(struct device *dev, |
@@ -134,7 +165,23 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) | |||
134 | 165 | ||
135 | blk_queue_bounce(q, &bio); | 166 | blk_queue_bounce(q, &bio); |
136 | 167 | ||
168 | if (bio == NULL) { | ||
169 | printk(KERN_ERR "aoe: bio is NULL\n"); | ||
170 | BUG(); | ||
171 | return 0; | ||
172 | } | ||
137 | d = bio->bi_bdev->bd_disk->private_data; | 173 | d = bio->bi_bdev->bd_disk->private_data; |
174 | if (d == NULL) { | ||
175 | printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n"); | ||
176 | BUG(); | ||
177 | bio_endio(bio, -ENXIO); | ||
178 | return 0; | ||
179 | } else if (bio->bi_io_vec == NULL) { | ||
180 | printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); | ||
181 | BUG(); | ||
182 | bio_endio(bio, -ENXIO); | ||
183 | return 0; | ||
184 | } | ||
138 | buf = mempool_alloc(d->bufpool, GFP_NOIO); | 185 | buf = mempool_alloc(d->bufpool, GFP_NOIO); |
139 | if (buf == NULL) { | 186 | if (buf == NULL) { |
140 | printk(KERN_INFO "aoe: buf allocation failure\n"); | 187 | printk(KERN_INFO "aoe: buf allocation failure\n"); |
@@ -143,19 +190,19 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) | |||
143 | } | 190 | } |
144 | memset(buf, 0, sizeof(*buf)); | 191 | memset(buf, 0, sizeof(*buf)); |
145 | INIT_LIST_HEAD(&buf->bufs); | 192 | INIT_LIST_HEAD(&buf->bufs); |
146 | buf->start_time = jiffies; | 193 | buf->stime = jiffies; |
147 | buf->bio = bio; | 194 | buf->bio = bio; |
148 | buf->resid = bio->bi_size; | 195 | buf->resid = bio->bi_size; |
149 | buf->sector = bio->bi_sector; | 196 | buf->sector = bio->bi_sector; |
150 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; | 197 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; |
151 | WARN_ON(buf->bv->bv_len == 0); | ||
152 | buf->bv_resid = buf->bv->bv_len; | 198 | buf->bv_resid = buf->bv->bv_len; |
153 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 199 | WARN_ON(buf->bv_resid == 0); |
200 | buf->bv_off = buf->bv->bv_offset; | ||
154 | 201 | ||
155 | spin_lock_irqsave(&d->lock, flags); | 202 | spin_lock_irqsave(&d->lock, flags); |
156 | 203 | ||
157 | if ((d->flags & DEVFL_UP) == 0) { | 204 | if ((d->flags & DEVFL_UP) == 0) { |
158 | printk(KERN_INFO "aoe: device %ld.%ld is not up\n", | 205 | printk(KERN_INFO "aoe: device %ld.%d is not up\n", |
159 | d->aoemajor, d->aoeminor); | 206 | d->aoemajor, d->aoeminor); |
160 | spin_unlock_irqrestore(&d->lock, flags); | 207 | spin_unlock_irqrestore(&d->lock, flags); |
161 | mempool_free(buf, d->bufpool); | 208 | mempool_free(buf, d->bufpool); |
@@ -208,14 +255,15 @@ aoeblk_gdalloc(void *vp) | |||
208 | 255 | ||
209 | gd = alloc_disk(AOE_PARTITIONS); | 256 | gd = alloc_disk(AOE_PARTITIONS); |
210 | if (gd == NULL) { | 257 | if (gd == NULL) { |
211 | printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n", | 258 | printk(KERN_ERR |
259 | "aoe: cannot allocate disk structure for %ld.%d\n", | ||
212 | d->aoemajor, d->aoeminor); | 260 | d->aoemajor, d->aoeminor); |
213 | goto err; | 261 | goto err; |
214 | } | 262 | } |
215 | 263 | ||
216 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); | 264 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); |
217 | if (d->bufpool == NULL) { | 265 | if (d->bufpool == NULL) { |
218 | printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n", | 266 | printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n", |
219 | d->aoemajor, d->aoeminor); | 267 | d->aoemajor, d->aoeminor); |
220 | goto err_disk; | 268 | goto err_disk; |
221 | } | 269 | } |
@@ -229,7 +277,7 @@ aoeblk_gdalloc(void *vp) | |||
229 | gd->fops = &aoe_bdops; | 277 | gd->fops = &aoe_bdops; |
230 | gd->private_data = d; | 278 | gd->private_data = d; |
231 | gd->capacity = d->ssize; | 279 | gd->capacity = d->ssize; |
232 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%ld", | 280 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", |
233 | d->aoemajor, d->aoeminor); | 281 | d->aoemajor, d->aoeminor); |
234 | 282 | ||
235 | gd->queue = &d->blkq; | 283 | gd->queue = &d->blkq; |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index d5480e34cb22..e8e60e7a2e70 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 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 |
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/hdreg.h> | 7 | #include <linux/hdreg.h> |
8 | #include <linux/blkdev.h> | 8 | #include <linux/blkdev.h> |
9 | #include <linux/delay.h> | ||
9 | #include "aoe.h" | 10 | #include "aoe.h" |
10 | 11 | ||
11 | enum { | 12 | enum { |
@@ -14,6 +15,7 @@ enum { | |||
14 | MINOR_DISCOVER, | 15 | MINOR_DISCOVER, |
15 | MINOR_INTERFACES, | 16 | MINOR_INTERFACES, |
16 | MINOR_REVALIDATE, | 17 | MINOR_REVALIDATE, |
18 | MINOR_FLUSH, | ||
17 | MSGSZ = 2048, | 19 | MSGSZ = 2048, |
18 | NMSG = 100, /* message backlog to retain */ | 20 | NMSG = 100, /* message backlog to retain */ |
19 | }; | 21 | }; |
@@ -42,6 +44,7 @@ static struct aoe_chardev chardevs[] = { | |||
42 | { MINOR_DISCOVER, "discover" }, | 44 | { MINOR_DISCOVER, "discover" }, |
43 | { MINOR_INTERFACES, "interfaces" }, | 45 | { MINOR_INTERFACES, "interfaces" }, |
44 | { MINOR_REVALIDATE, "revalidate" }, | 46 | { MINOR_REVALIDATE, "revalidate" }, |
47 | { MINOR_FLUSH, "flush" }, | ||
45 | }; | 48 | }; |
46 | 49 | ||
47 | static int | 50 | static int |
@@ -68,6 +71,7 @@ revalidate(const char __user *str, size_t size) | |||
68 | int major, minor, n; | 71 | int major, minor, n; |
69 | ulong flags; | 72 | ulong flags; |
70 | struct aoedev *d; | 73 | struct aoedev *d; |
74 | struct sk_buff *skb; | ||
71 | char buf[16]; | 75 | char buf[16]; |
72 | 76 | ||
73 | if (size >= sizeof buf) | 77 | if (size >= sizeof buf) |
@@ -85,13 +89,20 @@ revalidate(const char __user *str, size_t size) | |||
85 | d = aoedev_by_aoeaddr(major, minor); | 89 | d = aoedev_by_aoeaddr(major, minor); |
86 | if (!d) | 90 | if (!d) |
87 | return -EINVAL; | 91 | return -EINVAL; |
88 | |||
89 | spin_lock_irqsave(&d->lock, flags); | 92 | spin_lock_irqsave(&d->lock, flags); |
90 | d->flags &= ~DEVFL_MAXBCNT; | 93 | aoecmd_cleanslate(d); |
91 | d->flags |= DEVFL_PAUSE; | 94 | loop: |
95 | skb = aoecmd_ata_id(d); | ||
92 | spin_unlock_irqrestore(&d->lock, flags); | 96 | spin_unlock_irqrestore(&d->lock, flags); |
97 | /* try again if we are able to sleep a bit, | ||
98 | * otherwise give up this revalidation | ||
99 | */ | ||
100 | if (!skb && !msleep_interruptible(200)) { | ||
101 | spin_lock_irqsave(&d->lock, flags); | ||
102 | goto loop; | ||
103 | } | ||
104 | aoenet_xmit(skb); | ||
93 | aoecmd_cfg(major, minor); | 105 | aoecmd_cfg(major, minor); |
94 | |||
95 | return 0; | 106 | return 0; |
96 | } | 107 | } |
97 | 108 | ||
@@ -149,6 +160,9 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp | |||
149 | break; | 160 | break; |
150 | case MINOR_REVALIDATE: | 161 | case MINOR_REVALIDATE: |
151 | ret = revalidate(buf, cnt); | 162 | ret = revalidate(buf, cnt); |
163 | break; | ||
164 | case MINOR_FLUSH: | ||
165 | ret = aoedev_flush(buf, cnt); | ||
152 | } | 166 | } |
153 | if (ret == 0) | 167 | if (ret == 0) |
154 | ret = cnt; | 168 | ret = cnt; |
@@ -185,52 +199,51 @@ aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off) | |||
185 | ulong flags; | 199 | ulong flags; |
186 | 200 | ||
187 | n = (unsigned long) filp->private_data; | 201 | n = (unsigned long) filp->private_data; |
188 | switch (n) { | 202 | if (n != MINOR_ERR) |
189 | case MINOR_ERR: | 203 | return -EFAULT; |
190 | spin_lock_irqsave(&emsgs_lock, flags); | 204 | |
191 | loop: | 205 | spin_lock_irqsave(&emsgs_lock, flags); |
192 | em = emsgs + emsgs_head_idx; | ||
193 | if ((em->flags & EMFL_VALID) == 0) { | ||
194 | if (filp->f_flags & O_NDELAY) { | ||
195 | spin_unlock_irqrestore(&emsgs_lock, flags); | ||
196 | return -EAGAIN; | ||
197 | } | ||
198 | nblocked_emsgs_readers++; | ||
199 | 206 | ||
207 | for (;;) { | ||
208 | em = emsgs + emsgs_head_idx; | ||
209 | if ((em->flags & EMFL_VALID) != 0) | ||
210 | break; | ||
211 | if (filp->f_flags & O_NDELAY) { | ||
200 | spin_unlock_irqrestore(&emsgs_lock, flags); | 212 | spin_unlock_irqrestore(&emsgs_lock, flags); |
213 | return -EAGAIN; | ||
214 | } | ||
215 | nblocked_emsgs_readers++; | ||
201 | 216 | ||
202 | n = down_interruptible(&emsgs_sema); | 217 | spin_unlock_irqrestore(&emsgs_lock, flags); |
218 | |||
219 | n = down_interruptible(&emsgs_sema); | ||
203 | 220 | ||
204 | spin_lock_irqsave(&emsgs_lock, flags); | 221 | spin_lock_irqsave(&emsgs_lock, flags); |
205 | 222 | ||
206 | nblocked_emsgs_readers--; | 223 | nblocked_emsgs_readers--; |
207 | 224 | ||
208 | if (n) { | 225 | if (n) { |
209 | spin_unlock_irqrestore(&emsgs_lock, flags); | ||
210 | return -ERESTARTSYS; | ||
211 | } | ||
212 | goto loop; | ||
213 | } | ||
214 | if (em->len > cnt) { | ||
215 | spin_unlock_irqrestore(&emsgs_lock, flags); | 226 | spin_unlock_irqrestore(&emsgs_lock, flags); |
216 | return -EAGAIN; | 227 | return -ERESTARTSYS; |
217 | } | 228 | } |
218 | mp = em->msg; | 229 | } |
219 | len = em->len; | 230 | if (em->len > cnt) { |
220 | em->msg = NULL; | 231 | spin_unlock_irqrestore(&emsgs_lock, flags); |
221 | em->flags &= ~EMFL_VALID; | 232 | return -EAGAIN; |
233 | } | ||
234 | mp = em->msg; | ||
235 | len = em->len; | ||
236 | em->msg = NULL; | ||
237 | em->flags &= ~EMFL_VALID; | ||
222 | 238 | ||
223 | emsgs_head_idx++; | 239 | emsgs_head_idx++; |
224 | emsgs_head_idx %= ARRAY_SIZE(emsgs); | 240 | emsgs_head_idx %= ARRAY_SIZE(emsgs); |
225 | 241 | ||
226 | spin_unlock_irqrestore(&emsgs_lock, flags); | 242 | spin_unlock_irqrestore(&emsgs_lock, flags); |
227 | 243 | ||
228 | n = copy_to_user(buf, mp, len); | 244 | n = copy_to_user(buf, mp, len); |
229 | kfree(mp); | 245 | kfree(mp); |
230 | return n == 0 ? len : -EFAULT; | 246 | return n == 0 ? len : -EFAULT; |
231 | default: | ||
232 | return -EFAULT; | ||
233 | } | ||
234 | } | 247 | } |
235 | 248 | ||
236 | static const struct file_operations aoe_fops = { | 249 | static const struct file_operations aoe_fops = { |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 4d59d5057734..d00293ba3b45 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 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 |
@@ -9,19 +9,21 @@ | |||
9 | #include <linux/skbuff.h> | 9 | #include <linux/skbuff.h> |
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/genhd.h> | 11 | #include <linux/genhd.h> |
12 | #include <linux/moduleparam.h> | ||
12 | #include <net/net_namespace.h> | 13 | #include <net/net_namespace.h> |
13 | #include <asm/unaligned.h> | 14 | #include <asm/unaligned.h> |
14 | #include "aoe.h" | 15 | #include "aoe.h" |
15 | 16 | ||
16 | #define TIMERTICK (HZ / 10) | ||
17 | #define MINTIMER (2 * TIMERTICK) | ||
18 | #define MAXTIMER (HZ << 1) | ||
19 | |||
20 | static int aoe_deadsecs = 60 * 3; | 17 | static int aoe_deadsecs = 60 * 3; |
21 | module_param(aoe_deadsecs, int, 0644); | 18 | module_param(aoe_deadsecs, int, 0644); |
22 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | 19 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); |
23 | 20 | ||
24 | struct sk_buff * | 21 | static int aoe_maxout = 16; |
22 | module_param(aoe_maxout, int, 0644); | ||
23 | MODULE_PARM_DESC(aoe_maxout, | ||
24 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); | ||
25 | |||
26 | static struct sk_buff * | ||
25 | new_skb(ulong len) | 27 | new_skb(ulong len) |
26 | { | 28 | { |
27 | struct sk_buff *skb; | 29 | struct sk_buff *skb; |
@@ -43,12 +45,12 @@ new_skb(ulong len) | |||
43 | } | 45 | } |
44 | 46 | ||
45 | static struct frame * | 47 | static struct frame * |
46 | getframe(struct aoedev *d, int tag) | 48 | getframe(struct aoetgt *t, int tag) |
47 | { | 49 | { |
48 | struct frame *f, *e; | 50 | struct frame *f, *e; |
49 | 51 | ||
50 | f = d->frames; | 52 | f = t->frames; |
51 | e = f + d->nframes; | 53 | e = f + t->nframes; |
52 | for (; f<e; f++) | 54 | for (; f<e; f++) |
53 | if (f->tag == tag) | 55 | if (f->tag == tag) |
54 | return f; | 56 | return f; |
@@ -61,21 +63,21 @@ getframe(struct aoedev *d, int tag) | |||
61 | * This driver reserves tag -1 to mean "unused frame." | 63 | * This driver reserves tag -1 to mean "unused frame." |
62 | */ | 64 | */ |
63 | static int | 65 | static int |
64 | newtag(struct aoedev *d) | 66 | newtag(struct aoetgt *t) |
65 | { | 67 | { |
66 | register ulong n; | 68 | register ulong n; |
67 | 69 | ||
68 | n = jiffies & 0xffff; | 70 | n = jiffies & 0xffff; |
69 | return n |= (++d->lasttag & 0x7fff) << 16; | 71 | return n |= (++t->lasttag & 0x7fff) << 16; |
70 | } | 72 | } |
71 | 73 | ||
72 | static int | 74 | static int |
73 | aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) | 75 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) |
74 | { | 76 | { |
75 | u32 host_tag = newtag(d); | 77 | u32 host_tag = newtag(t); |
76 | 78 | ||
77 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 79 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
78 | memcpy(h->dst, d->addr, sizeof h->dst); | 80 | memcpy(h->dst, t->addr, sizeof h->dst); |
79 | h->type = __constant_cpu_to_be16(ETH_P_AOE); | 81 | h->type = __constant_cpu_to_be16(ETH_P_AOE); |
80 | h->verfl = AOE_HVER; | 82 | h->verfl = AOE_HVER; |
81 | h->major = cpu_to_be16(d->aoemajor); | 83 | h->major = cpu_to_be16(d->aoemajor); |
@@ -98,42 +100,162 @@ put_lba(struct aoe_atahdr *ah, sector_t lba) | |||
98 | } | 100 | } |
99 | 101 | ||
100 | static void | 102 | static void |
101 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 103 | ifrotate(struct aoetgt *t) |
104 | { | ||
105 | t->ifp++; | ||
106 | if (t->ifp >= &t->ifs[NAOEIFS] || t->ifp->nd == NULL) | ||
107 | t->ifp = t->ifs; | ||
108 | if (t->ifp->nd == NULL) { | ||
109 | printk(KERN_INFO "aoe: no interface to rotate to\n"); | ||
110 | BUG(); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | static void | ||
115 | skb_pool_put(struct aoedev *d, struct sk_buff *skb) | ||
116 | { | ||
117 | if (!d->skbpool_hd) | ||
118 | d->skbpool_hd = skb; | ||
119 | else | ||
120 | d->skbpool_tl->next = skb; | ||
121 | d->skbpool_tl = skb; | ||
122 | } | ||
123 | |||
124 | static struct sk_buff * | ||
125 | skb_pool_get(struct aoedev *d) | ||
126 | { | ||
127 | struct sk_buff *skb; | ||
128 | |||
129 | skb = d->skbpool_hd; | ||
130 | if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) { | ||
131 | d->skbpool_hd = skb->next; | ||
132 | skb->next = NULL; | ||
133 | return skb; | ||
134 | } | ||
135 | if (d->nskbpool < NSKBPOOLMAX | ||
136 | && (skb = new_skb(ETH_ZLEN))) { | ||
137 | d->nskbpool++; | ||
138 | return skb; | ||
139 | } | ||
140 | return NULL; | ||
141 | } | ||
142 | |||
143 | /* freeframe is where we do our load balancing so it's a little hairy. */ | ||
144 | static struct frame * | ||
145 | freeframe(struct aoedev *d) | ||
146 | { | ||
147 | struct frame *f, *e, *rf; | ||
148 | struct aoetgt **t; | ||
149 | struct sk_buff *skb; | ||
150 | |||
151 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ | ||
152 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); | ||
153 | return NULL; | ||
154 | } | ||
155 | t = d->tgt; | ||
156 | t++; | ||
157 | if (t >= &d->targets[NTARGETS] || !*t) | ||
158 | t = d->targets; | ||
159 | for (;;) { | ||
160 | if ((*t)->nout < (*t)->maxout | ||
161 | && t != d->htgt | ||
162 | && (*t)->ifp->nd) { | ||
163 | rf = NULL; | ||
164 | f = (*t)->frames; | ||
165 | e = f + (*t)->nframes; | ||
166 | for (; f < e; f++) { | ||
167 | if (f->tag != FREETAG) | ||
168 | continue; | ||
169 | skb = f->skb; | ||
170 | if (!skb | ||
171 | && !(f->skb = skb = new_skb(ETH_ZLEN))) | ||
172 | continue; | ||
173 | if (atomic_read(&skb_shinfo(skb)->dataref) | ||
174 | != 1) { | ||
175 | if (!rf) | ||
176 | rf = f; | ||
177 | continue; | ||
178 | } | ||
179 | gotone: skb_shinfo(skb)->nr_frags = skb->data_len = 0; | ||
180 | skb_trim(skb, 0); | ||
181 | d->tgt = t; | ||
182 | ifrotate(*t); | ||
183 | return f; | ||
184 | } | ||
185 | /* Work can be done, but the network layer is | ||
186 | holding our precious packets. Try to grab | ||
187 | one from the pool. */ | ||
188 | f = rf; | ||
189 | if (f == NULL) { /* more paranoia */ | ||
190 | printk(KERN_ERR | ||
191 | "aoe: freeframe: %s.\n", | ||
192 | "unexpected null rf"); | ||
193 | d->flags |= DEVFL_KICKME; | ||
194 | return NULL; | ||
195 | } | ||
196 | skb = skb_pool_get(d); | ||
197 | if (skb) { | ||
198 | skb_pool_put(d, f->skb); | ||
199 | f->skb = skb; | ||
200 | goto gotone; | ||
201 | } | ||
202 | (*t)->dataref++; | ||
203 | if ((*t)->nout == 0) | ||
204 | d->flags |= DEVFL_KICKME; | ||
205 | } | ||
206 | if (t == d->tgt) /* we've looped and found nada */ | ||
207 | break; | ||
208 | t++; | ||
209 | if (t >= &d->targets[NTARGETS] || !*t) | ||
210 | t = d->targets; | ||
211 | } | ||
212 | return NULL; | ||
213 | } | ||
214 | |||
215 | static int | ||
216 | aoecmd_ata_rw(struct aoedev *d) | ||
102 | { | 217 | { |
218 | struct frame *f; | ||
103 | struct aoe_hdr *h; | 219 | struct aoe_hdr *h; |
104 | struct aoe_atahdr *ah; | 220 | struct aoe_atahdr *ah; |
105 | struct buf *buf; | 221 | struct buf *buf; |
222 | struct bio_vec *bv; | ||
223 | struct aoetgt *t; | ||
106 | struct sk_buff *skb; | 224 | struct sk_buff *skb; |
107 | ulong bcnt; | 225 | ulong bcnt; |
108 | register sector_t sector; | ||
109 | char writebit, extbit; | 226 | char writebit, extbit; |
110 | 227 | ||
111 | writebit = 0x10; | 228 | writebit = 0x10; |
112 | extbit = 0x4; | 229 | extbit = 0x4; |
113 | 230 | ||
231 | f = freeframe(d); | ||
232 | if (f == NULL) | ||
233 | return 0; | ||
234 | t = *d->tgt; | ||
114 | buf = d->inprocess; | 235 | buf = d->inprocess; |
115 | 236 | bv = buf->bv; | |
116 | sector = buf->sector; | 237 | bcnt = t->ifp->maxbcnt; |
117 | bcnt = buf->bv_resid; | 238 | if (bcnt == 0) |
118 | if (bcnt > d->maxbcnt) | 239 | bcnt = DEFAULTBCNT; |
119 | bcnt = d->maxbcnt; | 240 | if (bcnt > buf->bv_resid) |
120 | 241 | bcnt = buf->bv_resid; | |
121 | /* initialize the headers & frame */ | 242 | /* initialize the headers & frame */ |
122 | skb = f->skb; | 243 | skb = f->skb; |
123 | h = (struct aoe_hdr *) skb_mac_header(skb); | 244 | h = (struct aoe_hdr *) skb_mac_header(skb); |
124 | ah = (struct aoe_atahdr *) (h+1); | 245 | ah = (struct aoe_atahdr *) (h+1); |
125 | skb_put(skb, sizeof *h + sizeof *ah); | 246 | skb_put(skb, sizeof *h + sizeof *ah); |
126 | memset(h, 0, skb->len); | 247 | memset(h, 0, skb->len); |
127 | f->tag = aoehdr_atainit(d, h); | 248 | f->tag = aoehdr_atainit(d, t, h); |
249 | t->nout++; | ||
128 | f->waited = 0; | 250 | f->waited = 0; |
129 | f->buf = buf; | 251 | f->buf = buf; |
130 | f->bufaddr = buf->bufaddr; | 252 | f->bufaddr = page_address(bv->bv_page) + buf->bv_off; |
131 | f->bcnt = bcnt; | 253 | f->bcnt = bcnt; |
132 | f->lba = sector; | 254 | f->lba = buf->sector; |
133 | 255 | ||
134 | /* set up ata header */ | 256 | /* set up ata header */ |
135 | ah->scnt = bcnt >> 9; | 257 | ah->scnt = bcnt >> 9; |
136 | put_lba(ah, sector); | 258 | put_lba(ah, buf->sector); |
137 | if (d->flags & DEVFL_EXT) { | 259 | if (d->flags & DEVFL_EXT) { |
138 | ah->aflags |= AOEAFL_EXT; | 260 | ah->aflags |= AOEAFL_EXT; |
139 | } else { | 261 | } else { |
@@ -141,14 +263,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
141 | ah->lba3 &= 0x0f; | 263 | ah->lba3 &= 0x0f; |
142 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ | 264 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ |
143 | } | 265 | } |
144 | |||
145 | if (bio_data_dir(buf->bio) == WRITE) { | 266 | if (bio_data_dir(buf->bio) == WRITE) { |
146 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | 267 | skb_fill_page_desc(skb, 0, bv->bv_page, buf->bv_off, bcnt); |
147 | offset_in_page(f->bufaddr), bcnt); | ||
148 | ah->aflags |= AOEAFL_WRITE; | 268 | ah->aflags |= AOEAFL_WRITE; |
149 | skb->len += bcnt; | 269 | skb->len += bcnt; |
150 | skb->data_len = bcnt; | 270 | skb->data_len = bcnt; |
271 | t->wpkts++; | ||
151 | } else { | 272 | } else { |
273 | t->rpkts++; | ||
152 | writebit = 0; | 274 | writebit = 0; |
153 | } | 275 | } |
154 | 276 | ||
@@ -156,29 +278,29 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
156 | 278 | ||
157 | /* mark all tracking fields and load out */ | 279 | /* mark all tracking fields and load out */ |
158 | buf->nframesout += 1; | 280 | buf->nframesout += 1; |
159 | buf->bufaddr += bcnt; | 281 | buf->bv_off += bcnt; |
160 | buf->bv_resid -= bcnt; | 282 | buf->bv_resid -= bcnt; |
161 | /* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ | ||
162 | buf->resid -= bcnt; | 283 | buf->resid -= bcnt; |
163 | buf->sector += bcnt >> 9; | 284 | buf->sector += bcnt >> 9; |
164 | if (buf->resid == 0) { | 285 | if (buf->resid == 0) { |
165 | d->inprocess = NULL; | 286 | d->inprocess = NULL; |
166 | } else if (buf->bv_resid == 0) { | 287 | } else if (buf->bv_resid == 0) { |
167 | buf->bv++; | 288 | buf->bv = ++bv; |
168 | WARN_ON(buf->bv->bv_len == 0); | 289 | buf->bv_resid = bv->bv_len; |
169 | buf->bv_resid = buf->bv->bv_len; | 290 | WARN_ON(buf->bv_resid == 0); |
170 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 291 | buf->bv_off = bv->bv_offset; |
171 | } | 292 | } |
172 | 293 | ||
173 | skb->dev = d->ifp; | 294 | skb->dev = t->ifp->nd; |
174 | skb = skb_clone(skb, GFP_ATOMIC); | 295 | skb = skb_clone(skb, GFP_ATOMIC); |
175 | if (skb == NULL) | 296 | if (skb) { |
176 | return; | 297 | if (d->sendq_hd) |
177 | if (d->sendq_hd) | 298 | d->sendq_tl->next = skb; |
178 | d->sendq_tl->next = skb; | 299 | else |
179 | else | 300 | d->sendq_hd = skb; |
180 | d->sendq_hd = skb; | 301 | d->sendq_tl = skb; |
181 | d->sendq_tl = skb; | 302 | } |
303 | return 1; | ||
182 | } | 304 | } |
183 | 305 | ||
184 | /* some callers cannot sleep, and they can call this function, | 306 | /* some callers cannot sleep, and they can call this function, |
@@ -232,62 +354,8 @@ cont: | |||
232 | return sl; | 354 | return sl; |
233 | } | 355 | } |
234 | 356 | ||
235 | static struct frame * | ||
236 | freeframe(struct aoedev *d) | ||
237 | { | ||
238 | struct frame *f, *e; | ||
239 | int n = 0; | ||
240 | |||
241 | f = d->frames; | ||
242 | e = f + d->nframes; | ||
243 | for (; f<e; f++) { | ||
244 | if (f->tag != FREETAG) | ||
245 | continue; | ||
246 | if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) { | ||
247 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
248 | skb_trim(f->skb, 0); | ||
249 | return f; | ||
250 | } | ||
251 | n++; | ||
252 | } | ||
253 | if (n == d->nframes) /* wait for network layer */ | ||
254 | d->flags |= DEVFL_KICKME; | ||
255 | |||
256 | return NULL; | ||
257 | } | ||
258 | |||
259 | /* enters with d->lock held */ | ||
260 | void | ||
261 | aoecmd_work(struct aoedev *d) | ||
262 | { | ||
263 | struct frame *f; | ||
264 | struct buf *buf; | ||
265 | |||
266 | if (d->flags & DEVFL_PAUSE) { | ||
267 | if (!aoedev_isbusy(d)) | ||
268 | d->sendq_hd = aoecmd_cfg_pkts(d->aoemajor, | ||
269 | d->aoeminor, &d->sendq_tl); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | loop: | ||
274 | f = freeframe(d); | ||
275 | if (f == NULL) | ||
276 | return; | ||
277 | if (d->inprocess == NULL) { | ||
278 | if (list_empty(&d->bufq)) | ||
279 | return; | ||
280 | buf = container_of(d->bufq.next, struct buf, bufs); | ||
281 | list_del(d->bufq.next); | ||
282 | /*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */ | ||
283 | d->inprocess = buf; | ||
284 | } | ||
285 | aoecmd_ata_rw(d, f); | ||
286 | goto loop; | ||
287 | } | ||
288 | |||
289 | static void | 357 | static void |
290 | rexmit(struct aoedev *d, struct frame *f) | 358 | resend(struct aoedev *d, struct aoetgt *t, struct frame *f) |
291 | { | 359 | { |
292 | struct sk_buff *skb; | 360 | struct sk_buff *skb; |
293 | struct aoe_hdr *h; | 361 | struct aoe_hdr *h; |
@@ -295,41 +363,46 @@ rexmit(struct aoedev *d, struct frame *f) | |||
295 | char buf[128]; | 363 | char buf[128]; |
296 | u32 n; | 364 | u32 n; |
297 | 365 | ||
298 | n = newtag(d); | 366 | ifrotate(t); |
367 | n = newtag(t); | ||
368 | skb = f->skb; | ||
369 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
370 | ah = (struct aoe_atahdr *) (h+1); | ||
299 | 371 | ||
300 | snprintf(buf, sizeof buf, | 372 | snprintf(buf, sizeof buf, |
301 | "%15s e%ld.%ld oldtag=%08x@%08lx newtag=%08x\n", | 373 | "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x " |
302 | "retransmit", | 374 | "s=%012llx d=%012llx nout=%d\n", |
303 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); | 375 | "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n, |
376 | mac_addr(h->src), | ||
377 | mac_addr(h->dst), t->nout); | ||
304 | aoechr_error(buf); | 378 | aoechr_error(buf); |
305 | 379 | ||
306 | skb = f->skb; | ||
307 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
308 | ah = (struct aoe_atahdr *) (h+1); | ||
309 | f->tag = n; | 380 | f->tag = n; |
310 | h->tag = cpu_to_be32(n); | 381 | h->tag = cpu_to_be32(n); |
311 | memcpy(h->dst, d->addr, sizeof h->dst); | 382 | memcpy(h->dst, t->addr, sizeof h->dst); |
312 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 383 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
313 | 384 | ||
314 | n = DEFAULTBCNT / 512; | 385 | switch (ah->cmdstat) { |
315 | if (ah->scnt > n) { | 386 | default: |
316 | ah->scnt = n; | 387 | break; |
388 | case WIN_READ: | ||
389 | case WIN_READ_EXT: | ||
390 | case WIN_WRITE: | ||
391 | case WIN_WRITE_EXT: | ||
392 | put_lba(ah, f->lba); | ||
393 | |||
394 | n = f->bcnt; | ||
395 | if (n > DEFAULTBCNT) | ||
396 | n = DEFAULTBCNT; | ||
397 | ah->scnt = n >> 9; | ||
317 | if (ah->aflags & AOEAFL_WRITE) { | 398 | if (ah->aflags & AOEAFL_WRITE) { |
318 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | 399 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), |
319 | offset_in_page(f->bufaddr), DEFAULTBCNT); | 400 | offset_in_page(f->bufaddr), n); |
320 | skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; | 401 | skb->len = sizeof *h + sizeof *ah + n; |
321 | skb->data_len = DEFAULTBCNT; | 402 | skb->data_len = n; |
322 | } | ||
323 | if (++d->lostjumbo > (d->nframes << 1)) | ||
324 | if (d->maxbcnt != DEFAULTBCNT) { | ||
325 | printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", | ||
326 | d->aoemajor, d->aoeminor, d->ifp->name); | ||
327 | d->maxbcnt = DEFAULTBCNT; | ||
328 | d->flags |= DEVFL_MAXBCNT; | ||
329 | } | 403 | } |
330 | } | 404 | } |
331 | 405 | skb->dev = t->ifp->nd; | |
332 | skb->dev = d->ifp; | ||
333 | skb = skb_clone(skb, GFP_ATOMIC); | 406 | skb = skb_clone(skb, GFP_ATOMIC); |
334 | if (skb == NULL) | 407 | if (skb == NULL) |
335 | return; | 408 | return; |
@@ -352,10 +425,92 @@ tsince(int tag) | |||
352 | return n; | 425 | return n; |
353 | } | 426 | } |
354 | 427 | ||
428 | static struct aoeif * | ||
429 | getif(struct aoetgt *t, struct net_device *nd) | ||
430 | { | ||
431 | struct aoeif *p, *e; | ||
432 | |||
433 | p = t->ifs; | ||
434 | e = p + NAOEIFS; | ||
435 | for (; p < e; p++) | ||
436 | if (p->nd == nd) | ||
437 | return p; | ||
438 | return NULL; | ||
439 | } | ||
440 | |||
441 | static struct aoeif * | ||
442 | addif(struct aoetgt *t, struct net_device *nd) | ||
443 | { | ||
444 | struct aoeif *p; | ||
445 | |||
446 | p = getif(t, NULL); | ||
447 | if (!p) | ||
448 | return NULL; | ||
449 | p->nd = nd; | ||
450 | p->maxbcnt = DEFAULTBCNT; | ||
451 | p->lost = 0; | ||
452 | p->lostjumbo = 0; | ||
453 | return p; | ||
454 | } | ||
455 | |||
456 | static void | ||
457 | ejectif(struct aoetgt *t, struct aoeif *ifp) | ||
458 | { | ||
459 | struct aoeif *e; | ||
460 | ulong n; | ||
461 | |||
462 | e = t->ifs + NAOEIFS - 1; | ||
463 | n = (e - ifp) * sizeof *ifp; | ||
464 | memmove(ifp, ifp+1, n); | ||
465 | e->nd = NULL; | ||
466 | } | ||
467 | |||
468 | static int | ||
469 | sthtith(struct aoedev *d) | ||
470 | { | ||
471 | struct frame *f, *e, *nf; | ||
472 | struct sk_buff *skb; | ||
473 | struct aoetgt *ht = *d->htgt; | ||
474 | |||
475 | f = ht->frames; | ||
476 | e = f + ht->nframes; | ||
477 | for (; f < e; f++) { | ||
478 | if (f->tag == FREETAG) | ||
479 | continue; | ||
480 | nf = freeframe(d); | ||
481 | if (!nf) | ||
482 | return 0; | ||
483 | skb = nf->skb; | ||
484 | *nf = *f; | ||
485 | f->skb = skb; | ||
486 | f->tag = FREETAG; | ||
487 | nf->waited = 0; | ||
488 | ht->nout--; | ||
489 | (*d->tgt)->nout++; | ||
490 | resend(d, *d->tgt, nf); | ||
491 | } | ||
492 | /* he's clean, he's useless. take away his interfaces */ | ||
493 | memset(ht->ifs, 0, sizeof ht->ifs); | ||
494 | d->htgt = NULL; | ||
495 | return 1; | ||
496 | } | ||
497 | |||
498 | static inline unsigned char | ||
499 | ata_scnt(unsigned char *packet) { | ||
500 | struct aoe_hdr *h; | ||
501 | struct aoe_atahdr *ah; | ||
502 | |||
503 | h = (struct aoe_hdr *) packet; | ||
504 | ah = (struct aoe_atahdr *) (h+1); | ||
505 | return ah->scnt; | ||
506 | } | ||
507 | |||
355 | static void | 508 | static void |
356 | rexmit_timer(ulong vp) | 509 | rexmit_timer(ulong vp) |
357 | { | 510 | { |
358 | struct aoedev *d; | 511 | struct aoedev *d; |
512 | struct aoetgt *t, **tt, **te; | ||
513 | struct aoeif *ifp; | ||
359 | struct frame *f, *e; | 514 | struct frame *f, *e; |
360 | struct sk_buff *sl; | 515 | struct sk_buff *sl; |
361 | register long timeout; | 516 | register long timeout; |
@@ -374,31 +529,79 @@ rexmit_timer(ulong vp) | |||
374 | spin_unlock_irqrestore(&d->lock, flags); | 529 | spin_unlock_irqrestore(&d->lock, flags); |
375 | return; | 530 | return; |
376 | } | 531 | } |
377 | f = d->frames; | 532 | tt = d->targets; |
378 | e = f + d->nframes; | 533 | te = tt + NTARGETS; |
379 | for (; f<e; f++) { | 534 | for (; tt < te && *tt; tt++) { |
380 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { | 535 | t = *tt; |
536 | f = t->frames; | ||
537 | e = f + t->nframes; | ||
538 | for (; f < e; f++) { | ||
539 | if (f->tag == FREETAG | ||
540 | || tsince(f->tag) < timeout) | ||
541 | continue; | ||
381 | n = f->waited += timeout; | 542 | n = f->waited += timeout; |
382 | n /= HZ; | 543 | n /= HZ; |
383 | if (n > aoe_deadsecs) { /* waited too long for response */ | 544 | if (n > aoe_deadsecs) { |
545 | /* waited too long. device failure. */ | ||
384 | aoedev_downdev(d); | 546 | aoedev_downdev(d); |
385 | break; | 547 | break; |
386 | } | 548 | } |
387 | rexmit(d, f); | 549 | |
550 | if (n > HELPWAIT /* see if another target can help */ | ||
551 | && (tt != d->targets || d->targets[1])) | ||
552 | d->htgt = tt; | ||
553 | |||
554 | if (t->nout == t->maxout) { | ||
555 | if (t->maxout > 1) | ||
556 | t->maxout--; | ||
557 | t->lastwadj = jiffies; | ||
558 | } | ||
559 | |||
560 | ifp = getif(t, f->skb->dev); | ||
561 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
562 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
563 | ejectif(t, ifp); | ||
564 | ifp = NULL; | ||
565 | } | ||
566 | |||
567 | if (ata_scnt(skb_mac_header(f->skb)) > DEFAULTBCNT / 512 | ||
568 | && ifp && ++ifp->lostjumbo > (t->nframes << 1) | ||
569 | && ifp->maxbcnt != DEFAULTBCNT) { | ||
570 | printk(KERN_INFO | ||
571 | "aoe: e%ld.%d: " | ||
572 | "too many lost jumbo on " | ||
573 | "%s:%012llx - " | ||
574 | "falling back to %d frames.\n", | ||
575 | d->aoemajor, d->aoeminor, | ||
576 | ifp->nd->name, mac_addr(t->addr), | ||
577 | DEFAULTBCNT); | ||
578 | ifp->maxbcnt = 0; | ||
579 | } | ||
580 | resend(d, t, f); | ||
581 | } | ||
582 | |||
583 | /* window check */ | ||
584 | if (t->nout == t->maxout | ||
585 | && t->maxout < t->nframes | ||
586 | && (jiffies - t->lastwadj)/HZ > 10) { | ||
587 | t->maxout++; | ||
588 | t->lastwadj = jiffies; | ||
388 | } | 589 | } |
389 | } | 590 | } |
390 | if (d->flags & DEVFL_KICKME) { | 591 | |
592 | if (d->sendq_hd) { | ||
593 | n = d->rttavg <<= 1; | ||
594 | if (n > MAXTIMER) | ||
595 | d->rttavg = MAXTIMER; | ||
596 | } | ||
597 | |||
598 | if (d->flags & DEVFL_KICKME || d->htgt) { | ||
391 | d->flags &= ~DEVFL_KICKME; | 599 | d->flags &= ~DEVFL_KICKME; |
392 | aoecmd_work(d); | 600 | aoecmd_work(d); |
393 | } | 601 | } |
394 | 602 | ||
395 | sl = d->sendq_hd; | 603 | sl = d->sendq_hd; |
396 | d->sendq_hd = d->sendq_tl = NULL; | 604 | d->sendq_hd = d->sendq_tl = NULL; |
397 | if (sl) { | ||
398 | n = d->rttavg <<= 1; | ||
399 | if (n > MAXTIMER) | ||
400 | d->rttavg = MAXTIMER; | ||
401 | } | ||
402 | 605 | ||
403 | d->timer.expires = jiffies + TIMERTICK; | 606 | d->timer.expires = jiffies + TIMERTICK; |
404 | add_timer(&d->timer); | 607 | add_timer(&d->timer); |
@@ -408,6 +611,25 @@ rexmit_timer(ulong vp) | |||
408 | aoenet_xmit(sl); | 611 | aoenet_xmit(sl); |
409 | } | 612 | } |
410 | 613 | ||
614 | /* enters with d->lock held */ | ||
615 | void | ||
616 | aoecmd_work(struct aoedev *d) | ||
617 | { | ||
618 | struct buf *buf; | ||
619 | loop: | ||
620 | if (d->htgt && !sthtith(d)) | ||
621 | return; | ||
622 | if (d->inprocess == NULL) { | ||
623 | if (list_empty(&d->bufq)) | ||
624 | return; | ||
625 | buf = container_of(d->bufq.next, struct buf, bufs); | ||
626 | list_del(d->bufq.next); | ||
627 | d->inprocess = buf; | ||
628 | } | ||
629 | if (aoecmd_ata_rw(d)) | ||
630 | goto loop; | ||
631 | } | ||
632 | |||
411 | /* this function performs work that has been deferred until sleeping is OK | 633 | /* this function performs work that has been deferred until sleeping is OK |
412 | */ | 634 | */ |
413 | void | 635 | void |
@@ -440,7 +662,7 @@ aoecmd_sleepwork(struct work_struct *work) | |||
440 | } | 662 | } |
441 | 663 | ||
442 | static void | 664 | static void |
443 | ataid_complete(struct aoedev *d, unsigned char *id) | 665 | ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) |
444 | { | 666 | { |
445 | u64 ssize; | 667 | u64 ssize; |
446 | u16 n; | 668 | u16 n; |
@@ -475,24 +697,20 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
475 | } | 697 | } |
476 | 698 | ||
477 | if (d->ssize != ssize) | 699 | if (d->ssize != ssize) |
478 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", | 700 | printk(KERN_INFO |
479 | (unsigned long long)mac_addr(d->addr), | 701 | "aoe: %012llx e%ld.%d v%04x has %llu sectors\n", |
702 | mac_addr(t->addr), | ||
480 | d->aoemajor, d->aoeminor, | 703 | d->aoemajor, d->aoeminor, |
481 | d->fw_ver, (long long)ssize); | 704 | d->fw_ver, (long long)ssize); |
482 | d->ssize = ssize; | 705 | d->ssize = ssize; |
483 | d->geo.start = 0; | 706 | d->geo.start = 0; |
707 | if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) | ||
708 | return; | ||
484 | if (d->gd != NULL) { | 709 | if (d->gd != NULL) { |
485 | d->gd->capacity = ssize; | 710 | d->gd->capacity = ssize; |
486 | d->flags |= DEVFL_NEWSIZE; | 711 | d->flags |= DEVFL_NEWSIZE; |
487 | } else { | 712 | } else |
488 | if (d->flags & DEVFL_GDALLOC) { | ||
489 | printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n", | ||
490 | d->aoemajor, d->aoeminor, | ||
491 | "it's already on! This shouldn't happen.\n"); | ||
492 | return; | ||
493 | } | ||
494 | d->flags |= DEVFL_GDALLOC; | 713 | d->flags |= DEVFL_GDALLOC; |
495 | } | ||
496 | schedule_work(&d->work); | 714 | schedule_work(&d->work); |
497 | } | 715 | } |
498 | 716 | ||
@@ -519,6 +737,31 @@ calc_rttavg(struct aoedev *d, int rtt) | |||
519 | d->rttavg += n >> 2; | 737 | d->rttavg += n >> 2; |
520 | } | 738 | } |
521 | 739 | ||
740 | static struct aoetgt * | ||
741 | gettgt(struct aoedev *d, char *addr) | ||
742 | { | ||
743 | struct aoetgt **t, **e; | ||
744 | |||
745 | t = d->targets; | ||
746 | e = t + NTARGETS; | ||
747 | for (; t < e && *t; t++) | ||
748 | if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) | ||
749 | return *t; | ||
750 | return NULL; | ||
751 | } | ||
752 | |||
753 | static inline void | ||
754 | diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector) | ||
755 | { | ||
756 | unsigned long n_sect = bio->bi_size >> 9; | ||
757 | const int rw = bio_data_dir(bio); | ||
758 | |||
759 | all_stat_inc(disk, ios[rw], sector); | ||
760 | all_stat_add(disk, ticks[rw], duration, sector); | ||
761 | all_stat_add(disk, sectors[rw], n_sect, sector); | ||
762 | all_stat_add(disk, io_ticks, duration, sector); | ||
763 | } | ||
764 | |||
522 | void | 765 | void |
523 | aoecmd_ata_rsp(struct sk_buff *skb) | 766 | aoecmd_ata_rsp(struct sk_buff *skb) |
524 | { | 767 | { |
@@ -528,6 +771,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
528 | struct frame *f; | 771 | struct frame *f; |
529 | struct buf *buf; | 772 | struct buf *buf; |
530 | struct sk_buff *sl; | 773 | struct sk_buff *sl; |
774 | struct aoetgt *t; | ||
775 | struct aoeif *ifp; | ||
531 | register long n; | 776 | register long n; |
532 | ulong flags; | 777 | ulong flags; |
533 | char ebuf[128]; | 778 | char ebuf[128]; |
@@ -547,7 +792,14 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
547 | spin_lock_irqsave(&d->lock, flags); | 792 | spin_lock_irqsave(&d->lock, flags); |
548 | 793 | ||
549 | n = be32_to_cpu(get_unaligned(&hin->tag)); | 794 | n = be32_to_cpu(get_unaligned(&hin->tag)); |
550 | f = getframe(d, n); | 795 | t = gettgt(d, hin->src); |
796 | if (t == NULL) { | ||
797 | printk(KERN_INFO "aoe: can't find target e%ld.%d:%012llx\n", | ||
798 | d->aoemajor, d->aoeminor, mac_addr(hin->src)); | ||
799 | spin_unlock_irqrestore(&d->lock, flags); | ||
800 | return; | ||
801 | } | ||
802 | f = getframe(t, n); | ||
551 | if (f == NULL) { | 803 | if (f == NULL) { |
552 | calc_rttavg(d, -tsince(n)); | 804 | calc_rttavg(d, -tsince(n)); |
553 | spin_unlock_irqrestore(&d->lock, flags); | 805 | spin_unlock_irqrestore(&d->lock, flags); |
@@ -569,24 +821,24 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
569 | ahout = (struct aoe_atahdr *) (hout+1); | 821 | ahout = (struct aoe_atahdr *) (hout+1); |
570 | buf = f->buf; | 822 | buf = f->buf; |
571 | 823 | ||
572 | if (ahout->cmdstat == WIN_IDENTIFY) | ||
573 | d->flags &= ~DEVFL_PAUSE; | ||
574 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | 824 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ |
575 | printk(KERN_ERR | 825 | printk(KERN_ERR |
576 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", | 826 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", |
577 | ahout->cmdstat, ahin->cmdstat, | 827 | ahout->cmdstat, ahin->cmdstat, |
578 | d->aoemajor, d->aoeminor); | 828 | d->aoemajor, d->aoeminor); |
579 | if (buf) | 829 | if (buf) |
580 | buf->flags |= BUFFL_FAIL; | 830 | buf->flags |= BUFFL_FAIL; |
581 | } else { | 831 | } else { |
832 | if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */ | ||
833 | d->htgt = NULL; | ||
582 | n = ahout->scnt << 9; | 834 | n = ahout->scnt << 9; |
583 | switch (ahout->cmdstat) { | 835 | switch (ahout->cmdstat) { |
584 | case WIN_READ: | 836 | case WIN_READ: |
585 | case WIN_READ_EXT: | 837 | case WIN_READ_EXT: |
586 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | 838 | if (skb->len - sizeof *hin - sizeof *ahin < n) { |
587 | printk(KERN_ERR | 839 | printk(KERN_ERR |
588 | "aoe: runt data size in read. skb->len=%d\n", | 840 | "aoe: %s. skb->len=%d need=%ld\n", |
589 | skb->len); | 841 | "runt data size in read", skb->len, n); |
590 | /* fail frame f? just returning will rexmit. */ | 842 | /* fail frame f? just returning will rexmit. */ |
591 | spin_unlock_irqrestore(&d->lock, flags); | 843 | spin_unlock_irqrestore(&d->lock, flags); |
592 | return; | 844 | return; |
@@ -594,32 +846,18 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
594 | memcpy(f->bufaddr, ahin+1, n); | 846 | memcpy(f->bufaddr, ahin+1, n); |
595 | case WIN_WRITE: | 847 | case WIN_WRITE: |
596 | case WIN_WRITE_EXT: | 848 | case WIN_WRITE_EXT: |
849 | ifp = getif(t, skb->dev); | ||
850 | if (ifp) { | ||
851 | ifp->lost = 0; | ||
852 | if (n > DEFAULTBCNT) | ||
853 | ifp->lostjumbo = 0; | ||
854 | } | ||
597 | if (f->bcnt -= n) { | 855 | if (f->bcnt -= n) { |
598 | skb = f->skb; | 856 | f->lba += n >> 9; |
599 | f->bufaddr += n; | 857 | f->bufaddr += n; |
600 | put_lba(ahout, f->lba += ahout->scnt); | 858 | resend(d, t, f); |
601 | n = f->bcnt; | 859 | goto xmit; |
602 | if (n > DEFAULTBCNT) | ||
603 | n = DEFAULTBCNT; | ||
604 | ahout->scnt = n >> 9; | ||
605 | if (ahout->aflags & AOEAFL_WRITE) { | ||
606 | skb_fill_page_desc(skb, 0, | ||
607 | virt_to_page(f->bufaddr), | ||
608 | offset_in_page(f->bufaddr), n); | ||
609 | skb->len = sizeof *hout + sizeof *ahout + n; | ||
610 | skb->data_len = n; | ||
611 | } | ||
612 | f->tag = newtag(d); | ||
613 | hout->tag = cpu_to_be32(f->tag); | ||
614 | skb->dev = d->ifp; | ||
615 | skb = skb_clone(skb, GFP_ATOMIC); | ||
616 | spin_unlock_irqrestore(&d->lock, flags); | ||
617 | if (skb) | ||
618 | aoenet_xmit(skb); | ||
619 | return; | ||
620 | } | 860 | } |
621 | if (n > DEFAULTBCNT) | ||
622 | d->lostjumbo = 0; | ||
623 | break; | 861 | break; |
624 | case WIN_IDENTIFY: | 862 | case WIN_IDENTIFY: |
625 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | 863 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { |
@@ -629,7 +867,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
629 | spin_unlock_irqrestore(&d->lock, flags); | 867 | spin_unlock_irqrestore(&d->lock, flags); |
630 | return; | 868 | return; |
631 | } | 869 | } |
632 | ataid_complete(d, (char *) (ahin+1)); | 870 | ataid_complete(d, t, (char *) (ahin+1)); |
633 | break; | 871 | break; |
634 | default: | 872 | default: |
635 | printk(KERN_INFO | 873 | printk(KERN_INFO |
@@ -640,28 +878,19 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
640 | } | 878 | } |
641 | } | 879 | } |
642 | 880 | ||
643 | if (buf) { | 881 | if (buf && --buf->nframesout == 0 && buf->resid == 0) { |
644 | buf->nframesout -= 1; | 882 | diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector); |
645 | if (buf->nframesout == 0 && buf->resid == 0) { | 883 | n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; |
646 | unsigned long duration = jiffies - buf->start_time; | 884 | bio_endio(buf->bio, n); |
647 | unsigned long n_sect = buf->bio->bi_size >> 9; | 885 | mempool_free(buf, d->bufpool); |
648 | struct gendisk *disk = d->gd; | ||
649 | const int rw = bio_data_dir(buf->bio); | ||
650 | |||
651 | disk_stat_inc(disk, ios[rw]); | ||
652 | disk_stat_add(disk, ticks[rw], duration); | ||
653 | disk_stat_add(disk, sectors[rw], n_sect); | ||
654 | disk_stat_add(disk, io_ticks, duration); | ||
655 | n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; | ||
656 | bio_endio(buf->bio, n); | ||
657 | mempool_free(buf, d->bufpool); | ||
658 | } | ||
659 | } | 886 | } |
660 | 887 | ||
661 | f->buf = NULL; | 888 | f->buf = NULL; |
662 | f->tag = FREETAG; | 889 | f->tag = FREETAG; |
890 | t->nout--; | ||
663 | 891 | ||
664 | aoecmd_work(d); | 892 | aoecmd_work(d); |
893 | xmit: | ||
665 | sl = d->sendq_hd; | 894 | sl = d->sendq_hd; |
666 | d->sendq_hd = d->sendq_tl = NULL; | 895 | d->sendq_hd = d->sendq_tl = NULL; |
667 | 896 | ||
@@ -679,23 +908,20 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) | |||
679 | aoenet_xmit(sl); | 908 | aoenet_xmit(sl); |
680 | } | 909 | } |
681 | 910 | ||
682 | /* | 911 | struct sk_buff * |
683 | * Since we only call this in one place (and it only prepares one frame) | ||
684 | * we just return the skb. Usually we'd chain it up to the aoedev sendq. | ||
685 | */ | ||
686 | static struct sk_buff * | ||
687 | aoecmd_ata_id(struct aoedev *d) | 912 | aoecmd_ata_id(struct aoedev *d) |
688 | { | 913 | { |
689 | struct aoe_hdr *h; | 914 | struct aoe_hdr *h; |
690 | struct aoe_atahdr *ah; | 915 | struct aoe_atahdr *ah; |
691 | struct frame *f; | 916 | struct frame *f; |
692 | struct sk_buff *skb; | 917 | struct sk_buff *skb; |
918 | struct aoetgt *t; | ||
693 | 919 | ||
694 | f = freeframe(d); | 920 | f = freeframe(d); |
695 | if (f == NULL) { | 921 | if (f == NULL) |
696 | printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); | ||
697 | return NULL; | 922 | return NULL; |
698 | } | 923 | |
924 | t = *d->tgt; | ||
699 | 925 | ||
700 | /* initialize the headers & frame */ | 926 | /* initialize the headers & frame */ |
701 | skb = f->skb; | 927 | skb = f->skb; |
@@ -703,7 +929,8 @@ aoecmd_ata_id(struct aoedev *d) | |||
703 | ah = (struct aoe_atahdr *) (h+1); | 929 | ah = (struct aoe_atahdr *) (h+1); |
704 | skb_put(skb, sizeof *h + sizeof *ah); | 930 | skb_put(skb, sizeof *h + sizeof *ah); |
705 | memset(h, 0, skb->len); | 931 | memset(h, 0, skb->len); |
706 | f->tag = aoehdr_atainit(d, h); | 932 | f->tag = aoehdr_atainit(d, t, h); |
933 | t->nout++; | ||
707 | f->waited = 0; | 934 | f->waited = 0; |
708 | 935 | ||
709 | /* set up ata header */ | 936 | /* set up ata header */ |
@@ -711,7 +938,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
711 | ah->cmdstat = WIN_IDENTIFY; | 938 | ah->cmdstat = WIN_IDENTIFY; |
712 | ah->lba3 = 0xa0; | 939 | ah->lba3 = 0xa0; |
713 | 940 | ||
714 | skb->dev = d->ifp; | 941 | skb->dev = t->ifp->nd; |
715 | 942 | ||
716 | d->rttavg = MAXTIMER; | 943 | d->rttavg = MAXTIMER; |
717 | d->timer.function = rexmit_timer; | 944 | d->timer.function = rexmit_timer; |
@@ -719,15 +946,52 @@ aoecmd_ata_id(struct aoedev *d) | |||
719 | return skb_clone(skb, GFP_ATOMIC); | 946 | return skb_clone(skb, GFP_ATOMIC); |
720 | } | 947 | } |
721 | 948 | ||
949 | static struct aoetgt * | ||
950 | addtgt(struct aoedev *d, char *addr, ulong nframes) | ||
951 | { | ||
952 | struct aoetgt *t, **tt, **te; | ||
953 | struct frame *f, *e; | ||
954 | |||
955 | tt = d->targets; | ||
956 | te = tt + NTARGETS; | ||
957 | for (; tt < te && *tt; tt++) | ||
958 | ; | ||
959 | |||
960 | if (tt == te) { | ||
961 | printk(KERN_INFO | ||
962 | "aoe: device addtgt failure; too many targets\n"); | ||
963 | return NULL; | ||
964 | } | ||
965 | t = kcalloc(1, sizeof *t, GFP_ATOMIC); | ||
966 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | ||
967 | if (!t || !f) { | ||
968 | kfree(f); | ||
969 | kfree(t); | ||
970 | printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); | ||
971 | return NULL; | ||
972 | } | ||
973 | |||
974 | t->nframes = nframes; | ||
975 | t->frames = f; | ||
976 | e = f + nframes; | ||
977 | for (; f < e; f++) | ||
978 | f->tag = FREETAG; | ||
979 | memcpy(t->addr, addr, sizeof t->addr); | ||
980 | t->ifp = t->ifs; | ||
981 | t->maxout = t->nframes; | ||
982 | return *tt = t; | ||
983 | } | ||
984 | |||
722 | void | 985 | void |
723 | aoecmd_cfg_rsp(struct sk_buff *skb) | 986 | aoecmd_cfg_rsp(struct sk_buff *skb) |
724 | { | 987 | { |
725 | struct aoedev *d; | 988 | struct aoedev *d; |
726 | struct aoe_hdr *h; | 989 | struct aoe_hdr *h; |
727 | struct aoe_cfghdr *ch; | 990 | struct aoe_cfghdr *ch; |
991 | struct aoetgt *t; | ||
992 | struct aoeif *ifp; | ||
728 | ulong flags, sysminor, aoemajor; | 993 | ulong flags, sysminor, aoemajor; |
729 | struct sk_buff *sl; | 994 | struct sk_buff *sl; |
730 | enum { MAXFRAMES = 16 }; | ||
731 | u16 n; | 995 | u16 n; |
732 | 996 | ||
733 | h = (struct aoe_hdr *) skb_mac_header(skb); | 997 | h = (struct aoe_hdr *) skb_mac_header(skb); |
@@ -752,10 +1016,10 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
752 | } | 1016 | } |
753 | 1017 | ||
754 | n = be16_to_cpu(ch->bufcnt); | 1018 | n = be16_to_cpu(ch->bufcnt); |
755 | if (n > MAXFRAMES) /* keep it reasonable */ | 1019 | if (n > aoe_maxout) /* keep it reasonable */ |
756 | n = MAXFRAMES; | 1020 | n = aoe_maxout; |
757 | 1021 | ||
758 | d = aoedev_by_sysminor_m(sysminor, n); | 1022 | d = aoedev_by_sysminor_m(sysminor); |
759 | if (d == NULL) { | 1023 | if (d == NULL) { |
760 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); | 1024 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); |
761 | return; | 1025 | return; |
@@ -763,38 +1027,74 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
763 | 1027 | ||
764 | spin_lock_irqsave(&d->lock, flags); | 1028 | spin_lock_irqsave(&d->lock, flags); |
765 | 1029 | ||
766 | /* permit device to migrate mac and network interface */ | 1030 | t = gettgt(d, h->src); |
767 | d->ifp = skb->dev; | 1031 | if (!t) { |
768 | memcpy(d->addr, h->src, sizeof d->addr); | 1032 | t = addtgt(d, h->src, n); |
769 | if (!(d->flags & DEVFL_MAXBCNT)) { | 1033 | if (!t) { |
770 | n = d->ifp->mtu; | 1034 | spin_unlock_irqrestore(&d->lock, flags); |
1035 | return; | ||
1036 | } | ||
1037 | } | ||
1038 | ifp = getif(t, skb->dev); | ||
1039 | if (!ifp) { | ||
1040 | ifp = addif(t, skb->dev); | ||
1041 | if (!ifp) { | ||
1042 | printk(KERN_INFO | ||
1043 | "aoe: device addif failure; " | ||
1044 | "too many interfaces?\n"); | ||
1045 | spin_unlock_irqrestore(&d->lock, flags); | ||
1046 | return; | ||
1047 | } | ||
1048 | } | ||
1049 | if (ifp->maxbcnt) { | ||
1050 | n = ifp->nd->mtu; | ||
771 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | 1051 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); |
772 | n /= 512; | 1052 | n /= 512; |
773 | if (n > ch->scnt) | 1053 | if (n > ch->scnt) |
774 | n = ch->scnt; | 1054 | n = ch->scnt; |
775 | n = n ? n * 512 : DEFAULTBCNT; | 1055 | n = n ? n * 512 : DEFAULTBCNT; |
776 | if (n != d->maxbcnt) { | 1056 | if (n != ifp->maxbcnt) { |
777 | printk(KERN_INFO | 1057 | printk(KERN_INFO |
778 | "aoe: e%ld.%ld: setting %d byte data frames on %s\n", | 1058 | "aoe: e%ld.%d: setting %d%s%s:%012llx\n", |
779 | d->aoemajor, d->aoeminor, n, d->ifp->name); | 1059 | d->aoemajor, d->aoeminor, n, |
780 | d->maxbcnt = n; | 1060 | " byte data frames on ", ifp->nd->name, |
1061 | mac_addr(t->addr)); | ||
1062 | ifp->maxbcnt = n; | ||
781 | } | 1063 | } |
782 | } | 1064 | } |
783 | 1065 | ||
784 | /* don't change users' perspective */ | 1066 | /* don't change users' perspective */ |
785 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { | 1067 | if (d->nopen) { |
786 | spin_unlock_irqrestore(&d->lock, flags); | 1068 | spin_unlock_irqrestore(&d->lock, flags); |
787 | return; | 1069 | return; |
788 | } | 1070 | } |
789 | d->flags |= DEVFL_PAUSE; /* force pause */ | ||
790 | d->mintimer = MINTIMER; | ||
791 | d->fw_ver = be16_to_cpu(ch->fwver); | 1071 | d->fw_ver = be16_to_cpu(ch->fwver); |
792 | 1072 | ||
793 | /* check for already outstanding ataid */ | 1073 | sl = aoecmd_ata_id(d); |
794 | sl = aoedev_isbusy(d) == 0 ? aoecmd_ata_id(d) : NULL; | ||
795 | 1074 | ||
796 | spin_unlock_irqrestore(&d->lock, flags); | 1075 | spin_unlock_irqrestore(&d->lock, flags); |
797 | 1076 | ||
798 | aoenet_xmit(sl); | 1077 | aoenet_xmit(sl); |
799 | } | 1078 | } |
800 | 1079 | ||
1080 | void | ||
1081 | aoecmd_cleanslate(struct aoedev *d) | ||
1082 | { | ||
1083 | struct aoetgt **t, **te; | ||
1084 | struct aoeif *p, *e; | ||
1085 | |||
1086 | d->mintimer = MINTIMER; | ||
1087 | |||
1088 | t = d->targets; | ||
1089 | te = t + NTARGETS; | ||
1090 | for (; t < te && *t; t++) { | ||
1091 | (*t)->maxout = (*t)->nframes; | ||
1092 | p = (*t)->ifs; | ||
1093 | e = p + NAOEIFS; | ||
1094 | for (; p < e; p++) { | ||
1095 | p->lostjumbo = 0; | ||
1096 | p->lost = 0; | ||
1097 | p->maxbcnt = DEFAULTBCNT; | ||
1098 | } | ||
1099 | } | ||
1100 | } | ||
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 51f50710e5fc..f9a1cd9edb77 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 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. |
@@ -7,23 +7,32 @@ | |||
7 | #include <linux/hdreg.h> | 7 | #include <linux/hdreg.h> |
8 | #include <linux/blkdev.h> | 8 | #include <linux/blkdev.h> |
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | #include <linux/delay.h> | ||
10 | #include "aoe.h" | 11 | #include "aoe.h" |
11 | 12 | ||
13 | static void dummy_timer(ulong); | ||
14 | static void aoedev_freedev(struct aoedev *); | ||
15 | static void freetgt(struct aoedev *d, struct aoetgt *t); | ||
16 | static void skbpoolfree(struct aoedev *d); | ||
17 | |||
12 | static struct aoedev *devlist; | 18 | static struct aoedev *devlist; |
13 | static spinlock_t devlist_lock; | 19 | static DEFINE_SPINLOCK(devlist_lock); |
14 | 20 | ||
15 | int | 21 | int |
16 | aoedev_isbusy(struct aoedev *d) | 22 | aoedev_isbusy(struct aoedev *d) |
17 | { | 23 | { |
24 | struct aoetgt **t, **te; | ||
18 | struct frame *f, *e; | 25 | struct frame *f, *e; |
19 | 26 | ||
20 | f = d->frames; | 27 | t = d->targets; |
21 | e = f + d->nframes; | 28 | te = t + NTARGETS; |
22 | do { | 29 | for (; t < te && *t; t++) { |
23 | if (f->tag != FREETAG) | 30 | f = (*t)->frames; |
24 | return 1; | 31 | e = f + (*t)->nframes; |
25 | } while (++f < e); | 32 | for (; f < e; f++) |
26 | 33 | if (f->tag != FREETAG) | |
34 | return 1; | ||
35 | } | ||
27 | return 0; | 36 | return 0; |
28 | } | 37 | } |
29 | 38 | ||
@@ -55,75 +64,41 @@ dummy_timer(ulong vp) | |||
55 | add_timer(&d->timer); | 64 | add_timer(&d->timer); |
56 | } | 65 | } |
57 | 66 | ||
58 | /* called with devlist lock held */ | ||
59 | static struct aoedev * | ||
60 | aoedev_newdev(ulong nframes) | ||
61 | { | ||
62 | struct aoedev *d; | ||
63 | struct frame *f, *e; | ||
64 | |||
65 | d = kzalloc(sizeof *d, GFP_ATOMIC); | ||
66 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | ||
67 | switch (!d || !f) { | ||
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); | ||
89 | return NULL; | ||
90 | } | ||
91 | INIT_WORK(&d->work, aoecmd_sleepwork); | ||
92 | spin_lock_init(&d->lock); | ||
93 | init_timer(&d->timer); | ||
94 | d->timer.data = (ulong) d; | ||
95 | d->timer.function = dummy_timer; | ||
96 | d->timer.expires = jiffies + HZ; | ||
97 | add_timer(&d->timer); | ||
98 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ | ||
99 | INIT_LIST_HEAD(&d->bufq); | ||
100 | d->next = devlist; | ||
101 | devlist = d; | ||
102 | |||
103 | return d; | ||
104 | } | ||
105 | |||
106 | void | 67 | void |
107 | aoedev_downdev(struct aoedev *d) | 68 | aoedev_downdev(struct aoedev *d) |
108 | { | 69 | { |
70 | struct aoetgt **t, **te; | ||
109 | struct frame *f, *e; | 71 | struct frame *f, *e; |
110 | struct buf *buf; | 72 | struct buf *buf; |
111 | struct bio *bio; | 73 | struct bio *bio; |
112 | 74 | ||
113 | f = d->frames; | 75 | t = d->targets; |
114 | e = f + d->nframes; | 76 | te = t + NTARGETS; |
115 | for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) { | 77 | for (; t < te && *t; t++) { |
116 | if (f->tag == FREETAG || f->buf == NULL) | 78 | f = (*t)->frames; |
117 | continue; | 79 | e = f + (*t)->nframes; |
118 | buf = f->buf; | 80 | for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) { |
119 | bio = buf->bio; | 81 | if (f->tag == FREETAG || f->buf == NULL) |
120 | if (--buf->nframesout == 0) { | 82 | continue; |
121 | mempool_free(buf, d->bufpool); | 83 | buf = f->buf; |
122 | bio_endio(bio, -EIO); | 84 | bio = buf->bio; |
85 | if (--buf->nframesout == 0 | ||
86 | && buf != d->inprocess) { | ||
87 | mempool_free(buf, d->bufpool); | ||
88 | bio_endio(bio, -EIO); | ||
89 | } | ||
123 | } | 90 | } |
124 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | 91 | (*t)->maxout = (*t)->nframes; |
92 | (*t)->nout = 0; | ||
93 | } | ||
94 | buf = d->inprocess; | ||
95 | if (buf) { | ||
96 | bio = buf->bio; | ||
97 | mempool_free(buf, d->bufpool); | ||
98 | bio_endio(bio, -EIO); | ||
125 | } | 99 | } |
126 | d->inprocess = NULL; | 100 | d->inprocess = NULL; |
101 | d->htgt = NULL; | ||
127 | 102 | ||
128 | while (!list_empty(&d->bufq)) { | 103 | while (!list_empty(&d->bufq)) { |
129 | buf = container_of(d->bufq.next, struct buf, bufs); | 104 | buf = container_of(d->bufq.next, struct buf, bufs); |
@@ -136,12 +111,114 @@ aoedev_downdev(struct aoedev *d) | |||
136 | if (d->gd) | 111 | if (d->gd) |
137 | d->gd->capacity = 0; | 112 | d->gd->capacity = 0; |
138 | 113 | ||
139 | d->flags &= ~(DEVFL_UP | DEVFL_PAUSE); | 114 | d->flags &= ~DEVFL_UP; |
115 | } | ||
116 | |||
117 | static void | ||
118 | aoedev_freedev(struct aoedev *d) | ||
119 | { | ||
120 | struct aoetgt **t, **e; | ||
121 | |||
122 | if (d->gd) { | ||
123 | aoedisk_rm_sysfs(d); | ||
124 | del_gendisk(d->gd); | ||
125 | put_disk(d->gd); | ||
126 | } | ||
127 | t = d->targets; | ||
128 | e = t + NTARGETS; | ||
129 | for (; t < e && *t; t++) | ||
130 | freetgt(d, *t); | ||
131 | if (d->bufpool) | ||
132 | mempool_destroy(d->bufpool); | ||
133 | skbpoolfree(d); | ||
134 | kfree(d); | ||
135 | } | ||
136 | |||
137 | int | ||
138 | aoedev_flush(const char __user *str, size_t cnt) | ||
139 | { | ||
140 | ulong flags; | ||
141 | struct aoedev *d, **dd; | ||
142 | struct aoedev *rmd = NULL; | ||
143 | char buf[16]; | ||
144 | int all = 0; | ||
145 | |||
146 | if (cnt >= 3) { | ||
147 | if (cnt > sizeof buf) | ||
148 | cnt = sizeof buf; | ||
149 | if (copy_from_user(buf, str, cnt)) | ||
150 | return -EFAULT; | ||
151 | all = !strncmp(buf, "all", 3); | ||
152 | } | ||
153 | |||
154 | flush_scheduled_work(); | ||
155 | spin_lock_irqsave(&devlist_lock, flags); | ||
156 | dd = &devlist; | ||
157 | while ((d = *dd)) { | ||
158 | spin_lock(&d->lock); | ||
159 | if ((!all && (d->flags & DEVFL_UP)) | ||
160 | || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) | ||
161 | || d->nopen) { | ||
162 | spin_unlock(&d->lock); | ||
163 | dd = &d->next; | ||
164 | continue; | ||
165 | } | ||
166 | *dd = d->next; | ||
167 | aoedev_downdev(d); | ||
168 | d->flags |= DEVFL_TKILL; | ||
169 | spin_unlock(&d->lock); | ||
170 | d->next = rmd; | ||
171 | rmd = d; | ||
172 | } | ||
173 | spin_unlock_irqrestore(&devlist_lock, flags); | ||
174 | while ((d = rmd)) { | ||
175 | rmd = d->next; | ||
176 | del_timer_sync(&d->timer); | ||
177 | aoedev_freedev(d); /* must be able to sleep */ | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | /* I'm not really sure that this is a realistic problem, but if the | ||
183 | network driver goes gonzo let's just leak memory after complaining. */ | ||
184 | static void | ||
185 | skbfree(struct sk_buff *skb) | ||
186 | { | ||
187 | enum { Sms = 100, Tms = 3*1000}; | ||
188 | int i = Tms / Sms; | ||
189 | |||
190 | if (skb == NULL) | ||
191 | return; | ||
192 | while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0) | ||
193 | msleep(Sms); | ||
194 | if (i <= 0) { | ||
195 | printk(KERN_ERR | ||
196 | "aoe: %s holds ref: %s\n", | ||
197 | skb->dev ? skb->dev->name : "netif", | ||
198 | "cannot free skb -- memory leaked."); | ||
199 | return; | ||
200 | } | ||
201 | skb_shinfo(skb)->nr_frags = skb->data_len = 0; | ||
202 | skb_trim(skb, 0); | ||
203 | dev_kfree_skb(skb); | ||
204 | } | ||
205 | |||
206 | static void | ||
207 | skbpoolfree(struct aoedev *d) | ||
208 | { | ||
209 | struct sk_buff *skb; | ||
210 | |||
211 | while ((skb = d->skbpool_hd)) { | ||
212 | d->skbpool_hd = skb->next; | ||
213 | skb->next = NULL; | ||
214 | skbfree(skb); | ||
215 | } | ||
216 | d->skbpool_tl = NULL; | ||
140 | } | 217 | } |
141 | 218 | ||
142 | /* find it or malloc it */ | 219 | /* find it or malloc it */ |
143 | struct aoedev * | 220 | struct aoedev * |
144 | aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | 221 | aoedev_by_sysminor_m(ulong sysminor) |
145 | { | 222 | { |
146 | struct aoedev *d; | 223 | struct aoedev *d; |
147 | ulong flags; | 224 | ulong flags; |
@@ -151,43 +228,43 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
151 | for (d=devlist; d; d=d->next) | 228 | for (d=devlist; d; d=d->next) |
152 | if (d->sysminor == sysminor) | 229 | if (d->sysminor == sysminor) |
153 | break; | 230 | break; |
154 | 231 | if (d) | |
155 | if (d == NULL) { | 232 | goto out; |
156 | d = aoedev_newdev(bufcnt); | 233 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); |
157 | if (d == NULL) { | 234 | if (!d) |
158 | spin_unlock_irqrestore(&devlist_lock, flags); | 235 | goto out; |
159 | printk(KERN_INFO "aoe: aoedev_newdev failure.\n"); | 236 | INIT_WORK(&d->work, aoecmd_sleepwork); |
160 | return NULL; | 237 | spin_lock_init(&d->lock); |
161 | } | 238 | init_timer(&d->timer); |
162 | d->sysminor = sysminor; | 239 | d->timer.data = (ulong) d; |
163 | d->aoemajor = AOEMAJOR(sysminor); | 240 | d->timer.function = dummy_timer; |
164 | d->aoeminor = AOEMINOR(sysminor); | 241 | d->timer.expires = jiffies + HZ; |
165 | } | 242 | add_timer(&d->timer); |
166 | 243 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ | |
244 | d->tgt = d->targets; | ||
245 | INIT_LIST_HEAD(&d->bufq); | ||
246 | d->sysminor = sysminor; | ||
247 | d->aoemajor = AOEMAJOR(sysminor); | ||
248 | d->aoeminor = AOEMINOR(sysminor); | ||
249 | d->mintimer = MINTIMER; | ||
250 | d->next = devlist; | ||
251 | devlist = d; | ||
252 | out: | ||
167 | spin_unlock_irqrestore(&devlist_lock, flags); | 253 | spin_unlock_irqrestore(&devlist_lock, flags); |
168 | return d; | 254 | return d; |
169 | } | 255 | } |
170 | 256 | ||
171 | static void | 257 | static void |
172 | aoedev_freedev(struct aoedev *d) | 258 | freetgt(struct aoedev *d, struct aoetgt *t) |
173 | { | 259 | { |
174 | struct frame *f, *e; | 260 | struct frame *f, *e; |
175 | 261 | ||
176 | if (d->gd) { | 262 | f = t->frames; |
177 | aoedisk_rm_sysfs(d); | 263 | e = f + t->nframes; |
178 | del_gendisk(d->gd); | 264 | for (; f < e; f++) |
179 | put_disk(d->gd); | 265 | skbfree(f->skb); |
180 | } | 266 | kfree(t->frames); |
181 | f = d->frames; | 267 | kfree(t); |
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 | } | ||
187 | kfree(d->frames); | ||
188 | if (d->bufpool) | ||
189 | mempool_destroy(d->bufpool); | ||
190 | kfree(d); | ||
191 | } | 268 | } |
192 | 269 | ||
193 | void | 270 | void |
@@ -214,7 +291,5 @@ aoedev_exit(void) | |||
214 | int __init | 291 | int __init |
215 | aoedev_init(void) | 292 | aoedev_init(void) |
216 | { | 293 | { |
217 | spin_lock_init(&devlist_lock); | ||
218 | return 0; | 294 | return 0; |
219 | } | 295 | } |
220 | |||
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index a04b7d613299..7b15a5e9cec0 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 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 |
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 4e6deb7f5c24..8460ef736d56 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2007 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 |
@@ -83,7 +83,7 @@ set_aoe_iflist(const char __user *user_str, size_t size) | |||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | u64 | 86 | unsigned long long |
87 | mac_addr(char addr[6]) | 87 | mac_addr(char addr[6]) |
88 | { | 88 | { |
89 | __be64 n = 0; | 89 | __be64 n = 0; |
@@ -91,7 +91,7 @@ mac_addr(char addr[6]) | |||
91 | 91 | ||
92 | memcpy(p + 2, addr, 6); /* (sizeof addr != 6) */ | 92 | memcpy(p + 2, addr, 6); /* (sizeof addr != 6) */ |
93 | 93 | ||
94 | return __be64_to_cpu(n); | 94 | return (unsigned long long) __be64_to_cpu(n); |
95 | } | 95 | } |
96 | 96 | ||
97 | void | 97 | void |
@@ -137,9 +137,12 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
137 | if (n > NECODES) | 137 | if (n > NECODES) |
138 | n = 0; | 138 | n = 0; |
139 | if (net_ratelimit()) | 139 | if (net_ratelimit()) |
140 | printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n", | 140 | printk(KERN_ERR |
141 | be16_to_cpu(get_unaligned(&h->major)), h->minor, | 141 | "%s%d.%d@%s; ecode=%d '%s'\n", |
142 | h->err, aoe_errlist[n]); | 142 | "aoe: error packet from ", |
143 | be16_to_cpu(get_unaligned(&h->major)), | ||
144 | h->minor, skb->dev->name, | ||
145 | h->err, aoe_errlist[n]); | ||
143 | goto exit; | 146 | goto exit; |
144 | } | 147 | } |
145 | 148 | ||