aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cca.cpqcorp.net>2009-06-02 08:47:50 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-06-02 08:47:50 -0400
commit4a4b2d7684c66dbd8ed04eb284bc94a78e061d29 (patch)
treecd53475c9c89a5d833c55bd53bf22d34228ea909 /drivers/block
parent53c663ce0f39ba8e8ef652e400b317bc60ac7f19 (diff)
cciss: factor out core of sendcmd() for a more sane interface
Factor out the core of sendcmd() to provide a simpler interface which exposes all the error information to the caller and make the original sendcmd use this new function. Rationale: The SCSI error handling routines need to send commands with interrupts turned off, but they also need access to the full error information. Signed-off-by: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net> Cc: Mike Miller <mikem@beardog.cca.cpqcorp.net> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss.c225
1 files changed, 109 insertions, 116 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 94474f5f8bce..8d0f8932fee7 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2373,41 +2373,21 @@ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
2373 return 0; 2373 return 0;
2374} 2374}
2375 2375
2376/* 2376/* Send command c to controller h and poll for it to complete.
2377 * Send a command to the controller, and wait for it to complete. 2377 * Turns interrupts off on the board. Used at driver init time
2378 * Only used at init time. 2378 * and during SCSI error recovery.
2379 */ 2379 */
2380static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, 2380static int sendcmd_core(ctlr_info_t *h, CommandList_struct *c)
2381 1: address logical volume log_unit,
2382 2: periph device address is scsi3addr */
2383 unsigned int log_unit,
2384 __u8 page_code, unsigned char *scsi3addr, int cmd_type)
2385{ 2381{
2386 CommandList_struct *c;
2387 int i; 2382 int i;
2388 unsigned long complete; 2383 unsigned long complete;
2389 ctlr_info_t *info_p = hba[ctlr]; 2384 int status = IO_ERROR;
2390 u64bit buff_dma_handle; 2385 u64bit buff_dma_handle;
2391 int status, done = 0;
2392 2386
2393 if ((c = cmd_alloc(info_p, 1)) == NULL) { 2387resend_cmd1:
2394 printk(KERN_WARNING "cciss: unable to get memory"); 2388
2395 return IO_ERROR; 2389 /* Disable interrupt on the board. */
2396 } 2390 h->access.set_intr_mask(h, CCISS_INTR_OFF);
2397 status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
2398 log_unit, page_code, scsi3addr, cmd_type);
2399 if (status != IO_OK) {
2400 cmd_free(info_p, c, 1);
2401 return status;
2402 }
2403 resend_cmd1:
2404 /*
2405 * Disable interrupt
2406 */
2407#ifdef CCISS_DEBUG
2408 printk(KERN_DEBUG "cciss: turning intr off\n");
2409#endif /* CCISS_DEBUG */
2410 info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
2411 2391
2412 /* Make sure there is room in the command FIFO */ 2392 /* Make sure there is room in the command FIFO */
2413 /* Actually it should be completely empty at this time */ 2393 /* Actually it should be completely empty at this time */
@@ -2415,21 +2395,15 @@ static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use
2415 /* tape side of the driver. */ 2395 /* tape side of the driver. */
2416 for (i = 200000; i > 0; i--) { 2396 for (i = 200000; i > 0; i--) {
2417 /* if fifo isn't full go */ 2397 /* if fifo isn't full go */
2418 if (!(info_p->access.fifo_full(info_p))) { 2398 if (!(h->access.fifo_full(h)))
2419
2420 break; 2399 break;
2421 }
2422 udelay(10); 2400 udelay(10);
2423 printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," 2401 printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
2424 " waiting!\n", ctlr); 2402 " waiting!\n", h->ctlr);
2425 } 2403 }
2426 /* 2404 h->access.submit_command(h, c); /* Send the cmd */
2427 * Send the cmd
2428 */
2429 info_p->access.submit_command(info_p, c);
2430 done = 0;
2431 do { 2405 do {
2432 complete = pollcomplete(ctlr); 2406 complete = pollcomplete(h->ctlr);
2433 2407
2434#ifdef CCISS_DEBUG 2408#ifdef CCISS_DEBUG
2435 printk(KERN_DEBUG "cciss: command completed\n"); 2409 printk(KERN_DEBUG "cciss: command completed\n");
@@ -2438,97 +2412,116 @@ static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use
2438 if (complete == 1) { 2412 if (complete == 1) {
2439 printk(KERN_WARNING 2413 printk(KERN_WARNING
2440 "cciss cciss%d: SendCmd Timeout out, " 2414 "cciss cciss%d: SendCmd Timeout out, "
2441 "No command list address returned!\n", ctlr); 2415 "No command list address returned!\n", h->ctlr);
2442 status = IO_ERROR; 2416 status = IO_ERROR;
2443 done = 1;
2444 break; 2417 break;
2445 } 2418 }
2446 2419
2447 /* This will need to change for direct lookup completions */ 2420 /* If it's not the cmd we're looking for, save it for later */
2448 if ((complete & CISS_ERROR_BIT) 2421 if ((complete & ~CISS_ERROR_BIT) != c->busaddr) {
2449 && (complete & ~CISS_ERROR_BIT) == c->busaddr) { 2422 if (add_sendcmd_reject(c->Request.CDB[0],
2450 /* if data overrun or underun on Report command 2423 h->ctlr, complete) != 0)
2451 ignore it 2424 BUG(); /* we are hosed if we get here. */
2452 */ 2425 continue;
2453 if (((c->Request.CDB[0] == CISS_REPORT_LOG) || 2426 }
2454 (c->Request.CDB[0] == CISS_REPORT_PHYS) || 2427
2455 (c->Request.CDB[0] == CISS_INQUIRY)) && 2428 /* It is our command. If no error, we're done. */
2456 ((c->err_info->CommandStatus == 2429 if (!(complete & CISS_ERROR_BIT)) {
2457 CMD_DATA_OVERRUN) || 2430 status = IO_OK;
2458 (c->err_info->CommandStatus == CMD_DATA_UNDERRUN) 2431 break;
2459 )) { 2432 }
2460 complete = c->busaddr; 2433
2461 } else { 2434 /* There is an error... */
2462 if (c->err_info->CommandStatus == 2435
2463 CMD_UNSOLICITED_ABORT) { 2436 /* if data overrun or underun on Report command ignore it */
2464 printk(KERN_WARNING "cciss%d: " 2437 if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
2465 "unsolicited abort %p\n", 2438 (c->Request.CDB[0] == CISS_REPORT_PHYS) ||
2466 ctlr, c); 2439 (c->Request.CDB[0] == CISS_INQUIRY)) &&
2467 if (c->retry_count < MAX_CMD_RETRIES) { 2440 ((c->err_info->CommandStatus == CMD_DATA_OVERRUN) ||
2468 printk(KERN_WARNING 2441 (c->err_info->CommandStatus == CMD_DATA_UNDERRUN))) {
2469 "cciss%d: retrying %p\n", 2442 complete = c->busaddr;
2470 ctlr, c); 2443 status = IO_OK;
2471 c->retry_count++; 2444 break;
2472 /* erase the old error */
2473 /* information */
2474 memset(c->err_info, 0,
2475 sizeof
2476 (ErrorInfo_struct));
2477 goto resend_cmd1;
2478 } else {
2479 printk(KERN_WARNING
2480 "cciss%d: retried %p too "
2481 "many times\n", ctlr, c);
2482 status = IO_ERROR;
2483 goto cleanup1;
2484 }
2485 } else if (c->err_info->CommandStatus ==
2486 CMD_UNABORTABLE) {
2487 printk(KERN_WARNING
2488 "cciss%d: command could not be aborted.\n",
2489 ctlr);
2490 status = IO_ERROR;
2491 goto cleanup1;
2492 }
2493 printk(KERN_WARNING "ciss ciss%d: sendcmd"
2494 " Error %x \n", ctlr,
2495 c->err_info->CommandStatus);
2496 printk(KERN_WARNING "ciss ciss%d: sendcmd"
2497 " offensive info\n"
2498 " size %x\n num %x value %x\n",
2499 ctlr,
2500 c->err_info->MoreErrInfo.Invalid_Cmd.
2501 offense_size,
2502 c->err_info->MoreErrInfo.Invalid_Cmd.
2503 offense_num,
2504 c->err_info->MoreErrInfo.Invalid_Cmd.
2505 offense_value);
2506 status = IO_ERROR;
2507 goto cleanup1;
2508 }
2509 } 2445 }
2510 /* This will need changing for direct lookup completions */ 2446
2511 if (complete != c->busaddr) { 2447 if (c->err_info->CommandStatus == CMD_UNSOLICITED_ABORT) {
2512 if (add_sendcmd_reject(cmd, ctlr, complete) != 0) { 2448 printk(KERN_WARNING "cciss%d: unsolicited abort %p\n",
2513 BUG(); /* we are pretty much hosed if we get here. */ 2449 h->ctlr, c);
2450 if (c->retry_count < MAX_CMD_RETRIES) {
2451 printk(KERN_WARNING "cciss%d: retrying %p\n",
2452 h->ctlr, c);
2453 c->retry_count++;
2454 /* erase the old error information */
2455 memset(c->err_info, 0, sizeof(c->err_info));
2456 goto resend_cmd1;
2514 } 2457 }
2515 continue; 2458 printk(KERN_WARNING "cciss%d: retried %p too many "
2516 } else 2459 "times\n", h->ctlr, c);
2517 done = 1; 2460 status = IO_ERROR;
2518 } while (!done); 2461 goto cleanup1;
2462 }
2463
2464 if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
2465 printk(KERN_WARNING "cciss%d: command could not be "
2466 "aborted.\n", h->ctlr);
2467 status = IO_ERROR;
2468 goto cleanup1;
2469 }
2470
2471 printk(KERN_WARNING "cciss%d: sendcmd error\n", h->ctlr);
2472 printk(KERN_WARNING "cmd = 0x%02x, CommandStatus = 0x%02x\n",
2473 c->Request.CDB[0], c->err_info->CommandStatus);
2474 if (c->err_info->CommandStatus == CMD_TARGET_STATUS) {
2475 printk(KERN_WARNING "Target status = 0x%02x\n",
2476 c->err_info->ScsiStatus);
2477 if (c->err_info->ScsiStatus == 2) /* chk cond */
2478 printk(KERN_WARNING "Sense key = 0x%02x\n",
2479 0xf & c->err_info->SenseInfo[2]);
2480 }
2481
2482 status = IO_ERROR;
2483 goto cleanup1;
2484
2485 } while (1);
2519 2486
2520 cleanup1: 2487cleanup1:
2521 /* unlock the data buffer from DMA */ 2488 /* unlock the data buffer from DMA */
2522 buff_dma_handle.val32.lower = c->SG[0].Addr.lower; 2489 buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
2523 buff_dma_handle.val32.upper = c->SG[0].Addr.upper; 2490 buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
2524 pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, 2491 pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
2525 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); 2492 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
2526#ifdef CONFIG_CISS_SCSI_TAPE 2493#ifdef CONFIG_CISS_SCSI_TAPE
2527 /* if we saved some commands for later, process them now. */ 2494 /* if we saved some commands for later, process them now. */
2528 if (info_p->scsi_rejects.ncompletions > 0) 2495 if (h->scsi_rejects.ncompletions > 0)
2529 do_cciss_intr(0, info_p); 2496 do_cciss_intr(0, h);
2530#endif 2497#endif
2531 cmd_free(info_p, c, 1); 2498 return status;
2499}
2500
2501/*
2502 * Send a command to the controller, and wait for it to complete.
2503 * Used at init time, and during SCSI error recovery.
2504 */
2505static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
2506 unsigned int use_unit_num,/* 0: address the controller,
2507 1: address logical volume log_unit,
2508 2: periph device address is scsi3addr */
2509 unsigned int log_unit,
2510 __u8 page_code, unsigned char *scsi3addr, int cmd_type)
2511{
2512 CommandList_struct *c;
2513 int status;
2514
2515 c = cmd_alloc(hba[ctlr], 1);
2516 if (!c) {
2517 printk(KERN_WARNING "cciss: unable to get memory");
2518 return IO_ERROR;
2519 }
2520 status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
2521 log_unit, page_code, scsi3addr, cmd_type);
2522 if (status == IO_OK)
2523 status = sendcmd_core(hba[ctlr], c);
2524 cmd_free(hba[ctlr], c, 1);
2532 return status; 2525 return status;
2533} 2526}
2534 2527