diff options
author | scameron@beardog.cca.cpqcorp.net <scameron@beardog.cca.cpqcorp.net> | 2009-06-08 17:01:11 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-06-08 23:47:42 -0400 |
commit | 5390cfc3fea49d015ae1eed8551c0bf00489b50e (patch) | |
tree | 75e10c0906513958f5e9654f43f864a096049701 /drivers/block/cciss.c | |
parent | 40df6ae4277a67e97aa0a8bd8e293fdbb00e5623 (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/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 183 |
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 | ||
2281 | static int sendcmd_withirq(__u8 cmd, | 2281 | static 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) | 2288 | resend_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 | |||
2371 | command_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 | |||
2380 | static 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 | } |