diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/cciss.c | 77 | ||||
-rw-r--r-- | drivers/block/cciss.h | 1 |
2 files changed, 46 insertions, 32 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 2d128831d3ca..700170711061 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -2292,26 +2292,12 @@ static int check_target_status(ctlr_info_t *h, CommandList_struct *c) | |||
2292 | return IO_ERROR; | 2292 | return IO_ERROR; |
2293 | } | 2293 | } |
2294 | 2294 | ||
2295 | static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c) | 2295 | static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c) |
2296 | { | 2296 | { |
2297 | DECLARE_COMPLETION_ONSTACK(wait); | ||
2298 | u64bit buff_dma_handle; | ||
2299 | unsigned long flags; | ||
2300 | int return_status = IO_OK; | 2297 | int return_status = IO_OK; |
2301 | 2298 | ||
2302 | resend_cmd2: | 2299 | if (c->err_info->CommandStatus == CMD_SUCCESS) |
2303 | c->waiting = &wait; | 2300 | return IO_OK; |
2304 | /* Put the request on the tail of the queue and send it */ | ||
2305 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
2306 | addQ(&h->reqQ, c); | ||
2307 | h->Qdepth++; | ||
2308 | start_io(h); | ||
2309 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
2310 | |||
2311 | wait_for_completion(&wait); | ||
2312 | |||
2313 | if (c->err_info->CommandStatus == 0) | ||
2314 | goto command_done; | ||
2315 | 2301 | ||
2316 | switch (c->err_info->CommandStatus) { | 2302 | switch (c->err_info->CommandStatus) { |
2317 | case CMD_TARGET_STATUS: | 2303 | case CMD_TARGET_STATUS: |
@@ -2322,7 +2308,7 @@ resend_cmd2: | |||
2322 | /* expected for inquiry and report lun commands */ | 2308 | /* expected for inquiry and report lun commands */ |
2323 | break; | 2309 | break; |
2324 | case CMD_INVALID: | 2310 | case CMD_INVALID: |
2325 | printk(KERN_WARNING "cciss: Cmd 0x%02x is " | 2311 | printk(KERN_WARNING "cciss: cmd 0x%02x is " |
2326 | "reported invalid\n", c->Request.CDB[0]); | 2312 | "reported invalid\n", c->Request.CDB[0]); |
2327 | return_status = IO_ERROR; | 2313 | return_status = IO_ERROR; |
2328 | break; | 2314 | break; |
@@ -2355,19 +2341,7 @@ resend_cmd2: | |||
2355 | printk(KERN_WARNING | 2341 | printk(KERN_WARNING |
2356 | "cciss%d: unsolicited abort 0x%02x\n", h->ctlr, | 2342 | "cciss%d: unsolicited abort 0x%02x\n", h->ctlr, |
2357 | c->Request.CDB[0]); | 2343 | c->Request.CDB[0]); |
2358 | if (c->retry_count < MAX_CMD_RETRIES) { | 2344 | return_status = IO_NEEDS_RETRY; |
2359 | printk(KERN_WARNING | ||
2360 | "cciss%d: retrying 0x%02x\n", h->ctlr, | ||
2361 | c->Request.CDB[0]); | ||
2362 | c->retry_count++; | ||
2363 | /* erase the old error information */ | ||
2364 | memset(c->err_info, 0, | ||
2365 | sizeof(ErrorInfo_struct)); | ||
2366 | return_status = IO_OK; | ||
2367 | INIT_COMPLETION(wait); | ||
2368 | goto resend_cmd2; | ||
2369 | } | ||
2370 | return_status = IO_ERROR; | ||
2371 | break; | 2345 | break; |
2372 | default: | 2346 | default: |
2373 | printk(KERN_WARNING "cciss: cmd 0x%02x returned " | 2347 | printk(KERN_WARNING "cciss: cmd 0x%02x returned " |
@@ -2375,6 +2349,44 @@ resend_cmd2: | |||
2375 | c->err_info->CommandStatus); | 2349 | c->err_info->CommandStatus); |
2376 | return_status = IO_ERROR; | 2350 | return_status = IO_ERROR; |
2377 | } | 2351 | } |
2352 | return return_status; | ||
2353 | } | ||
2354 | |||
2355 | static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, | ||
2356 | int attempt_retry) | ||
2357 | { | ||
2358 | DECLARE_COMPLETION_ONSTACK(wait); | ||
2359 | u64bit buff_dma_handle; | ||
2360 | unsigned long flags; | ||
2361 | int return_status = IO_OK; | ||
2362 | |||
2363 | resend_cmd2: | ||
2364 | c->waiting = &wait; | ||
2365 | /* Put the request on the tail of the queue and send it */ | ||
2366 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
2367 | addQ(&h->reqQ, c); | ||
2368 | h->Qdepth++; | ||
2369 | start_io(h); | ||
2370 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
2371 | |||
2372 | wait_for_completion(&wait); | ||
2373 | |||
2374 | if (c->err_info->CommandStatus == 0 || !attempt_retry) | ||
2375 | goto command_done; | ||
2376 | |||
2377 | return_status = process_sendcmd_error(h, c); | ||
2378 | |||
2379 | if (return_status == IO_NEEDS_RETRY && | ||
2380 | c->retry_count < MAX_CMD_RETRIES) { | ||
2381 | printk(KERN_WARNING "cciss%d: retrying 0x%02x\n", h->ctlr, | ||
2382 | c->Request.CDB[0]); | ||
2383 | c->retry_count++; | ||
2384 | /* erase the old error information */ | ||
2385 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); | ||
2386 | return_status = IO_OK; | ||
2387 | INIT_COMPLETION(wait); | ||
2388 | goto resend_cmd2; | ||
2389 | } | ||
2378 | 2390 | ||
2379 | command_done: | 2391 | command_done: |
2380 | /* unlock the buffers from DMA */ | 2392 | /* unlock the buffers from DMA */ |
@@ -2399,7 +2411,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, | |||
2399 | return_status = fill_cmd(c, cmd, ctlr, buff, size, page_code, | 2411 | return_status = fill_cmd(c, cmd, ctlr, buff, size, page_code, |
2400 | scsi3addr, cmd_type); | 2412 | scsi3addr, cmd_type); |
2401 | if (return_status == IO_OK) | 2413 | if (return_status == IO_OK) |
2402 | return_status = sendcmd_withirq_core(h, c); | 2414 | return_status = sendcmd_withirq_core(h, c, 1); |
2415 | |||
2403 | cmd_free(h, c, 0); | 2416 | cmd_free(h, c, 0); |
2404 | return return_status; | 2417 | return return_status; |
2405 | } | 2418 | } |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index dd1926d8cd97..25cd58e25021 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #define IO_OK 0 | 12 | #define IO_OK 0 |
13 | #define IO_ERROR 1 | 13 | #define IO_ERROR 1 |
14 | #define IO_NEEDS_RETRY 3 | ||
14 | 15 | ||
15 | #define VENDOR_LEN 8 | 16 | #define VENDOR_LEN 8 |
16 | #define MODEL_LEN 16 | 17 | #define MODEL_LEN 16 |