aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2012-05-01 12:42:56 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-05-10 04:15:16 -0400
commit6cba3f1972de14421ef4cf4b46a15cc5d604e791 (patch)
tree29f4a1ad2729ce2808e788cd064b7f7a83de8153
parent75167d2cc7654f57b90497fe90b1f0ae946c22a6 (diff)
[SCSI] hpsa: do aborts two ways
When aborting a command, the tag is supposed to be specified as 64-bit little endian. However, some smart arrays expect the tag of the command to be aborted to be specified in a strange byte order. How to tell which sort of Smart Array firmware we're dealing with is not obvious. However, because of the way we construct our tags, the values of any outstanding tag when specified with the "strange" byte order will not collide with the value specified in the correct order. That means we can safely attempt the abort both ways. Signed-off-by: Stephen M. Cameron <stephenmcameron@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/hpsa.c74
1 files changed, 72 insertions, 2 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a2c99245b82c..87f8a1b8d2ea 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2355,8 +2355,23 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
2355 return FAILED; 2355 return FAILED;
2356} 2356}
2357 2357
2358static void swizzle_abort_tag(u8 *tag)
2359{
2360 u8 original_tag[8];
2361
2362 memcpy(original_tag, tag, 8);
2363 tag[0] = original_tag[3];
2364 tag[1] = original_tag[2];
2365 tag[2] = original_tag[1];
2366 tag[3] = original_tag[0];
2367 tag[4] = original_tag[7];
2368 tag[5] = original_tag[6];
2369 tag[6] = original_tag[5];
2370 tag[7] = original_tag[4];
2371}
2372
2358static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr, 2373static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
2359 struct CommandList *abort) 2374 struct CommandList *abort, int swizzle)
2360{ 2375{
2361 int rc = IO_OK; 2376 int rc = IO_OK;
2362 struct CommandList *c; 2377 struct CommandList *c;
@@ -2369,6 +2384,8 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
2369 } 2384 }
2370 2385
2371 fill_cmd(c, HPSA_ABORT_MSG, h, abort, 0, 0, scsi3addr, TYPE_MSG); 2386 fill_cmd(c, HPSA_ABORT_MSG, h, abort, 0, 0, scsi3addr, TYPE_MSG);
2387 if (swizzle)
2388 swizzle_abort_tag(&c->Request.CDB[4]);
2372 hpsa_scsi_do_simple_cmd_core(h, c); 2389 hpsa_scsi_do_simple_cmd_core(h, c);
2373 dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd_core completed.\n", 2390 dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd_core completed.\n",
2374 __func__, abort->Header.Tag.upper, abort->Header.Tag.lower); 2391 __func__, abort->Header.Tag.upper, abort->Header.Tag.lower);
@@ -2428,6 +2445,59 @@ static struct CommandList *hpsa_find_cmd_in_queue(struct ctlr_info *h,
2428 return NULL; 2445 return NULL;
2429} 2446}
2430 2447
2448static struct CommandList *hpsa_find_cmd_in_queue_by_tag(struct ctlr_info *h,
2449 u8 *tag, struct list_head *queue_head)
2450{
2451 unsigned long flags;
2452 struct CommandList *c;
2453
2454 spin_lock_irqsave(&h->lock, flags);
2455 list_for_each_entry(c, queue_head, list) {
2456 if (memcmp(&c->Header.Tag, tag, 8) != 0)
2457 continue;
2458 spin_unlock_irqrestore(&h->lock, flags);
2459 return c;
2460 }
2461 spin_unlock_irqrestore(&h->lock, flags);
2462 return NULL;
2463}
2464
2465/* Some Smart Arrays need the abort tag swizzled, and some don't. It's hard to
2466 * tell which kind we're dealing with, so we send the abort both ways. There
2467 * shouldn't be any collisions between swizzled and unswizzled tags due to the
2468 * way we construct our tags but we check anyway in case the assumptions which
2469 * make this true someday become false.
2470 */
2471static int hpsa_send_abort_both_ways(struct ctlr_info *h,
2472 unsigned char *scsi3addr, struct CommandList *abort)
2473{
2474 u8 swizzled_tag[8];
2475 struct CommandList *c;
2476 int rc = 0, rc2 = 0;
2477
2478 /* we do not expect to find the swizzled tag in our queue, but
2479 * check anyway just to be sure the assumptions which make this
2480 * the case haven't become wrong.
2481 */
2482 memcpy(swizzled_tag, &abort->Request.CDB[4], 8);
2483 swizzle_abort_tag(swizzled_tag);
2484 c = hpsa_find_cmd_in_queue_by_tag(h, swizzled_tag, &h->cmpQ);
2485 if (c != NULL) {
2486 dev_warn(&h->pdev->dev, "Unexpectedly found byte-swapped tag in completion queue.\n");
2487 return hpsa_send_abort(h, scsi3addr, abort, 0);
2488 }
2489 rc = hpsa_send_abort(h, scsi3addr, abort, 0);
2490
2491 /* if the command is still in our queue, we can't conclude that it was
2492 * aborted (it might have just completed normally) but in any case
2493 * we don't need to try to abort it another way.
2494 */
2495 c = hpsa_find_cmd_in_queue(h, abort->scsi_cmd, &h->cmpQ);
2496 if (c)
2497 rc2 = hpsa_send_abort(h, scsi3addr, abort, 1);
2498 return rc && rc2;
2499}
2500
2431/* Send an abort for the specified command. 2501/* Send an abort for the specified command.
2432 * If the device and controller support it, 2502 * If the device and controller support it,
2433 * send a task abort request. 2503 * send a task abort request.
@@ -2512,7 +2582,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
2512 * by the firmware (but not to the scsi mid layer) but we can't 2582 * by the firmware (but not to the scsi mid layer) but we can't
2513 * distinguish which. Send the abort down. 2583 * distinguish which. Send the abort down.
2514 */ 2584 */
2515 rc = hpsa_send_abort(h, dev->scsi3addr, abort); 2585 rc = hpsa_send_abort_both_ways(h, dev->scsi3addr, abort);
2516 if (rc != 0) { 2586 if (rc != 0) {
2517 dev_dbg(&h->pdev->dev, "%s Request FAILED.\n", msg); 2587 dev_dbg(&h->pdev->dev, "%s Request FAILED.\n", msg);
2518 dev_warn(&h->pdev->dev, "FAILED abort on device C%d:B%d:T%d:L%d\n", 2588 dev_warn(&h->pdev->dev, "FAILED abort on device C%d:B%d:T%d:L%d\n",