diff options
Diffstat (limited to 'drivers/block/aoe/aoecmd.c')
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 675 |
1 files changed, 460 insertions, 215 deletions
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 4d59d5057734..5e7daa1ff6f6 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -9,19 +9,16 @@ | |||
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 struct sk_buff * |
25 | new_skb(ulong len) | 22 | new_skb(ulong len) |
26 | { | 23 | { |
27 | struct sk_buff *skb; | 24 | struct sk_buff *skb; |
@@ -43,12 +40,12 @@ new_skb(ulong len) | |||
43 | } | 40 | } |
44 | 41 | ||
45 | static struct frame * | 42 | static struct frame * |
46 | getframe(struct aoedev *d, int tag) | 43 | getframe(struct aoetgt *t, int tag) |
47 | { | 44 | { |
48 | struct frame *f, *e; | 45 | struct frame *f, *e; |
49 | 46 | ||
50 | f = d->frames; | 47 | f = t->frames; |
51 | e = f + d->nframes; | 48 | e = f + t->nframes; |
52 | for (; f<e; f++) | 49 | for (; f<e; f++) |
53 | if (f->tag == tag) | 50 | if (f->tag == tag) |
54 | return f; | 51 | return f; |
@@ -61,21 +58,21 @@ getframe(struct aoedev *d, int tag) | |||
61 | * This driver reserves tag -1 to mean "unused frame." | 58 | * This driver reserves tag -1 to mean "unused frame." |
62 | */ | 59 | */ |
63 | static int | 60 | static int |
64 | newtag(struct aoedev *d) | 61 | newtag(struct aoetgt *t) |
65 | { | 62 | { |
66 | register ulong n; | 63 | register ulong n; |
67 | 64 | ||
68 | n = jiffies & 0xffff; | 65 | n = jiffies & 0xffff; |
69 | return n |= (++d->lasttag & 0x7fff) << 16; | 66 | return n |= (++t->lasttag & 0x7fff) << 16; |
70 | } | 67 | } |
71 | 68 | ||
72 | static int | 69 | static int |
73 | aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) | 70 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) |
74 | { | 71 | { |
75 | u32 host_tag = newtag(d); | 72 | u32 host_tag = newtag(t); |
76 | 73 | ||
77 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 74 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
78 | memcpy(h->dst, d->addr, sizeof h->dst); | 75 | memcpy(h->dst, t->addr, sizeof h->dst); |
79 | h->type = __constant_cpu_to_be16(ETH_P_AOE); | 76 | h->type = __constant_cpu_to_be16(ETH_P_AOE); |
80 | h->verfl = AOE_HVER; | 77 | h->verfl = AOE_HVER; |
81 | h->major = cpu_to_be16(d->aoemajor); | 78 | h->major = cpu_to_be16(d->aoemajor); |
@@ -98,42 +95,103 @@ put_lba(struct aoe_atahdr *ah, sector_t lba) | |||
98 | } | 95 | } |
99 | 96 | ||
100 | static void | 97 | static void |
101 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 98 | ifrotate(struct aoetgt *t) |
99 | { | ||
100 | t->ifp++; | ||
101 | if (t->ifp >= &t->ifs[NAOEIFS] || t->ifp->nd == NULL) | ||
102 | t->ifp = t->ifs; | ||
103 | if (t->ifp->nd == NULL) { | ||
104 | printk(KERN_INFO "aoe: no interface to rotate to\n"); | ||
105 | BUG(); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static struct frame * | ||
110 | freeframe(struct aoedev *d) | ||
102 | { | 111 | { |
112 | struct frame *f, *e; | ||
113 | struct aoetgt **t; | ||
114 | ulong n; | ||
115 | |||
116 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ | ||
117 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); | ||
118 | return NULL; | ||
119 | } | ||
120 | t = d->targets; | ||
121 | do { | ||
122 | if (t != d->htgt | ||
123 | && (*t)->ifp->nd | ||
124 | && (*t)->nout < (*t)->maxout) { | ||
125 | n = (*t)->nframes; | ||
126 | f = (*t)->frames; | ||
127 | e = f + n; | ||
128 | for (; f < e; f++) { | ||
129 | if (f->tag != FREETAG) | ||
130 | continue; | ||
131 | if (atomic_read(&skb_shinfo(f->skb)->dataref) | ||
132 | != 1) { | ||
133 | n--; | ||
134 | continue; | ||
135 | } | ||
136 | skb_shinfo(f->skb)->nr_frags = 0; | ||
137 | f->skb->data_len = 0; | ||
138 | skb_trim(f->skb, 0); | ||
139 | d->tgt = t; | ||
140 | ifrotate(*t); | ||
141 | return f; | ||
142 | } | ||
143 | if (n == 0) /* slow polling network card */ | ||
144 | d->flags |= DEVFL_KICKME; | ||
145 | } | ||
146 | t++; | ||
147 | } while (t < &d->targets[NTARGETS] && *t); | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | static int | ||
152 | aoecmd_ata_rw(struct aoedev *d) | ||
153 | { | ||
154 | struct frame *f; | ||
103 | struct aoe_hdr *h; | 155 | struct aoe_hdr *h; |
104 | struct aoe_atahdr *ah; | 156 | struct aoe_atahdr *ah; |
105 | struct buf *buf; | 157 | struct buf *buf; |
158 | struct bio_vec *bv; | ||
159 | struct aoetgt *t; | ||
106 | struct sk_buff *skb; | 160 | struct sk_buff *skb; |
107 | ulong bcnt; | 161 | ulong bcnt; |
108 | register sector_t sector; | ||
109 | char writebit, extbit; | 162 | char writebit, extbit; |
110 | 163 | ||
111 | writebit = 0x10; | 164 | writebit = 0x10; |
112 | extbit = 0x4; | 165 | extbit = 0x4; |
113 | 166 | ||
167 | f = freeframe(d); | ||
168 | if (f == NULL) | ||
169 | return 0; | ||
170 | t = *d->tgt; | ||
114 | buf = d->inprocess; | 171 | buf = d->inprocess; |
115 | 172 | bv = buf->bv; | |
116 | sector = buf->sector; | 173 | bcnt = t->ifp->maxbcnt; |
117 | bcnt = buf->bv_resid; | 174 | if (bcnt == 0) |
118 | if (bcnt > d->maxbcnt) | 175 | bcnt = DEFAULTBCNT; |
119 | bcnt = d->maxbcnt; | 176 | if (bcnt > buf->bv_resid) |
120 | 177 | bcnt = buf->bv_resid; | |
121 | /* initialize the headers & frame */ | 178 | /* initialize the headers & frame */ |
122 | skb = f->skb; | 179 | skb = f->skb; |
123 | h = (struct aoe_hdr *) skb_mac_header(skb); | 180 | h = (struct aoe_hdr *) skb_mac_header(skb); |
124 | ah = (struct aoe_atahdr *) (h+1); | 181 | ah = (struct aoe_atahdr *) (h+1); |
125 | skb_put(skb, sizeof *h + sizeof *ah); | 182 | skb_put(skb, sizeof *h + sizeof *ah); |
126 | memset(h, 0, skb->len); | 183 | memset(h, 0, skb->len); |
127 | f->tag = aoehdr_atainit(d, h); | 184 | f->tag = aoehdr_atainit(d, t, h); |
185 | t->nout++; | ||
128 | f->waited = 0; | 186 | f->waited = 0; |
129 | f->buf = buf; | 187 | f->buf = buf; |
130 | f->bufaddr = buf->bufaddr; | 188 | f->bufaddr = page_address(bv->bv_page) + buf->bv_off; |
131 | f->bcnt = bcnt; | 189 | f->bcnt = bcnt; |
132 | f->lba = sector; | 190 | f->lba = buf->sector; |
133 | 191 | ||
134 | /* set up ata header */ | 192 | /* set up ata header */ |
135 | ah->scnt = bcnt >> 9; | 193 | ah->scnt = bcnt >> 9; |
136 | put_lba(ah, sector); | 194 | put_lba(ah, buf->sector); |
137 | if (d->flags & DEVFL_EXT) { | 195 | if (d->flags & DEVFL_EXT) { |
138 | ah->aflags |= AOEAFL_EXT; | 196 | ah->aflags |= AOEAFL_EXT; |
139 | } else { | 197 | } else { |
@@ -141,14 +199,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
141 | ah->lba3 &= 0x0f; | 199 | ah->lba3 &= 0x0f; |
142 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ | 200 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ |
143 | } | 201 | } |
144 | |||
145 | if (bio_data_dir(buf->bio) == WRITE) { | 202 | if (bio_data_dir(buf->bio) == WRITE) { |
146 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | 203 | 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; | 204 | ah->aflags |= AOEAFL_WRITE; |
149 | skb->len += bcnt; | 205 | skb->len += bcnt; |
150 | skb->data_len = bcnt; | 206 | skb->data_len = bcnt; |
207 | t->wpkts++; | ||
151 | } else { | 208 | } else { |
209 | t->rpkts++; | ||
152 | writebit = 0; | 210 | writebit = 0; |
153 | } | 211 | } |
154 | 212 | ||
@@ -156,29 +214,29 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
156 | 214 | ||
157 | /* mark all tracking fields and load out */ | 215 | /* mark all tracking fields and load out */ |
158 | buf->nframesout += 1; | 216 | buf->nframesout += 1; |
159 | buf->bufaddr += bcnt; | 217 | buf->bv_off += bcnt; |
160 | buf->bv_resid -= bcnt; | 218 | buf->bv_resid -= bcnt; |
161 | /* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ | ||
162 | buf->resid -= bcnt; | 219 | buf->resid -= bcnt; |
163 | buf->sector += bcnt >> 9; | 220 | buf->sector += bcnt >> 9; |
164 | if (buf->resid == 0) { | 221 | if (buf->resid == 0) { |
165 | d->inprocess = NULL; | 222 | d->inprocess = NULL; |
166 | } else if (buf->bv_resid == 0) { | 223 | } else if (buf->bv_resid == 0) { |
167 | buf->bv++; | 224 | buf->bv = ++bv; |
168 | WARN_ON(buf->bv->bv_len == 0); | 225 | buf->bv_resid = bv->bv_len; |
169 | buf->bv_resid = buf->bv->bv_len; | 226 | WARN_ON(buf->bv_resid == 0); |
170 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 227 | buf->bv_off = bv->bv_offset; |
171 | } | 228 | } |
172 | 229 | ||
173 | skb->dev = d->ifp; | 230 | skb->dev = t->ifp->nd; |
174 | skb = skb_clone(skb, GFP_ATOMIC); | 231 | skb = skb_clone(skb, GFP_ATOMIC); |
175 | if (skb == NULL) | 232 | if (skb) { |
176 | return; | 233 | if (d->sendq_hd) |
177 | if (d->sendq_hd) | 234 | d->sendq_tl->next = skb; |
178 | d->sendq_tl->next = skb; | 235 | else |
179 | else | 236 | d->sendq_hd = skb; |
180 | d->sendq_hd = skb; | 237 | d->sendq_tl = skb; |
181 | d->sendq_tl = skb; | 238 | } |
239 | return 1; | ||
182 | } | 240 | } |
183 | 241 | ||
184 | /* some callers cannot sleep, and they can call this function, | 242 | /* some callers cannot sleep, and they can call this function, |
@@ -232,62 +290,8 @@ cont: | |||
232 | return sl; | 290 | return sl; |
233 | } | 291 | } |
234 | 292 | ||
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 | 293 | static void |
290 | rexmit(struct aoedev *d, struct frame *f) | 294 | resend(struct aoedev *d, struct aoetgt *t, struct frame *f) |
291 | { | 295 | { |
292 | struct sk_buff *skb; | 296 | struct sk_buff *skb; |
293 | struct aoe_hdr *h; | 297 | struct aoe_hdr *h; |
@@ -295,41 +299,45 @@ rexmit(struct aoedev *d, struct frame *f) | |||
295 | char buf[128]; | 299 | char buf[128]; |
296 | u32 n; | 300 | u32 n; |
297 | 301 | ||
298 | n = newtag(d); | 302 | ifrotate(t); |
303 | n = newtag(t); | ||
304 | skb = f->skb; | ||
305 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
306 | ah = (struct aoe_atahdr *) (h+1); | ||
299 | 307 | ||
300 | snprintf(buf, sizeof buf, | 308 | snprintf(buf, sizeof buf, |
301 | "%15s e%ld.%ld oldtag=%08x@%08lx newtag=%08x\n", | 309 | "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x " |
302 | "retransmit", | 310 | "s=%012llx d=%012llx nout=%d\n", |
303 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); | 311 | "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n, |
312 | mac_addr(h->src), mac_addr(h->dst), t->nout); | ||
304 | aoechr_error(buf); | 313 | aoechr_error(buf); |
305 | 314 | ||
306 | skb = f->skb; | ||
307 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
308 | ah = (struct aoe_atahdr *) (h+1); | ||
309 | f->tag = n; | 315 | f->tag = n; |
310 | h->tag = cpu_to_be32(n); | 316 | h->tag = cpu_to_be32(n); |
311 | memcpy(h->dst, d->addr, sizeof h->dst); | 317 | memcpy(h->dst, t->addr, sizeof h->dst); |
312 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 318 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
313 | 319 | ||
314 | n = DEFAULTBCNT / 512; | 320 | switch (ah->cmdstat) { |
315 | if (ah->scnt > n) { | 321 | default: |
316 | ah->scnt = n; | 322 | break; |
323 | case WIN_READ: | ||
324 | case WIN_READ_EXT: | ||
325 | case WIN_WRITE: | ||
326 | case WIN_WRITE_EXT: | ||
327 | put_lba(ah, f->lba); | ||
328 | |||
329 | n = f->bcnt; | ||
330 | if (n > DEFAULTBCNT) | ||
331 | n = DEFAULTBCNT; | ||
332 | ah->scnt = n >> 9; | ||
317 | if (ah->aflags & AOEAFL_WRITE) { | 333 | if (ah->aflags & AOEAFL_WRITE) { |
318 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | 334 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), |
319 | offset_in_page(f->bufaddr), DEFAULTBCNT); | 335 | offset_in_page(f->bufaddr), n); |
320 | skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; | 336 | skb->len = sizeof *h + sizeof *ah + n; |
321 | skb->data_len = DEFAULTBCNT; | 337 | 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 | } | 338 | } |
330 | } | 339 | } |
331 | 340 | skb->dev = t->ifp->nd; | |
332 | skb->dev = d->ifp; | ||
333 | skb = skb_clone(skb, GFP_ATOMIC); | 341 | skb = skb_clone(skb, GFP_ATOMIC); |
334 | if (skb == NULL) | 342 | if (skb == NULL) |
335 | return; | 343 | return; |
@@ -352,10 +360,92 @@ tsince(int tag) | |||
352 | return n; | 360 | return n; |
353 | } | 361 | } |
354 | 362 | ||
363 | static struct aoeif * | ||
364 | getif(struct aoetgt *t, struct net_device *nd) | ||
365 | { | ||
366 | struct aoeif *p, *e; | ||
367 | |||
368 | p = t->ifs; | ||
369 | e = p + NAOEIFS; | ||
370 | for (; p < e; p++) | ||
371 | if (p->nd == nd) | ||
372 | return p; | ||
373 | return NULL; | ||
374 | } | ||
375 | |||
376 | static struct aoeif * | ||
377 | addif(struct aoetgt *t, struct net_device *nd) | ||
378 | { | ||
379 | struct aoeif *p; | ||
380 | |||
381 | p = getif(t, NULL); | ||
382 | if (!p) | ||
383 | return NULL; | ||
384 | p->nd = nd; | ||
385 | p->maxbcnt = DEFAULTBCNT; | ||
386 | p->lost = 0; | ||
387 | p->lostjumbo = 0; | ||
388 | return p; | ||
389 | } | ||
390 | |||
391 | static void | ||
392 | ejectif(struct aoetgt *t, struct aoeif *ifp) | ||
393 | { | ||
394 | struct aoeif *e; | ||
395 | ulong n; | ||
396 | |||
397 | e = t->ifs + NAOEIFS - 1; | ||
398 | n = (e - ifp) * sizeof *ifp; | ||
399 | memmove(ifp, ifp+1, n); | ||
400 | e->nd = NULL; | ||
401 | } | ||
402 | |||
403 | static int | ||
404 | sthtith(struct aoedev *d) | ||
405 | { | ||
406 | struct frame *f, *e, *nf; | ||
407 | struct sk_buff *skb; | ||
408 | struct aoetgt *ht = *d->htgt; | ||
409 | |||
410 | f = ht->frames; | ||
411 | e = f + ht->nframes; | ||
412 | for (; f < e; f++) { | ||
413 | if (f->tag == FREETAG) | ||
414 | continue; | ||
415 | nf = freeframe(d); | ||
416 | if (!nf) | ||
417 | return 0; | ||
418 | skb = nf->skb; | ||
419 | *nf = *f; | ||
420 | f->skb = skb; | ||
421 | f->tag = FREETAG; | ||
422 | nf->waited = 0; | ||
423 | ht->nout--; | ||
424 | (*d->tgt)->nout++; | ||
425 | resend(d, *d->tgt, nf); | ||
426 | } | ||
427 | /* he's clean, he's useless. take away his interfaces */ | ||
428 | memset(ht->ifs, 0, sizeof ht->ifs); | ||
429 | d->htgt = NULL; | ||
430 | return 1; | ||
431 | } | ||
432 | |||
433 | static inline unsigned char | ||
434 | ata_scnt(unsigned char *packet) { | ||
435 | struct aoe_hdr *h; | ||
436 | struct aoe_atahdr *ah; | ||
437 | |||
438 | h = (struct aoe_hdr *) packet; | ||
439 | ah = (struct aoe_atahdr *) (h+1); | ||
440 | return ah->scnt; | ||
441 | } | ||
442 | |||
355 | static void | 443 | static void |
356 | rexmit_timer(ulong vp) | 444 | rexmit_timer(ulong vp) |
357 | { | 445 | { |
358 | struct aoedev *d; | 446 | struct aoedev *d; |
447 | struct aoetgt *t, **tt, **te; | ||
448 | struct aoeif *ifp; | ||
359 | struct frame *f, *e; | 449 | struct frame *f, *e; |
360 | struct sk_buff *sl; | 450 | struct sk_buff *sl; |
361 | register long timeout; | 451 | register long timeout; |
@@ -374,31 +464,79 @@ rexmit_timer(ulong vp) | |||
374 | spin_unlock_irqrestore(&d->lock, flags); | 464 | spin_unlock_irqrestore(&d->lock, flags); |
375 | return; | 465 | return; |
376 | } | 466 | } |
377 | f = d->frames; | 467 | tt = d->targets; |
378 | e = f + d->nframes; | 468 | te = tt + NTARGETS; |
379 | for (; f<e; f++) { | 469 | for (; tt < te && *tt; tt++) { |
380 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { | 470 | t = *tt; |
471 | f = t->frames; | ||
472 | e = f + t->nframes; | ||
473 | for (; f < e; f++) { | ||
474 | if (f->tag == FREETAG | ||
475 | || tsince(f->tag) < timeout) | ||
476 | continue; | ||
381 | n = f->waited += timeout; | 477 | n = f->waited += timeout; |
382 | n /= HZ; | 478 | n /= HZ; |
383 | if (n > aoe_deadsecs) { /* waited too long for response */ | 479 | if (n > aoe_deadsecs) { |
480 | /* waited too long. device failure. */ | ||
384 | aoedev_downdev(d); | 481 | aoedev_downdev(d); |
385 | break; | 482 | break; |
386 | } | 483 | } |
387 | rexmit(d, f); | 484 | |
485 | if (n > HELPWAIT /* see if another target can help */ | ||
486 | && (tt != d->targets || d->targets[1])) | ||
487 | d->htgt = tt; | ||
488 | |||
489 | if (t->nout == t->maxout) { | ||
490 | if (t->maxout > 1) | ||
491 | t->maxout--; | ||
492 | t->lastwadj = jiffies; | ||
493 | } | ||
494 | |||
495 | ifp = getif(t, f->skb->dev); | ||
496 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
497 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
498 | ejectif(t, ifp); | ||
499 | ifp = NULL; | ||
500 | } | ||
501 | |||
502 | if (ata_scnt(skb_mac_header(f->skb)) > DEFAULTBCNT / 512 | ||
503 | && ifp && ++ifp->lostjumbo > (t->nframes << 1) | ||
504 | && ifp->maxbcnt != DEFAULTBCNT) { | ||
505 | printk(KERN_INFO | ||
506 | "aoe: e%ld.%d: " | ||
507 | "too many lost jumbo on " | ||
508 | "%s:%012llx - " | ||
509 | "falling back to %d frames.\n", | ||
510 | d->aoemajor, d->aoeminor, | ||
511 | ifp->nd->name, mac_addr(t->addr), | ||
512 | DEFAULTBCNT); | ||
513 | ifp->maxbcnt = 0; | ||
514 | } | ||
515 | resend(d, t, f); | ||
516 | } | ||
517 | |||
518 | /* window check */ | ||
519 | if (t->nout == t->maxout | ||
520 | && t->maxout < t->nframes | ||
521 | && (jiffies - t->lastwadj)/HZ > 10) { | ||
522 | t->maxout++; | ||
523 | t->lastwadj = jiffies; | ||
388 | } | 524 | } |
389 | } | 525 | } |
390 | if (d->flags & DEVFL_KICKME) { | 526 | |
527 | if (d->sendq_hd) { | ||
528 | n = d->rttavg <<= 1; | ||
529 | if (n > MAXTIMER) | ||
530 | d->rttavg = MAXTIMER; | ||
531 | } | ||
532 | |||
533 | if (d->flags & DEVFL_KICKME || d->htgt) { | ||
391 | d->flags &= ~DEVFL_KICKME; | 534 | d->flags &= ~DEVFL_KICKME; |
392 | aoecmd_work(d); | 535 | aoecmd_work(d); |
393 | } | 536 | } |
394 | 537 | ||
395 | sl = d->sendq_hd; | 538 | sl = d->sendq_hd; |
396 | d->sendq_hd = d->sendq_tl = NULL; | 539 | 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 | 540 | ||
403 | d->timer.expires = jiffies + TIMERTICK; | 541 | d->timer.expires = jiffies + TIMERTICK; |
404 | add_timer(&d->timer); | 542 | add_timer(&d->timer); |
@@ -408,6 +546,25 @@ rexmit_timer(ulong vp) | |||
408 | aoenet_xmit(sl); | 546 | aoenet_xmit(sl); |
409 | } | 547 | } |
410 | 548 | ||
549 | /* enters with d->lock held */ | ||
550 | void | ||
551 | aoecmd_work(struct aoedev *d) | ||
552 | { | ||
553 | struct buf *buf; | ||
554 | loop: | ||
555 | if (d->htgt && !sthtith(d)) | ||
556 | return; | ||
557 | if (d->inprocess == NULL) { | ||
558 | if (list_empty(&d->bufq)) | ||
559 | return; | ||
560 | buf = container_of(d->bufq.next, struct buf, bufs); | ||
561 | list_del(d->bufq.next); | ||
562 | d->inprocess = buf; | ||
563 | } | ||
564 | if (aoecmd_ata_rw(d)) | ||
565 | goto loop; | ||
566 | } | ||
567 | |||
411 | /* this function performs work that has been deferred until sleeping is OK | 568 | /* this function performs work that has been deferred until sleeping is OK |
412 | */ | 569 | */ |
413 | void | 570 | void |
@@ -440,7 +597,7 @@ aoecmd_sleepwork(struct work_struct *work) | |||
440 | } | 597 | } |
441 | 598 | ||
442 | static void | 599 | static void |
443 | ataid_complete(struct aoedev *d, unsigned char *id) | 600 | ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) |
444 | { | 601 | { |
445 | u64 ssize; | 602 | u64 ssize; |
446 | u16 n; | 603 | u16 n; |
@@ -476,7 +633,7 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
476 | 633 | ||
477 | if (d->ssize != ssize) | 634 | if (d->ssize != ssize) |
478 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", | 635 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", |
479 | (unsigned long long)mac_addr(d->addr), | 636 | (unsigned long long)mac_addr(t->addr), |
480 | d->aoemajor, d->aoeminor, | 637 | d->aoemajor, d->aoeminor, |
481 | d->fw_ver, (long long)ssize); | 638 | d->fw_ver, (long long)ssize); |
482 | d->ssize = ssize; | 639 | d->ssize = ssize; |
@@ -484,15 +641,8 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
484 | if (d->gd != NULL) { | 641 | if (d->gd != NULL) { |
485 | d->gd->capacity = ssize; | 642 | d->gd->capacity = ssize; |
486 | d->flags |= DEVFL_NEWSIZE; | 643 | d->flags |= DEVFL_NEWSIZE; |
487 | } else { | 644 | } 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; | 645 | d->flags |= DEVFL_GDALLOC; |
495 | } | ||
496 | schedule_work(&d->work); | 646 | schedule_work(&d->work); |
497 | } | 647 | } |
498 | 648 | ||
@@ -519,6 +669,31 @@ calc_rttavg(struct aoedev *d, int rtt) | |||
519 | d->rttavg += n >> 2; | 669 | d->rttavg += n >> 2; |
520 | } | 670 | } |
521 | 671 | ||
672 | static struct aoetgt * | ||
673 | gettgt(struct aoedev *d, char *addr) | ||
674 | { | ||
675 | struct aoetgt **t, **e; | ||
676 | |||
677 | t = d->targets; | ||
678 | e = t + NTARGETS; | ||
679 | for (; t < e && *t; t++) | ||
680 | if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) | ||
681 | return *t; | ||
682 | return NULL; | ||
683 | } | ||
684 | |||
685 | static inline void | ||
686 | diskstats(struct gendisk *disk, struct bio *bio, ulong duration) | ||
687 | { | ||
688 | unsigned long n_sect = bio->bi_size >> 9; | ||
689 | const int rw = bio_data_dir(bio); | ||
690 | |||
691 | disk_stat_inc(disk, ios[rw]); | ||
692 | disk_stat_add(disk, ticks[rw], duration); | ||
693 | disk_stat_add(disk, sectors[rw], n_sect); | ||
694 | disk_stat_add(disk, io_ticks, duration); | ||
695 | } | ||
696 | |||
522 | void | 697 | void |
523 | aoecmd_ata_rsp(struct sk_buff *skb) | 698 | aoecmd_ata_rsp(struct sk_buff *skb) |
524 | { | 699 | { |
@@ -528,6 +703,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
528 | struct frame *f; | 703 | struct frame *f; |
529 | struct buf *buf; | 704 | struct buf *buf; |
530 | struct sk_buff *sl; | 705 | struct sk_buff *sl; |
706 | struct aoetgt *t; | ||
707 | struct aoeif *ifp; | ||
531 | register long n; | 708 | register long n; |
532 | ulong flags; | 709 | ulong flags; |
533 | char ebuf[128]; | 710 | char ebuf[128]; |
@@ -547,7 +724,15 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
547 | spin_lock_irqsave(&d->lock, flags); | 724 | spin_lock_irqsave(&d->lock, flags); |
548 | 725 | ||
549 | n = be32_to_cpu(get_unaligned(&hin->tag)); | 726 | n = be32_to_cpu(get_unaligned(&hin->tag)); |
550 | f = getframe(d, n); | 727 | t = gettgt(d, hin->src); |
728 | if (t == NULL) { | ||
729 | printk(KERN_INFO "aoe: can't find target e%ld.%d:%012llx\n", | ||
730 | d->aoemajor, d->aoeminor, | ||
731 | (unsigned long long) mac_addr(hin->src)); | ||
732 | spin_unlock_irqrestore(&d->lock, flags); | ||
733 | return; | ||
734 | } | ||
735 | f = getframe(t, n); | ||
551 | if (f == NULL) { | 736 | if (f == NULL) { |
552 | calc_rttavg(d, -tsince(n)); | 737 | calc_rttavg(d, -tsince(n)); |
553 | spin_unlock_irqrestore(&d->lock, flags); | 738 | spin_unlock_irqrestore(&d->lock, flags); |
@@ -569,8 +754,6 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
569 | ahout = (struct aoe_atahdr *) (hout+1); | 754 | ahout = (struct aoe_atahdr *) (hout+1); |
570 | buf = f->buf; | 755 | buf = f->buf; |
571 | 756 | ||
572 | if (ahout->cmdstat == WIN_IDENTIFY) | ||
573 | d->flags &= ~DEVFL_PAUSE; | ||
574 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | 757 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ |
575 | printk(KERN_ERR | 758 | printk(KERN_ERR |
576 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", | 759 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", |
@@ -579,14 +762,16 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
579 | if (buf) | 762 | if (buf) |
580 | buf->flags |= BUFFL_FAIL; | 763 | buf->flags |= BUFFL_FAIL; |
581 | } else { | 764 | } else { |
765 | if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */ | ||
766 | d->htgt = NULL; | ||
582 | n = ahout->scnt << 9; | 767 | n = ahout->scnt << 9; |
583 | switch (ahout->cmdstat) { | 768 | switch (ahout->cmdstat) { |
584 | case WIN_READ: | 769 | case WIN_READ: |
585 | case WIN_READ_EXT: | 770 | case WIN_READ_EXT: |
586 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | 771 | if (skb->len - sizeof *hin - sizeof *ahin < n) { |
587 | printk(KERN_ERR | 772 | printk(KERN_ERR |
588 | "aoe: runt data size in read. skb->len=%d\n", | 773 | "aoe: %s. skb->len=%d need=%ld\n", |
589 | skb->len); | 774 | "runt data size in read", skb->len, n); |
590 | /* fail frame f? just returning will rexmit. */ | 775 | /* fail frame f? just returning will rexmit. */ |
591 | spin_unlock_irqrestore(&d->lock, flags); | 776 | spin_unlock_irqrestore(&d->lock, flags); |
592 | return; | 777 | return; |
@@ -594,32 +779,18 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
594 | memcpy(f->bufaddr, ahin+1, n); | 779 | memcpy(f->bufaddr, ahin+1, n); |
595 | case WIN_WRITE: | 780 | case WIN_WRITE: |
596 | case WIN_WRITE_EXT: | 781 | case WIN_WRITE_EXT: |
782 | ifp = getif(t, skb->dev); | ||
783 | if (ifp) { | ||
784 | ifp->lost = 0; | ||
785 | if (n > DEFAULTBCNT) | ||
786 | ifp->lostjumbo = 0; | ||
787 | } | ||
597 | if (f->bcnt -= n) { | 788 | if (f->bcnt -= n) { |
598 | skb = f->skb; | 789 | f->lba += n >> 9; |
599 | f->bufaddr += n; | 790 | f->bufaddr += n; |
600 | put_lba(ahout, f->lba += ahout->scnt); | 791 | resend(d, t, f); |
601 | n = f->bcnt; | 792 | 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 | } | 793 | } |
621 | if (n > DEFAULTBCNT) | ||
622 | d->lostjumbo = 0; | ||
623 | break; | 794 | break; |
624 | case WIN_IDENTIFY: | 795 | case WIN_IDENTIFY: |
625 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | 796 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { |
@@ -629,7 +800,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
629 | spin_unlock_irqrestore(&d->lock, flags); | 800 | spin_unlock_irqrestore(&d->lock, flags); |
630 | return; | 801 | return; |
631 | } | 802 | } |
632 | ataid_complete(d, (char *) (ahin+1)); | 803 | ataid_complete(d, t, (char *) (ahin+1)); |
633 | break; | 804 | break; |
634 | default: | 805 | default: |
635 | printk(KERN_INFO | 806 | printk(KERN_INFO |
@@ -640,28 +811,19 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
640 | } | 811 | } |
641 | } | 812 | } |
642 | 813 | ||
643 | if (buf) { | 814 | if (buf && --buf->nframesout == 0 && buf->resid == 0) { |
644 | buf->nframesout -= 1; | 815 | diskstats(d->gd, buf->bio, jiffies - buf->stime); |
645 | if (buf->nframesout == 0 && buf->resid == 0) { | 816 | n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; |
646 | unsigned long duration = jiffies - buf->start_time; | 817 | bio_endio(buf->bio, n); |
647 | unsigned long n_sect = buf->bio->bi_size >> 9; | 818 | 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 | } | 819 | } |
660 | 820 | ||
661 | f->buf = NULL; | 821 | f->buf = NULL; |
662 | f->tag = FREETAG; | 822 | f->tag = FREETAG; |
823 | t->nout--; | ||
663 | 824 | ||
664 | aoecmd_work(d); | 825 | aoecmd_work(d); |
826 | xmit: | ||
665 | sl = d->sendq_hd; | 827 | sl = d->sendq_hd; |
666 | d->sendq_hd = d->sendq_tl = NULL; | 828 | d->sendq_hd = d->sendq_tl = NULL; |
667 | 829 | ||
@@ -679,23 +841,20 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) | |||
679 | aoenet_xmit(sl); | 841 | aoenet_xmit(sl); |
680 | } | 842 | } |
681 | 843 | ||
682 | /* | 844 | 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) | 845 | aoecmd_ata_id(struct aoedev *d) |
688 | { | 846 | { |
689 | struct aoe_hdr *h; | 847 | struct aoe_hdr *h; |
690 | struct aoe_atahdr *ah; | 848 | struct aoe_atahdr *ah; |
691 | struct frame *f; | 849 | struct frame *f; |
692 | struct sk_buff *skb; | 850 | struct sk_buff *skb; |
851 | struct aoetgt *t; | ||
693 | 852 | ||
694 | f = freeframe(d); | 853 | f = freeframe(d); |
695 | if (f == NULL) { | 854 | if (f == NULL) |
696 | printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); | ||
697 | return NULL; | 855 | return NULL; |
698 | } | 856 | |
857 | t = *d->tgt; | ||
699 | 858 | ||
700 | /* initialize the headers & frame */ | 859 | /* initialize the headers & frame */ |
701 | skb = f->skb; | 860 | skb = f->skb; |
@@ -703,7 +862,8 @@ aoecmd_ata_id(struct aoedev *d) | |||
703 | ah = (struct aoe_atahdr *) (h+1); | 862 | ah = (struct aoe_atahdr *) (h+1); |
704 | skb_put(skb, sizeof *h + sizeof *ah); | 863 | skb_put(skb, sizeof *h + sizeof *ah); |
705 | memset(h, 0, skb->len); | 864 | memset(h, 0, skb->len); |
706 | f->tag = aoehdr_atainit(d, h); | 865 | f->tag = aoehdr_atainit(d, t, h); |
866 | t->nout++; | ||
707 | f->waited = 0; | 867 | f->waited = 0; |
708 | 868 | ||
709 | /* set up ata header */ | 869 | /* set up ata header */ |
@@ -711,7 +871,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
711 | ah->cmdstat = WIN_IDENTIFY; | 871 | ah->cmdstat = WIN_IDENTIFY; |
712 | ah->lba3 = 0xa0; | 872 | ah->lba3 = 0xa0; |
713 | 873 | ||
714 | skb->dev = d->ifp; | 874 | skb->dev = t->ifp->nd; |
715 | 875 | ||
716 | d->rttavg = MAXTIMER; | 876 | d->rttavg = MAXTIMER; |
717 | d->timer.function = rexmit_timer; | 877 | d->timer.function = rexmit_timer; |
@@ -719,12 +879,58 @@ aoecmd_ata_id(struct aoedev *d) | |||
719 | return skb_clone(skb, GFP_ATOMIC); | 879 | return skb_clone(skb, GFP_ATOMIC); |
720 | } | 880 | } |
721 | 881 | ||
882 | static struct aoetgt * | ||
883 | addtgt(struct aoedev *d, char *addr, ulong nframes) | ||
884 | { | ||
885 | struct aoetgt *t, **tt, **te; | ||
886 | struct frame *f, *e; | ||
887 | |||
888 | tt = d->targets; | ||
889 | te = tt + NTARGETS; | ||
890 | for (; tt < te && *tt; tt++) | ||
891 | ; | ||
892 | |||
893 | if (tt == te) | ||
894 | return NULL; | ||
895 | |||
896 | t = kcalloc(1, sizeof *t, GFP_ATOMIC); | ||
897 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | ||
898 | if (!t || !f) | ||
899 | goto bail; | ||
900 | t->nframes = nframes; | ||
901 | t->frames = f; | ||
902 | e = f + nframes; | ||
903 | for (; f < e; f++) { | ||
904 | f->tag = FREETAG; | ||
905 | f->skb = new_skb(ETH_ZLEN); | ||
906 | if (!f->skb) | ||
907 | break; | ||
908 | } | ||
909 | if (f != e) { | ||
910 | while (f > t->frames) { | ||
911 | f--; | ||
912 | dev_kfree_skb(f->skb); | ||
913 | } | ||
914 | goto bail; | ||
915 | } | ||
916 | memcpy(t->addr, addr, sizeof t->addr); | ||
917 | t->ifp = t->ifs; | ||
918 | t->maxout = t->nframes; | ||
919 | return *tt = t; | ||
920 | bail: | ||
921 | kfree(t); | ||
922 | kfree(f); | ||
923 | return NULL; | ||
924 | } | ||
925 | |||
722 | void | 926 | void |
723 | aoecmd_cfg_rsp(struct sk_buff *skb) | 927 | aoecmd_cfg_rsp(struct sk_buff *skb) |
724 | { | 928 | { |
725 | struct aoedev *d; | 929 | struct aoedev *d; |
726 | struct aoe_hdr *h; | 930 | struct aoe_hdr *h; |
727 | struct aoe_cfghdr *ch; | 931 | struct aoe_cfghdr *ch; |
932 | struct aoetgt *t; | ||
933 | struct aoeif *ifp; | ||
728 | ulong flags, sysminor, aoemajor; | 934 | ulong flags, sysminor, aoemajor; |
729 | struct sk_buff *sl; | 935 | struct sk_buff *sl; |
730 | enum { MAXFRAMES = 16 }; | 936 | enum { MAXFRAMES = 16 }; |
@@ -755,7 +961,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
755 | if (n > MAXFRAMES) /* keep it reasonable */ | 961 | if (n > MAXFRAMES) /* keep it reasonable */ |
756 | n = MAXFRAMES; | 962 | n = MAXFRAMES; |
757 | 963 | ||
758 | d = aoedev_by_sysminor_m(sysminor, n); | 964 | d = aoedev_by_sysminor_m(sysminor); |
759 | if (d == NULL) { | 965 | if (d == NULL) { |
760 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); | 966 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); |
761 | return; | 967 | return; |
@@ -763,38 +969,77 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
763 | 969 | ||
764 | spin_lock_irqsave(&d->lock, flags); | 970 | spin_lock_irqsave(&d->lock, flags); |
765 | 971 | ||
766 | /* permit device to migrate mac and network interface */ | 972 | t = gettgt(d, h->src); |
767 | d->ifp = skb->dev; | 973 | if (!t) { |
768 | memcpy(d->addr, h->src, sizeof d->addr); | 974 | t = addtgt(d, h->src, n); |
769 | if (!(d->flags & DEVFL_MAXBCNT)) { | 975 | if (!t) { |
770 | n = d->ifp->mtu; | 976 | printk(KERN_INFO |
977 | "aoe: device addtgt failure; " | ||
978 | "too many targets?\n"); | ||
979 | spin_unlock_irqrestore(&d->lock, flags); | ||
980 | return; | ||
981 | } | ||
982 | } | ||
983 | ifp = getif(t, skb->dev); | ||
984 | if (!ifp) { | ||
985 | ifp = addif(t, skb->dev); | ||
986 | if (!ifp) { | ||
987 | printk(KERN_INFO | ||
988 | "aoe: device addif failure; " | ||
989 | "too many interfaces?\n"); | ||
990 | spin_unlock_irqrestore(&d->lock, flags); | ||
991 | return; | ||
992 | } | ||
993 | } | ||
994 | if (ifp->maxbcnt) { | ||
995 | n = ifp->nd->mtu; | ||
771 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | 996 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); |
772 | n /= 512; | 997 | n /= 512; |
773 | if (n > ch->scnt) | 998 | if (n > ch->scnt) |
774 | n = ch->scnt; | 999 | n = ch->scnt; |
775 | n = n ? n * 512 : DEFAULTBCNT; | 1000 | n = n ? n * 512 : DEFAULTBCNT; |
776 | if (n != d->maxbcnt) { | 1001 | if (n != ifp->maxbcnt) { |
777 | printk(KERN_INFO | 1002 | printk(KERN_INFO |
778 | "aoe: e%ld.%ld: setting %d byte data frames on %s\n", | 1003 | "aoe: e%ld.%d: setting %d%s%s:%012llx\n", |
779 | d->aoemajor, d->aoeminor, n, d->ifp->name); | 1004 | d->aoemajor, d->aoeminor, n, |
780 | d->maxbcnt = n; | 1005 | " byte data frames on ", ifp->nd->name, |
1006 | (unsigned long long) mac_addr(t->addr)); | ||
1007 | ifp->maxbcnt = n; | ||
781 | } | 1008 | } |
782 | } | 1009 | } |
783 | 1010 | ||
784 | /* don't change users' perspective */ | 1011 | /* don't change users' perspective */ |
785 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { | 1012 | if (d->nopen) { |
786 | spin_unlock_irqrestore(&d->lock, flags); | 1013 | spin_unlock_irqrestore(&d->lock, flags); |
787 | return; | 1014 | return; |
788 | } | 1015 | } |
789 | d->flags |= DEVFL_PAUSE; /* force pause */ | ||
790 | d->mintimer = MINTIMER; | ||
791 | d->fw_ver = be16_to_cpu(ch->fwver); | 1016 | d->fw_ver = be16_to_cpu(ch->fwver); |
792 | 1017 | ||
793 | /* check for already outstanding ataid */ | 1018 | sl = aoecmd_ata_id(d); |
794 | sl = aoedev_isbusy(d) == 0 ? aoecmd_ata_id(d) : NULL; | ||
795 | 1019 | ||
796 | spin_unlock_irqrestore(&d->lock, flags); | 1020 | spin_unlock_irqrestore(&d->lock, flags); |
797 | 1021 | ||
798 | aoenet_xmit(sl); | 1022 | aoenet_xmit(sl); |
799 | } | 1023 | } |
800 | 1024 | ||
1025 | void | ||
1026 | aoecmd_cleanslate(struct aoedev *d) | ||
1027 | { | ||
1028 | struct aoetgt **t, **te; | ||
1029 | struct aoeif *p, *e; | ||
1030 | |||
1031 | d->mintimer = MINTIMER; | ||
1032 | |||
1033 | t = d->targets; | ||
1034 | te = t + NTARGETS; | ||
1035 | for (; t < te && *t; t++) { | ||
1036 | (*t)->maxout = (*t)->nframes; | ||
1037 | p = (*t)->ifs; | ||
1038 | e = p + NAOEIFS; | ||
1039 | for (; p < e; p++) { | ||
1040 | p->lostjumbo = 0; | ||
1041 | p->lost = 0; | ||
1042 | p->maxbcnt = DEFAULTBCNT; | ||
1043 | } | ||
1044 | } | ||
1045 | } | ||