aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorscameron@beardog.cca.cpqcorp.net <scameron@beardog.cca.cpqcorp.net>2009-06-08 17:01:11 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-06-08 23:47:42 -0400
commit5390cfc3fea49d015ae1eed8551c0bf00489b50e (patch)
tree75e10c0906513958f5e9654f43f864a096049701 /drivers
parent40df6ae4277a67e97aa0a8bd8e293fdbb00e5623 (diff)
cciss: factor out core of sendcmd_withirq() for use by SCSI error handling code
Factor the core of sendcmd_withirq out to provide a simpler interface which provides access to full error information. Signed-off-by: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/cciss.c183
1 files changed, 96 insertions, 87 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index e7d00952dd4f..74fc85aded92 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2278,114 +2278,123 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
2278 return status; 2278 return status;
2279} 2279}
2280 2280
2281static int sendcmd_withirq(__u8 cmd, 2281static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c)
2282 int ctlr,
2283 void *buff,
2284 size_t size,
2285 unsigned int use_unit_num,
2286 unsigned int log_unit, __u8 page_code, int cmd_type)
2287{ 2282{
2288 ctlr_info_t *h = hba[ctlr]; 2283 DECLARE_COMPLETION_ONSTACK(wait);
2289 CommandList_struct *c;
2290 u64bit buff_dma_handle; 2284 u64bit buff_dma_handle;
2291 unsigned long flags; 2285 unsigned long flags;
2292 int return_status; 2286 int return_status = IO_OK;
2293 DECLARE_COMPLETION_ONSTACK(wait);
2294 2287
2295 if ((c = cmd_alloc(h, 0)) == NULL) 2288resend_cmd2:
2296 return -ENOMEM;
2297 return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
2298 log_unit, page_code, NULL, cmd_type);
2299 if (return_status != IO_OK) {
2300 cmd_free(h, c, 0);
2301 return return_status;
2302 }
2303 resend_cmd2:
2304 c->waiting = &wait; 2289 c->waiting = &wait;
2305
2306 /* Put the request on the tail of the queue and send it */ 2290 /* Put the request on the tail of the queue and send it */
2307 spin_lock_irqsave(CCISS_LOCK(ctlr), flags); 2291 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
2308 addQ(&h->reqQ, c); 2292 addQ(&h->reqQ, c);
2309 h->Qdepth++; 2293 h->Qdepth++;
2310 start_io(h); 2294 start_io(h);
2311 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 2295 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
2312 2296
2313 wait_for_completion(&wait); 2297 wait_for_completion(&wait);
2314 2298
2315 if (c->err_info->CommandStatus != 0) { /* an error has occurred */ 2299 if (c->err_info->CommandStatus == 0)
2316 switch (c->err_info->CommandStatus) { 2300 goto command_done;
2317 case CMD_TARGET_STATUS:
2318 printk(KERN_WARNING "cciss: cmd %p has "
2319 " completed with errors\n", c);
2320 if (c->err_info->ScsiStatus) {
2321 printk(KERN_WARNING "cciss: cmd %p "
2322 "has SCSI Status = %x\n",
2323 c, c->err_info->ScsiStatus);
2324 }
2325 2301
2326 break; 2302 switch (c->err_info->CommandStatus) {
2327 case CMD_DATA_UNDERRUN: 2303 case CMD_TARGET_STATUS:
2328 case CMD_DATA_OVERRUN: 2304 printk(KERN_WARNING "cciss: cmd 0x%02x "
2329 /* expected for inquire and report lun commands */ 2305 "has completed with errors\n", c->Request.CDB[0]);
2330 break; 2306 if (c->err_info->ScsiStatus) {
2331 case CMD_INVALID: 2307 printk(KERN_WARNING "cciss: cmd 0x%02x "
2332 printk(KERN_WARNING "cciss: Cmd %p is " 2308 "has SCSI Status = %x\n",
2333 "reported invalid\n", c); 2309 c->Request.CDB[0], c->err_info->ScsiStatus);
2334 return_status = IO_ERROR; 2310 }
2335 break; 2311 break;
2336 case CMD_PROTOCOL_ERR: 2312 case CMD_DATA_UNDERRUN:
2337 printk(KERN_WARNING "cciss: cmd %p has " 2313 case CMD_DATA_OVERRUN:
2338 "protocol error \n", c); 2314 /* expected for inquiry and report lun commands */
2339 return_status = IO_ERROR; 2315 break;
2340 break; 2316 case CMD_INVALID:
2341 case CMD_HARDWARE_ERR: 2317 printk(KERN_WARNING "cciss: Cmd 0x%02x is "
2342 printk(KERN_WARNING "cciss: cmd %p had " 2318 "reported invalid\n", c->Request.CDB[0]);
2343 " hardware error\n", c); 2319 return_status = IO_ERROR;
2344 return_status = IO_ERROR; 2320 break;
2345 break; 2321 case CMD_PROTOCOL_ERR:
2346 case CMD_CONNECTION_LOST: 2322 printk(KERN_WARNING "cciss: cmd 0x%02x has "
2347 printk(KERN_WARNING "cciss: cmd %p had " 2323 "protocol error \n", c->Request.CDB[0]);
2348 "connection lost\n", c); 2324 return_status = IO_ERROR;
2349 return_status = IO_ERROR; 2325 break;
2350 break; 2326 case CMD_HARDWARE_ERR:
2351 case CMD_ABORTED: 2327 printk(KERN_WARNING "cciss: cmd 0x%02x had "
2352 printk(KERN_WARNING "cciss: cmd %p was " 2328 " hardware error\n", c->Request.CDB[0]);
2353 "aborted\n", c); 2329 return_status = IO_ERROR;
2354 return_status = IO_ERROR; 2330 break;
2355 break; 2331 case CMD_CONNECTION_LOST:
2356 case CMD_ABORT_FAILED: 2332 printk(KERN_WARNING "cciss: cmd 0x%02x had "
2357 printk(KERN_WARNING "cciss: cmd %p reports " 2333 "connection lost\n", c->Request.CDB[0]);
2358 "abort failed\n", c); 2334 return_status = IO_ERROR;
2359 return_status = IO_ERROR; 2335 break;
2360 break; 2336 case CMD_ABORTED:
2361 case CMD_UNSOLICITED_ABORT: 2337 printk(KERN_WARNING "cciss: cmd 0x%02x was "
2338 "aborted\n", c->Request.CDB[0]);
2339 return_status = IO_ERROR;
2340 break;
2341 case CMD_ABORT_FAILED:
2342 printk(KERN_WARNING "cciss: cmd 0x%02x reports "
2343 "abort failed\n", c->Request.CDB[0]);
2344 return_status = IO_ERROR;
2345 break;
2346 case CMD_UNSOLICITED_ABORT:
2347 printk(KERN_WARNING
2348 "cciss%d: unsolicited abort 0x%02x\n", h->ctlr,
2349 c->Request.CDB[0]);
2350 if (c->retry_count < MAX_CMD_RETRIES) {
2362 printk(KERN_WARNING 2351 printk(KERN_WARNING
2363 "cciss%d: unsolicited abort %p\n", ctlr, c); 2352 "cciss%d: retrying 0x%02x\n", h->ctlr,
2364 if (c->retry_count < MAX_CMD_RETRIES) { 2353 c->Request.CDB[0]);
2365 printk(KERN_WARNING 2354 c->retry_count++;
2366 "cciss%d: retrying %p\n", ctlr, c); 2355 /* erase the old error information */
2367 c->retry_count++; 2356 memset(c->err_info, 0,
2368 /* erase the old error information */ 2357 sizeof(ErrorInfo_struct));
2369 memset(c->err_info, 0, 2358 return_status = IO_OK;
2370 sizeof(ErrorInfo_struct)); 2359 INIT_COMPLETION(wait);
2371 return_status = IO_OK; 2360 goto resend_cmd2;
2372 INIT_COMPLETION(wait);
2373 goto resend_cmd2;
2374 }
2375 return_status = IO_ERROR;
2376 break;
2377 default:
2378 printk(KERN_WARNING "cciss: cmd %p returned "
2379 "unknown status %x\n", c,
2380 c->err_info->CommandStatus);
2381 return_status = IO_ERROR;
2382 } 2361 }
2362 return_status = IO_ERROR;
2363 break;
2364 default:
2365 printk(KERN_WARNING "cciss: cmd 0x%02x returned "
2366 "unknown status %x\n", c->Request.CDB[0],
2367 c->err_info->CommandStatus);
2368 return_status = IO_ERROR;
2383 } 2369 }
2370
2371command_done:
2384 /* unlock the buffers from DMA */ 2372 /* unlock the buffers from DMA */
2385 buff_dma_handle.val32.lower = c->SG[0].Addr.lower; 2373 buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
2386 buff_dma_handle.val32.upper = c->SG[0].Addr.upper; 2374 buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
2387 pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val, 2375 pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
2388 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); 2376 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
2377 return return_status;
2378}
2379
2380static int sendcmd_withirq(__u8 cmd,
2381 int ctlr,
2382 void *buff,
2383 size_t size,
2384 unsigned int use_unit_num,
2385 unsigned int log_unit, __u8 page_code, int cmd_type)
2386{
2387 ctlr_info_t *h = hba[ctlr];
2388 CommandList_struct *c;
2389 int return_status;
2390
2391 c = cmd_alloc(h, 0);
2392 if (!c)
2393 return -ENOMEM;
2394 return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
2395 log_unit, page_code, NULL, cmd_type);
2396 if (return_status == IO_OK)
2397 return_status = sendcmd_withirq_core(h, c);
2389 cmd_free(h, c, 0); 2398 cmd_free(h, c, 0);
2390 return return_status; 2399 return return_status;
2391} 2400}