diff options
author | Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net> | 2009-06-02 08:47:50 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-06-02 08:47:50 -0400 |
commit | 4a4b2d7684c66dbd8ed04eb284bc94a78e061d29 (patch) | |
tree | cd53475c9c89a5d833c55bd53bf22d34228ea909 /drivers | |
parent | 53c663ce0f39ba8e8ef652e400b317bc60ac7f19 (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')
-rw-r--r-- | drivers/block/cciss.c | 225 |
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 | */ |
2380 | static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, | 2380 | static 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) { | 2387 | resend_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: | 2487 | cleanup1: |
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 | */ | ||
2505 | static 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 | ||