aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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",