diff options
Diffstat (limited to 'drivers/block/aoe/aoecmd.c')
| -rw-r--r-- | drivers/block/aoe/aoecmd.c | 303 |
1 files changed, 196 insertions, 107 deletions
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 39da28d344fe..8a13b1af8bab 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
| 2 | /* | 2 | /* |
| 3 | * aoecmd.c | 3 | * aoecmd.c |
| 4 | * Filesystem request handling methods | 4 | * Filesystem request handling methods |
| @@ -15,17 +15,19 @@ | |||
| 15 | #define TIMERTICK (HZ / 10) | 15 | #define TIMERTICK (HZ / 10) |
| 16 | #define MINTIMER (2 * TIMERTICK) | 16 | #define MINTIMER (2 * TIMERTICK) |
| 17 | #define MAXTIMER (HZ << 1) | 17 | #define MAXTIMER (HZ << 1) |
| 18 | #define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */ | ||
| 19 | 18 | ||
| 20 | static struct sk_buff * | 19 | static int aoe_deadsecs = 60 * 3; |
| 21 | new_skb(struct net_device *if_dev, ulong len) | 20 | module_param(aoe_deadsecs, int, 0644); |
| 21 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | ||
| 22 | |||
| 23 | struct sk_buff * | ||
| 24 | new_skb(ulong len) | ||
| 22 | { | 25 | { |
| 23 | struct sk_buff *skb; | 26 | struct sk_buff *skb; |
| 24 | 27 | ||
| 25 | skb = alloc_skb(len, GFP_ATOMIC); | 28 | skb = alloc_skb(len, GFP_ATOMIC); |
| 26 | if (skb) { | 29 | if (skb) { |
| 27 | skb->nh.raw = skb->mac.raw = skb->data; | 30 | skb->nh.raw = skb->mac.raw = skb->data; |
| 28 | skb->dev = if_dev; | ||
| 29 | skb->protocol = __constant_htons(ETH_P_AOE); | 31 | skb->protocol = __constant_htons(ETH_P_AOE); |
| 30 | skb->priority = 0; | 32 | skb->priority = 0; |
| 31 | skb_put(skb, len); | 33 | skb_put(skb, len); |
| @@ -40,29 +42,6 @@ new_skb(struct net_device *if_dev, ulong len) | |||
| 40 | return skb; | 42 | return skb; |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | static struct sk_buff * | ||
| 44 | skb_prepare(struct aoedev *d, struct frame *f) | ||
| 45 | { | ||
| 46 | struct sk_buff *skb; | ||
| 47 | char *p; | ||
| 48 | |||
| 49 | skb = new_skb(d->ifp, f->ndata + f->writedatalen); | ||
| 50 | if (!skb) { | ||
| 51 | printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n"); | ||
| 52 | return NULL; | ||
| 53 | } | ||
| 54 | |||
| 55 | p = skb->mac.raw; | ||
| 56 | memcpy(p, f->data, f->ndata); | ||
| 57 | |||
| 58 | if (f->writedatalen) { | ||
| 59 | p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr); | ||
| 60 | memcpy(p, f->bufaddr, f->writedatalen); | ||
| 61 | } | ||
| 62 | |||
| 63 | return skb; | ||
| 64 | } | ||
| 65 | |||
| 66 | static struct frame * | 45 | static struct frame * |
| 67 | getframe(struct aoedev *d, int tag) | 46 | getframe(struct aoedev *d, int tag) |
| 68 | { | 47 | { |
| @@ -107,6 +86,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) | |||
| 107 | return host_tag; | 86 | return host_tag; |
| 108 | } | 87 | } |
| 109 | 88 | ||
| 89 | static inline void | ||
| 90 | put_lba(struct aoe_atahdr *ah, sector_t lba) | ||
| 91 | { | ||
| 92 | ah->lba0 = lba; | ||
| 93 | ah->lba1 = lba >>= 8; | ||
| 94 | ah->lba2 = lba >>= 8; | ||
| 95 | ah->lba3 = lba >>= 8; | ||
| 96 | ah->lba4 = lba >>= 8; | ||
| 97 | ah->lba5 = lba >>= 8; | ||
| 98 | } | ||
| 99 | |||
| 110 | static void | 100 | static void |
| 111 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 101 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) |
| 112 | { | 102 | { |
| @@ -125,29 +115,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
| 125 | 115 | ||
| 126 | sector = buf->sector; | 116 | sector = buf->sector; |
| 127 | bcnt = buf->bv_resid; | 117 | bcnt = buf->bv_resid; |
| 128 | if (bcnt > MAXATADATA) | 118 | if (bcnt > d->maxbcnt) |
| 129 | bcnt = MAXATADATA; | 119 | bcnt = d->maxbcnt; |
| 130 | 120 | ||
| 131 | /* initialize the headers & frame */ | 121 | /* initialize the headers & frame */ |
| 132 | h = (struct aoe_hdr *) f->data; | 122 | skb = f->skb; |
| 123 | h = (struct aoe_hdr *) skb->mac.raw; | ||
| 133 | ah = (struct aoe_atahdr *) (h+1); | 124 | ah = (struct aoe_atahdr *) (h+1); |
| 134 | f->ndata = sizeof *h + sizeof *ah; | 125 | skb->len = sizeof *h + sizeof *ah; |
| 135 | memset(h, 0, f->ndata); | 126 | memset(h, 0, ETH_ZLEN); |
| 136 | f->tag = aoehdr_atainit(d, h); | 127 | f->tag = aoehdr_atainit(d, h); |
| 137 | f->waited = 0; | 128 | f->waited = 0; |
| 138 | f->buf = buf; | 129 | f->buf = buf; |
| 139 | f->bufaddr = buf->bufaddr; | 130 | f->bufaddr = buf->bufaddr; |
| 131 | f->bcnt = bcnt; | ||
| 132 | f->lba = sector; | ||
| 140 | 133 | ||
| 141 | /* set up ata header */ | 134 | /* set up ata header */ |
| 142 | ah->scnt = bcnt >> 9; | 135 | ah->scnt = bcnt >> 9; |
| 143 | ah->lba0 = sector; | 136 | put_lba(ah, sector); |
| 144 | ah->lba1 = sector >>= 8; | ||
| 145 | ah->lba2 = sector >>= 8; | ||
| 146 | ah->lba3 = sector >>= 8; | ||
| 147 | if (d->flags & DEVFL_EXT) { | 137 | if (d->flags & DEVFL_EXT) { |
| 148 | ah->aflags |= AOEAFL_EXT; | 138 | ah->aflags |= AOEAFL_EXT; |
| 149 | ah->lba4 = sector >>= 8; | ||
| 150 | ah->lba5 = sector >>= 8; | ||
| 151 | } else { | 139 | } else { |
| 152 | extbit = 0; | 140 | extbit = 0; |
| 153 | ah->lba3 &= 0x0f; | 141 | ah->lba3 &= 0x0f; |
| @@ -155,11 +143,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
| 155 | } | 143 | } |
| 156 | 144 | ||
| 157 | if (bio_data_dir(buf->bio) == WRITE) { | 145 | if (bio_data_dir(buf->bio) == WRITE) { |
| 146 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | ||
| 147 | offset_in_page(f->bufaddr), bcnt); | ||
| 158 | ah->aflags |= AOEAFL_WRITE; | 148 | ah->aflags |= AOEAFL_WRITE; |
| 159 | f->writedatalen = bcnt; | 149 | skb->len += bcnt; |
| 150 | skb->data_len = bcnt; | ||
| 160 | } else { | 151 | } else { |
| 152 | skb->len = ETH_ZLEN; | ||
| 161 | writebit = 0; | 153 | writebit = 0; |
| 162 | f->writedatalen = 0; | ||
| 163 | } | 154 | } |
| 164 | 155 | ||
| 165 | ah->cmdstat = WIN_READ | writebit | extbit; | 156 | ah->cmdstat = WIN_READ | writebit | extbit; |
| @@ -168,26 +159,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
| 168 | buf->nframesout += 1; | 159 | buf->nframesout += 1; |
| 169 | buf->bufaddr += bcnt; | 160 | buf->bufaddr += bcnt; |
| 170 | buf->bv_resid -= bcnt; | 161 | buf->bv_resid -= bcnt; |
| 171 | /* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */ | 162 | /* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ |
| 172 | buf->resid -= bcnt; | 163 | buf->resid -= bcnt; |
| 173 | buf->sector += bcnt >> 9; | 164 | buf->sector += bcnt >> 9; |
| 174 | if (buf->resid == 0) { | 165 | if (buf->resid == 0) { |
| 175 | d->inprocess = NULL; | 166 | d->inprocess = NULL; |
| 176 | } else if (buf->bv_resid == 0) { | 167 | } else if (buf->bv_resid == 0) { |
| 177 | buf->bv++; | 168 | buf->bv++; |
| 169 | WARN_ON(buf->bv->bv_len == 0); | ||
| 178 | buf->bv_resid = buf->bv->bv_len; | 170 | buf->bv_resid = buf->bv->bv_len; |
| 179 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 171 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; |
| 180 | } | 172 | } |
| 181 | 173 | ||
| 182 | skb = skb_prepare(d, f); | 174 | skb->dev = d->ifp; |
| 183 | if (skb) { | 175 | skb = skb_clone(skb, GFP_ATOMIC); |
| 184 | skb->next = NULL; | 176 | if (skb == NULL) |
| 185 | if (d->sendq_hd) | 177 | return; |
| 186 | d->sendq_tl->next = skb; | 178 | if (d->sendq_hd) |
| 187 | else | 179 | d->sendq_tl->next = skb; |
| 188 | d->sendq_hd = skb; | 180 | else |
| 189 | d->sendq_tl = skb; | 181 | d->sendq_hd = skb; |
| 190 | } | 182 | d->sendq_tl = skb; |
| 191 | } | 183 | } |
| 192 | 184 | ||
| 193 | /* some callers cannot sleep, and they can call this function, | 185 | /* some callers cannot sleep, and they can call this function, |
| @@ -209,11 +201,12 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) | |||
| 209 | if (!is_aoe_netif(ifp)) | 201 | if (!is_aoe_netif(ifp)) |
| 210 | continue; | 202 | continue; |
| 211 | 203 | ||
| 212 | skb = new_skb(ifp, sizeof *h + sizeof *ch); | 204 | skb = new_skb(sizeof *h + sizeof *ch); |
| 213 | if (skb == NULL) { | 205 | if (skb == NULL) { |
| 214 | printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); | 206 | printk(KERN_INFO "aoe: skb alloc failure\n"); |
| 215 | continue; | 207 | continue; |
| 216 | } | 208 | } |
| 209 | skb->dev = ifp; | ||
| 217 | if (sl_tail == NULL) | 210 | if (sl_tail == NULL) |
| 218 | sl_tail = skb; | 211 | sl_tail = skb; |
| 219 | h = (struct aoe_hdr *) skb->mac.raw; | 212 | h = (struct aoe_hdr *) skb->mac.raw; |
| @@ -237,6 +230,29 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) | |||
| 237 | return sl; | 230 | return sl; |
| 238 | } | 231 | } |
| 239 | 232 | ||
| 233 | static struct frame * | ||
| 234 | freeframe(struct aoedev *d) | ||
| 235 | { | ||
| 236 | struct frame *f, *e; | ||
| 237 | int n = 0; | ||
| 238 | |||
| 239 | f = d->frames; | ||
| 240 | e = f + d->nframes; | ||
| 241 | for (; f<e; f++) { | ||
| 242 | if (f->tag != FREETAG) | ||
| 243 | continue; | ||
| 244 | if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) { | ||
| 245 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
| 246 | return f; | ||
| 247 | } | ||
| 248 | n++; | ||
| 249 | } | ||
| 250 | if (n == d->nframes) /* wait for network layer */ | ||
| 251 | d->flags |= DEVFL_KICKME; | ||
| 252 | |||
| 253 | return NULL; | ||
| 254 | } | ||
| 255 | |||
| 240 | /* enters with d->lock held */ | 256 | /* enters with d->lock held */ |
| 241 | void | 257 | void |
| 242 | aoecmd_work(struct aoedev *d) | 258 | aoecmd_work(struct aoedev *d) |
| @@ -252,7 +268,7 @@ aoecmd_work(struct aoedev *d) | |||
| 252 | } | 268 | } |
| 253 | 269 | ||
| 254 | loop: | 270 | loop: |
| 255 | f = getframe(d, FREETAG); | 271 | f = freeframe(d); |
| 256 | if (f == NULL) | 272 | if (f == NULL) |
| 257 | return; | 273 | return; |
| 258 | if (d->inprocess == NULL) { | 274 | if (d->inprocess == NULL) { |
| @@ -260,7 +276,7 @@ loop: | |||
| 260 | return; | 276 | return; |
| 261 | buf = container_of(d->bufq.next, struct buf, bufs); | 277 | buf = container_of(d->bufq.next, struct buf, bufs); |
| 262 | list_del(d->bufq.next); | 278 | list_del(d->bufq.next); |
| 263 | /*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */ | 279 | /*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */ |
| 264 | d->inprocess = buf; | 280 | d->inprocess = buf; |
| 265 | } | 281 | } |
| 266 | aoecmd_ata_rw(d, f); | 282 | aoecmd_ata_rw(d, f); |
| @@ -272,6 +288,7 @@ rexmit(struct aoedev *d, struct frame *f) | |||
| 272 | { | 288 | { |
| 273 | struct sk_buff *skb; | 289 | struct sk_buff *skb; |
| 274 | struct aoe_hdr *h; | 290 | struct aoe_hdr *h; |
| 291 | struct aoe_atahdr *ah; | ||
| 275 | char buf[128]; | 292 | char buf[128]; |
| 276 | u32 n; | 293 | u32 n; |
| 277 | 294 | ||
| @@ -283,21 +300,41 @@ rexmit(struct aoedev *d, struct frame *f) | |||
| 283 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); | 300 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); |
| 284 | aoechr_error(buf); | 301 | aoechr_error(buf); |
| 285 | 302 | ||
| 286 | h = (struct aoe_hdr *) f->data; | 303 | skb = f->skb; |
| 304 | h = (struct aoe_hdr *) skb->mac.raw; | ||
| 305 | ah = (struct aoe_atahdr *) (h+1); | ||
| 287 | f->tag = n; | 306 | f->tag = n; |
| 288 | h->tag = cpu_to_be32(n); | 307 | h->tag = cpu_to_be32(n); |
| 289 | memcpy(h->dst, d->addr, sizeof h->dst); | 308 | memcpy(h->dst, d->addr, sizeof h->dst); |
| 290 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 309 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); |
| 291 | 310 | ||
| 292 | skb = skb_prepare(d, f); | 311 | n = DEFAULTBCNT / 512; |
| 293 | if (skb) { | 312 | if (ah->scnt > n) { |
| 294 | skb->next = NULL; | 313 | ah->scnt = n; |
| 295 | if (d->sendq_hd) | 314 | if (ah->aflags & AOEAFL_WRITE) { |
| 296 | d->sendq_tl->next = skb; | 315 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), |
| 297 | else | 316 | offset_in_page(f->bufaddr), DEFAULTBCNT); |
| 298 | d->sendq_hd = skb; | 317 | skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; |
| 299 | d->sendq_tl = skb; | 318 | skb->data_len = DEFAULTBCNT; |
| 319 | } | ||
| 320 | if (++d->lostjumbo > (d->nframes << 1)) | ||
| 321 | if (d->maxbcnt != DEFAULTBCNT) { | ||
| 322 | printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", | ||
| 323 | d->aoemajor, d->aoeminor, d->ifp->name); | ||
| 324 | d->maxbcnt = DEFAULTBCNT; | ||
| 325 | d->flags |= DEVFL_MAXBCNT; | ||
| 326 | } | ||
| 300 | } | 327 | } |
| 328 | |||
| 329 | skb->dev = d->ifp; | ||
| 330 | skb = skb_clone(skb, GFP_ATOMIC); | ||
| 331 | if (skb == NULL) | ||
| 332 | return; | ||
| 333 | if (d->sendq_hd) | ||
| 334 | d->sendq_tl->next = skb; | ||
| 335 | else | ||
| 336 | d->sendq_hd = skb; | ||
| 337 | d->sendq_tl = skb; | ||
| 301 | } | 338 | } |
| 302 | 339 | ||
| 303 | static int | 340 | static int |
| @@ -340,13 +377,17 @@ rexmit_timer(ulong vp) | |||
| 340 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { | 377 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { |
| 341 | n = f->waited += timeout; | 378 | n = f->waited += timeout; |
| 342 | n /= HZ; | 379 | n /= HZ; |
| 343 | if (n > MAXWAIT) { /* waited too long. device failure. */ | 380 | if (n > aoe_deadsecs) { /* waited too long for response */ |
| 344 | aoedev_downdev(d); | 381 | aoedev_downdev(d); |
| 345 | break; | 382 | break; |
| 346 | } | 383 | } |
| 347 | rexmit(d, f); | 384 | rexmit(d, f); |
| 348 | } | 385 | } |
| 349 | } | 386 | } |
| 387 | if (d->flags & DEVFL_KICKME) { | ||
| 388 | d->flags &= ~DEVFL_KICKME; | ||
| 389 | aoecmd_work(d); | ||
| 390 | } | ||
| 350 | 391 | ||
| 351 | sl = d->sendq_hd; | 392 | sl = d->sendq_hd; |
| 352 | d->sendq_hd = d->sendq_tl = NULL; | 393 | d->sendq_hd = d->sendq_tl = NULL; |
| @@ -431,8 +472,8 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
| 431 | } | 472 | } |
| 432 | 473 | ||
| 433 | if (d->ssize != ssize) | 474 | if (d->ssize != ssize) |
| 434 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu " | 475 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", |
| 435 | "sectors\n", (unsigned long long)mac_addr(d->addr), | 476 | (unsigned long long)mac_addr(d->addr), |
| 436 | d->aoemajor, d->aoeminor, | 477 | d->aoemajor, d->aoeminor, |
| 437 | d->fw_ver, (long long)ssize); | 478 | d->fw_ver, (long long)ssize); |
| 438 | d->ssize = ssize; | 479 | d->ssize = ssize; |
| @@ -442,11 +483,9 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
| 442 | d->flags |= DEVFL_NEWSIZE; | 483 | d->flags |= DEVFL_NEWSIZE; |
| 443 | } else { | 484 | } else { |
| 444 | if (d->flags & DEVFL_GDALLOC) { | 485 | if (d->flags & DEVFL_GDALLOC) { |
| 445 | printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n", | 486 | printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n", |
| 446 | __FUNCTION__, | ||
| 447 | "can't schedule work for", | ||
| 448 | d->aoemajor, d->aoeminor, | 487 | d->aoemajor, d->aoeminor, |
| 449 | "it's already on! (This really shouldn't happen).\n"); | 488 | "it's already on! This shouldn't happen.\n"); |
| 450 | return; | 489 | return; |
| 451 | } | 490 | } |
| 452 | d->flags |= DEVFL_GDALLOC; | 491 | d->flags |= DEVFL_GDALLOC; |
| @@ -460,8 +499,15 @@ calc_rttavg(struct aoedev *d, int rtt) | |||
| 460 | register long n; | 499 | register long n; |
| 461 | 500 | ||
| 462 | n = rtt; | 501 | n = rtt; |
| 463 | if (n < MINTIMER) | 502 | if (n < 0) { |
| 464 | n = MINTIMER; | 503 | n = -rtt; |
| 504 | if (n < MINTIMER) | ||
| 505 | n = MINTIMER; | ||
| 506 | else if (n > MAXTIMER) | ||
| 507 | n = MAXTIMER; | ||
| 508 | d->mintimer += (n - d->mintimer) >> 1; | ||
| 509 | } else if (n < d->mintimer) | ||
| 510 | n = d->mintimer; | ||
| 465 | else if (n > MAXTIMER) | 511 | else if (n > MAXTIMER) |
| 466 | n = MAXTIMER; | 512 | n = MAXTIMER; |
| 467 | 513 | ||
| @@ -474,7 +520,7 @@ void | |||
| 474 | aoecmd_ata_rsp(struct sk_buff *skb) | 520 | aoecmd_ata_rsp(struct sk_buff *skb) |
| 475 | { | 521 | { |
| 476 | struct aoedev *d; | 522 | struct aoedev *d; |
| 477 | struct aoe_hdr *hin; | 523 | struct aoe_hdr *hin, *hout; |
| 478 | struct aoe_atahdr *ahin, *ahout; | 524 | struct aoe_atahdr *ahin, *ahout; |
| 479 | struct frame *f; | 525 | struct frame *f; |
| 480 | struct buf *buf; | 526 | struct buf *buf; |
| @@ -497,8 +543,10 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
| 497 | 543 | ||
| 498 | spin_lock_irqsave(&d->lock, flags); | 544 | spin_lock_irqsave(&d->lock, flags); |
| 499 | 545 | ||
| 500 | f = getframe(d, be32_to_cpu(hin->tag)); | 546 | n = be32_to_cpu(hin->tag); |
| 547 | f = getframe(d, n); | ||
| 501 | if (f == NULL) { | 548 | if (f == NULL) { |
| 549 | calc_rttavg(d, -tsince(n)); | ||
| 502 | spin_unlock_irqrestore(&d->lock, flags); | 550 | spin_unlock_irqrestore(&d->lock, flags); |
| 503 | snprintf(ebuf, sizeof ebuf, | 551 | snprintf(ebuf, sizeof ebuf, |
| 504 | "%15s e%d.%d tag=%08x@%08lx\n", | 552 | "%15s e%d.%d tag=%08x@%08lx\n", |
| @@ -514,26 +562,27 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
| 514 | calc_rttavg(d, tsince(f->tag)); | 562 | calc_rttavg(d, tsince(f->tag)); |
| 515 | 563 | ||
| 516 | ahin = (struct aoe_atahdr *) (hin+1); | 564 | ahin = (struct aoe_atahdr *) (hin+1); |
| 517 | ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr)); | 565 | hout = (struct aoe_hdr *) f->skb->mac.raw; |
| 566 | ahout = (struct aoe_atahdr *) (hout+1); | ||
| 518 | buf = f->buf; | 567 | buf = f->buf; |
| 519 | 568 | ||
| 520 | if (ahout->cmdstat == WIN_IDENTIFY) | 569 | if (ahout->cmdstat == WIN_IDENTIFY) |
| 521 | d->flags &= ~DEVFL_PAUSE; | 570 | d->flags &= ~DEVFL_PAUSE; |
| 522 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | 571 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ |
| 523 | printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh " | 572 | printk(KERN_ERR |
| 524 | "stat=%2.2Xh from e%ld.%ld\n", | 573 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", |
| 525 | ahout->cmdstat, ahin->cmdstat, | 574 | ahout->cmdstat, ahin->cmdstat, |
| 526 | d->aoemajor, d->aoeminor); | 575 | d->aoemajor, d->aoeminor); |
| 527 | if (buf) | 576 | if (buf) |
| 528 | buf->flags |= BUFFL_FAIL; | 577 | buf->flags |= BUFFL_FAIL; |
| 529 | } else { | 578 | } else { |
| 579 | n = ahout->scnt << 9; | ||
| 530 | switch (ahout->cmdstat) { | 580 | switch (ahout->cmdstat) { |
| 531 | case WIN_READ: | 581 | case WIN_READ: |
| 532 | case WIN_READ_EXT: | 582 | case WIN_READ_EXT: |
| 533 | n = ahout->scnt << 9; | ||
| 534 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | 583 | if (skb->len - sizeof *hin - sizeof *ahin < n) { |
| 535 | printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " | 584 | printk(KERN_ERR |
| 536 | "ata data size in read. skb->len=%d\n", | 585 | "aoe: runt data size in read. skb->len=%d\n", |
| 537 | skb->len); | 586 | skb->len); |
| 538 | /* fail frame f? just returning will rexmit. */ | 587 | /* fail frame f? just returning will rexmit. */ |
| 539 | spin_unlock_irqrestore(&d->lock, flags); | 588 | spin_unlock_irqrestore(&d->lock, flags); |
| @@ -542,22 +591,49 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
| 542 | memcpy(f->bufaddr, ahin+1, n); | 591 | memcpy(f->bufaddr, ahin+1, n); |
| 543 | case WIN_WRITE: | 592 | case WIN_WRITE: |
| 544 | case WIN_WRITE_EXT: | 593 | case WIN_WRITE_EXT: |
| 594 | if (f->bcnt -= n) { | ||
| 595 | skb = f->skb; | ||
| 596 | f->bufaddr += n; | ||
| 597 | put_lba(ahout, f->lba += ahout->scnt); | ||
| 598 | n = f->bcnt; | ||
| 599 | if (n > DEFAULTBCNT) | ||
| 600 | n = DEFAULTBCNT; | ||
| 601 | ahout->scnt = n >> 9; | ||
| 602 | if (ahout->aflags & AOEAFL_WRITE) { | ||
| 603 | skb_fill_page_desc(skb, 0, | ||
| 604 | virt_to_page(f->bufaddr), | ||
| 605 | offset_in_page(f->bufaddr), n); | ||
| 606 | skb->len = sizeof *hout + sizeof *ahout + n; | ||
| 607 | skb->data_len = n; | ||
| 608 | } | ||
| 609 | f->tag = newtag(d); | ||
| 610 | hout->tag = cpu_to_be32(f->tag); | ||
| 611 | skb->dev = d->ifp; | ||
| 612 | skb = skb_clone(skb, GFP_ATOMIC); | ||
| 613 | spin_unlock_irqrestore(&d->lock, flags); | ||
| 614 | if (skb) | ||
| 615 | aoenet_xmit(skb); | ||
| 616 | return; | ||
| 617 | } | ||
| 618 | if (n > DEFAULTBCNT) | ||
| 619 | d->lostjumbo = 0; | ||
| 545 | break; | 620 | break; |
| 546 | case WIN_IDENTIFY: | 621 | case WIN_IDENTIFY: |
| 547 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | 622 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { |
| 548 | printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size " | 623 | printk(KERN_INFO |
| 549 | "in ataid. skb->len=%d\n", skb->len); | 624 | "aoe: runt data size in ataid. skb->len=%d\n", |
| 625 | skb->len); | ||
| 550 | spin_unlock_irqrestore(&d->lock, flags); | 626 | spin_unlock_irqrestore(&d->lock, flags); |
| 551 | return; | 627 | return; |
| 552 | } | 628 | } |
| 553 | ataid_complete(d, (char *) (ahin+1)); | 629 | ataid_complete(d, (char *) (ahin+1)); |
| 554 | break; | 630 | break; |
| 555 | default: | 631 | default: |
| 556 | printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized " | 632 | printk(KERN_INFO |
| 557 | "outbound ata command %2.2Xh for %d.%d\n", | 633 | "aoe: unrecognized ata command %2.2Xh for %d.%d\n", |
| 558 | ahout->cmdstat, | 634 | ahout->cmdstat, |
| 559 | be16_to_cpu(hin->major), | 635 | be16_to_cpu(hin->major), |
| 560 | hin->minor); | 636 | hin->minor); |
| 561 | } | 637 | } |
| 562 | } | 638 | } |
| 563 | 639 | ||
| @@ -612,33 +688,32 @@ aoecmd_ata_id(struct aoedev *d) | |||
| 612 | struct frame *f; | 688 | struct frame *f; |
| 613 | struct sk_buff *skb; | 689 | struct sk_buff *skb; |
| 614 | 690 | ||
| 615 | f = getframe(d, FREETAG); | 691 | f = freeframe(d); |
| 616 | if (f == NULL) { | 692 | if (f == NULL) { |
| 617 | printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame. " | 693 | printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); |
| 618 | "This shouldn't happen.\n"); | ||
| 619 | return NULL; | 694 | return NULL; |
| 620 | } | 695 | } |
| 621 | 696 | ||
| 622 | /* initialize the headers & frame */ | 697 | /* initialize the headers & frame */ |
| 623 | h = (struct aoe_hdr *) f->data; | 698 | skb = f->skb; |
| 699 | h = (struct aoe_hdr *) skb->mac.raw; | ||
| 624 | ah = (struct aoe_atahdr *) (h+1); | 700 | ah = (struct aoe_atahdr *) (h+1); |
| 625 | f->ndata = sizeof *h + sizeof *ah; | 701 | skb->len = ETH_ZLEN; |
| 626 | memset(h, 0, f->ndata); | 702 | memset(h, 0, ETH_ZLEN); |
| 627 | f->tag = aoehdr_atainit(d, h); | 703 | f->tag = aoehdr_atainit(d, h); |
| 628 | f->waited = 0; | 704 | f->waited = 0; |
| 629 | f->writedatalen = 0; | ||
| 630 | 705 | ||
| 631 | /* set up ata header */ | 706 | /* set up ata header */ |
| 632 | ah->scnt = 1; | 707 | ah->scnt = 1; |
| 633 | ah->cmdstat = WIN_IDENTIFY; | 708 | ah->cmdstat = WIN_IDENTIFY; |
| 634 | ah->lba3 = 0xa0; | 709 | ah->lba3 = 0xa0; |
| 635 | 710 | ||
| 636 | skb = skb_prepare(d, f); | 711 | skb->dev = d->ifp; |
| 637 | 712 | ||
| 638 | d->rttavg = MAXTIMER; | 713 | d->rttavg = MAXTIMER; |
| 639 | d->timer.function = rexmit_timer; | 714 | d->timer.function = rexmit_timer; |
| 640 | 715 | ||
| 641 | return skb; | 716 | return skb_clone(skb, GFP_ATOMIC); |
| 642 | } | 717 | } |
| 643 | 718 | ||
| 644 | void | 719 | void |
| @@ -648,9 +723,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 648 | struct aoe_hdr *h; | 723 | struct aoe_hdr *h; |
| 649 | struct aoe_cfghdr *ch; | 724 | struct aoe_cfghdr *ch; |
| 650 | ulong flags, sysminor, aoemajor; | 725 | ulong flags, sysminor, aoemajor; |
| 651 | u16 bufcnt; | ||
| 652 | struct sk_buff *sl; | 726 | struct sk_buff *sl; |
| 653 | enum { MAXFRAMES = 16 }; | 727 | enum { MAXFRAMES = 16 }; |
| 728 | u16 n; | ||
| 654 | 729 | ||
| 655 | h = (struct aoe_hdr *) skb->mac.raw; | 730 | h = (struct aoe_hdr *) skb->mac.raw; |
| 656 | ch = (struct aoe_cfghdr *) (h+1); | 731 | ch = (struct aoe_cfghdr *) (h+1); |
| @@ -661,26 +736,25 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 661 | */ | 736 | */ |
| 662 | aoemajor = be16_to_cpu(h->major); | 737 | aoemajor = be16_to_cpu(h->major); |
| 663 | if (aoemajor == 0xfff) { | 738 | if (aoemajor == 0xfff) { |
| 664 | printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf " | 739 | printk(KERN_ERR "aoe: Warning: shelf address is all ones. " |
| 665 | "address is all ones. Check shelf dip switches\n"); | 740 | "Check shelf dip switches.\n"); |
| 666 | return; | 741 | return; |
| 667 | } | 742 | } |
| 668 | 743 | ||
| 669 | sysminor = SYSMINOR(aoemajor, h->minor); | 744 | sysminor = SYSMINOR(aoemajor, h->minor); |
| 670 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { | 745 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { |
| 671 | printk(KERN_INFO | 746 | printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n", |
| 672 | "aoe: e%ld.%d: minor number too large\n", | ||
| 673 | aoemajor, (int) h->minor); | 747 | aoemajor, (int) h->minor); |
| 674 | return; | 748 | return; |
| 675 | } | 749 | } |
| 676 | 750 | ||
| 677 | bufcnt = be16_to_cpu(ch->bufcnt); | 751 | n = be16_to_cpu(ch->bufcnt); |
| 678 | if (bufcnt > MAXFRAMES) /* keep it reasonable */ | 752 | if (n > MAXFRAMES) /* keep it reasonable */ |
| 679 | bufcnt = MAXFRAMES; | 753 | n = MAXFRAMES; |
| 680 | 754 | ||
| 681 | d = aoedev_by_sysminor_m(sysminor, bufcnt); | 755 | d = aoedev_by_sysminor_m(sysminor, n); |
| 682 | if (d == NULL) { | 756 | if (d == NULL) { |
| 683 | printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); | 757 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); |
| 684 | return; | 758 | return; |
| 685 | } | 759 | } |
| 686 | 760 | ||
| @@ -689,6 +763,20 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 689 | /* permit device to migrate mac and network interface */ | 763 | /* permit device to migrate mac and network interface */ |
| 690 | d->ifp = skb->dev; | 764 | d->ifp = skb->dev; |
| 691 | memcpy(d->addr, h->src, sizeof d->addr); | 765 | memcpy(d->addr, h->src, sizeof d->addr); |
| 766 | if (!(d->flags & DEVFL_MAXBCNT)) { | ||
| 767 | n = d->ifp->mtu; | ||
| 768 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | ||
| 769 | n /= 512; | ||
| 770 | if (n > ch->scnt) | ||
| 771 | n = ch->scnt; | ||
| 772 | n = n ? n * 512 : DEFAULTBCNT; | ||
| 773 | if (n != d->maxbcnt) { | ||
| 774 | printk(KERN_INFO | ||
| 775 | "aoe: e%ld.%ld: setting %d byte data frames on %s\n", | ||
| 776 | d->aoemajor, d->aoeminor, n, d->ifp->name); | ||
| 777 | d->maxbcnt = n; | ||
| 778 | } | ||
| 779 | } | ||
| 692 | 780 | ||
| 693 | /* don't change users' perspective */ | 781 | /* don't change users' perspective */ |
| 694 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { | 782 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { |
| @@ -696,6 +784,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
| 696 | return; | 784 | return; |
| 697 | } | 785 | } |
| 698 | d->flags |= DEVFL_PAUSE; /* force pause */ | 786 | d->flags |= DEVFL_PAUSE; /* force pause */ |
| 787 | d->mintimer = MINTIMER; | ||
| 699 | d->fw_ver = be16_to_cpu(ch->fwver); | 788 | d->fw_ver = be16_to_cpu(ch->fwver); |
| 700 | 789 | ||
| 701 | /* check for already outstanding ataid */ | 790 | /* check for already outstanding ataid */ |
