aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c288
1 files changed, 176 insertions, 112 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 65a725cd3422..370dfe1c422e 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -45,6 +45,10 @@
45#include <linux/blkdev.h> 45#include <linux/blkdev.h>
46#include <linux/genhd.h> 46#include <linux/genhd.h>
47#include <linux/completion.h> 47#include <linux/completion.h>
48#include <scsi/scsi.h>
49#include <scsi/sg.h>
50#include <scsi/scsi_ioctl.h>
51#include <linux/cdrom.h>
48 52
49#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) 53#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
50#define DRIVER_NAME "HP CISS Driver (v 3.6.14)" 54#define DRIVER_NAME "HP CISS Driver (v 3.6.14)"
@@ -1152,6 +1156,30 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
1152 kfree(ioc); 1156 kfree(ioc);
1153 return status; 1157 return status;
1154 } 1158 }
1159
1160 /* scsi_cmd_ioctl handles these, below, though some are not */
1161 /* very meaningful for cciss. SG_IO is the main one people want. */
1162
1163 case SG_GET_VERSION_NUM:
1164 case SG_SET_TIMEOUT:
1165 case SG_GET_TIMEOUT:
1166 case SG_GET_RESERVED_SIZE:
1167 case SG_SET_RESERVED_SIZE:
1168 case SG_EMULATED_HOST:
1169 case SG_IO:
1170 case SCSI_IOCTL_SEND_COMMAND:
1171 return scsi_cmd_ioctl(filep, disk, cmd, argp);
1172
1173 /* scsi_cmd_ioctl would normally handle these, below, but */
1174 /* they aren't a good fit for cciss, as CD-ROMs are */
1175 /* not supported, and we don't have any bus/target/lun */
1176 /* which we present to the kernel. */
1177
1178 case CDROM_SEND_PACKET:
1179 case CDROMCLOSETRAY:
1180 case CDROMEJECT:
1181 case SCSI_IOCTL_GET_IDLUN:
1182 case SCSI_IOCTL_GET_BUS_NUMBER:
1155 default: 1183 default:
1156 return -ENOTTY; 1184 return -ENOTTY;
1157 } 1185 }
@@ -1234,7 +1262,7 @@ static void cciss_softirq_done(struct request *rq)
1234 pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir); 1262 pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
1235 } 1263 }
1236 1264
1237 complete_buffers(rq->bio, rq->errors); 1265 complete_buffers(rq->bio, (rq->errors == 0));
1238 1266
1239 if (blk_fs_request(rq)) { 1267 if (blk_fs_request(rq)) {
1240 const int rw = rq_data_dir(rq); 1268 const int rw = rq_data_dir(rq);
@@ -1248,7 +1276,7 @@ static void cciss_softirq_done(struct request *rq)
1248 1276
1249 add_disk_randomness(rq->rq_disk); 1277 add_disk_randomness(rq->rq_disk);
1250 spin_lock_irqsave(&h->lock, flags); 1278 spin_lock_irqsave(&h->lock, flags);
1251 end_that_request_last(rq, rq->errors); 1279 end_that_request_last(rq, (rq->errors == 0));
1252 cmd_free(h, cmd, 1); 1280 cmd_free(h, cmd, 1);
1253 cciss_check_queues(h); 1281 cciss_check_queues(h);
1254 spin_unlock_irqrestore(&h->lock, flags); 1282 spin_unlock_irqrestore(&h->lock, flags);
@@ -2336,6 +2364,44 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
2336 start_io(h); 2364 start_io(h);
2337} 2365}
2338 2366
2367static inline int evaluate_target_status(CommandList_struct *cmd)
2368{
2369 unsigned char sense_key;
2370 int error_count = 1;
2371
2372 if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */
2373 if (!blk_pc_request(cmd->rq))
2374 printk(KERN_WARNING "cciss: cmd %p "
2375 "has SCSI Status 0x%x\n",
2376 cmd, cmd->err_info->ScsiStatus);
2377 return error_count;
2378 }
2379
2380 /* check the sense key */
2381 sense_key = 0xf & cmd->err_info->SenseInfo[2];
2382 /* no status or recovered error */
2383 if ((sense_key == 0x0) || (sense_key == 0x1))
2384 error_count = 0;
2385
2386 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
2387 if (error_count != 0)
2388 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
2389 " sense key = 0x%x\n", cmd, sense_key);
2390 return error_count;
2391 }
2392
2393 /* SG_IO or similar, copy sense data back */
2394 if (cmd->rq->sense) {
2395 if (cmd->rq->sense_len > cmd->err_info->SenseLen)
2396 cmd->rq->sense_len = cmd->err_info->SenseLen;
2397 memcpy(cmd->rq->sense, cmd->err_info->SenseInfo,
2398 cmd->rq->sense_len);
2399 } else
2400 cmd->rq->sense_len = 0;
2401
2402 return error_count;
2403}
2404
2339/* checks the status of the job and calls complete buffers to mark all 2405/* checks the status of the job and calls complete buffers to mark all
2340 * buffers for the completed job. Note that this function does not need 2406 * buffers for the completed job. Note that this function does not need
2341 * to hold the hba/queue lock. 2407 * to hold the hba/queue lock.
@@ -2343,109 +2409,99 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
2343static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, 2409static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2344 int timeout) 2410 int timeout)
2345{ 2411{
2346 int status = 1;
2347 int retry_cmd = 0; 2412 int retry_cmd = 0;
2413 struct request *rq = cmd->rq;
2414
2415 rq->errors = 0;
2348 2416
2349 if (timeout) 2417 if (timeout)
2350 status = 0; 2418 rq->errors = 1;
2351 2419
2352 if (cmd->err_info->CommandStatus != 0) { /* an error has occurred */ 2420 if (cmd->err_info->CommandStatus == 0) /* no error has occurred */
2353 switch (cmd->err_info->CommandStatus) { 2421 goto after_error_processing;
2354 unsigned char sense_key;
2355 case CMD_TARGET_STATUS:
2356 status = 0;
2357 2422
2358 if (cmd->err_info->ScsiStatus == 0x02) { 2423 switch (cmd->err_info->CommandStatus) {
2359 printk(KERN_WARNING "cciss: cmd %p " 2424 case CMD_TARGET_STATUS:
2360 "has CHECK CONDITION " 2425 rq->errors = evaluate_target_status(cmd);
2361 " byte 2 = 0x%x\n", cmd, 2426 break;
2362 cmd->err_info->SenseInfo[2] 2427 case CMD_DATA_UNDERRUN:
2363 ); 2428 if (blk_fs_request(cmd->rq)) {
2364 /* check the sense key */
2365 sense_key = 0xf & cmd->err_info->SenseInfo[2];
2366 /* no status or recovered error */
2367 if ((sense_key == 0x0) || (sense_key == 0x1)) {
2368 status = 1;
2369 }
2370 } else {
2371 printk(KERN_WARNING "cciss: cmd %p "
2372 "has SCSI Status 0x%x\n",
2373 cmd, cmd->err_info->ScsiStatus);
2374 }
2375 break;
2376 case CMD_DATA_UNDERRUN:
2377 printk(KERN_WARNING "cciss: cmd %p has" 2429 printk(KERN_WARNING "cciss: cmd %p has"
2378 " completed with data underrun " 2430 " completed with data underrun "
2379 "reported\n", cmd); 2431 "reported\n", cmd);
2380 break; 2432 cmd->rq->data_len = cmd->err_info->ResidualCnt;
2381 case CMD_DATA_OVERRUN: 2433 }
2434 break;
2435 case CMD_DATA_OVERRUN:
2436 if (blk_fs_request(cmd->rq))
2382 printk(KERN_WARNING "cciss: cmd %p has" 2437 printk(KERN_WARNING "cciss: cmd %p has"
2383 " completed with data overrun " 2438 " completed with data overrun "
2384 "reported\n", cmd); 2439 "reported\n", cmd);
2385 break; 2440 break;
2386 case CMD_INVALID: 2441 case CMD_INVALID:
2387 printk(KERN_WARNING "cciss: cmd %p is " 2442 printk(KERN_WARNING "cciss: cmd %p is "
2388 "reported invalid\n", cmd); 2443 "reported invalid\n", cmd);
2389 status = 0; 2444 rq->errors = 1;
2390 break; 2445 break;
2391 case CMD_PROTOCOL_ERR: 2446 case CMD_PROTOCOL_ERR:
2392 printk(KERN_WARNING "cciss: cmd %p has " 2447 printk(KERN_WARNING "cciss: cmd %p has "
2393 "protocol error \n", cmd); 2448 "protocol error \n", cmd);
2394 status = 0; 2449 rq->errors = 1;
2395 break; 2450 break;
2396 case CMD_HARDWARE_ERR: 2451 case CMD_HARDWARE_ERR:
2397 printk(KERN_WARNING "cciss: cmd %p had " 2452 printk(KERN_WARNING "cciss: cmd %p had "
2398 " hardware error\n", cmd); 2453 " hardware error\n", cmd);
2399 status = 0; 2454 rq->errors = 1;
2400 break; 2455 break;
2401 case CMD_CONNECTION_LOST: 2456 case CMD_CONNECTION_LOST:
2402 printk(KERN_WARNING "cciss: cmd %p had " 2457 printk(KERN_WARNING "cciss: cmd %p had "
2403 "connection lost\n", cmd); 2458 "connection lost\n", cmd);
2404 status = 0; 2459 rq->errors = 1;
2405 break; 2460 break;
2406 case CMD_ABORTED: 2461 case CMD_ABORTED:
2407 printk(KERN_WARNING "cciss: cmd %p was " 2462 printk(KERN_WARNING "cciss: cmd %p was "
2408 "aborted\n", cmd); 2463 "aborted\n", cmd);
2409 status = 0; 2464 rq->errors = 1;
2410 break; 2465 break;
2411 case CMD_ABORT_FAILED: 2466 case CMD_ABORT_FAILED:
2412 printk(KERN_WARNING "cciss: cmd %p reports " 2467 printk(KERN_WARNING "cciss: cmd %p reports "
2413 "abort failed\n", cmd); 2468 "abort failed\n", cmd);
2414 status = 0; 2469 rq->errors = 1;
2415 break; 2470 break;
2416 case CMD_UNSOLICITED_ABORT: 2471 case CMD_UNSOLICITED_ABORT:
2417 printk(KERN_WARNING "cciss%d: unsolicited " 2472 printk(KERN_WARNING "cciss%d: unsolicited "
2418 "abort %p\n", h->ctlr, cmd); 2473 "abort %p\n", h->ctlr, cmd);
2419 if (cmd->retry_count < MAX_CMD_RETRIES) { 2474 if (cmd->retry_count < MAX_CMD_RETRIES) {
2420 retry_cmd = 1; 2475 retry_cmd = 1;
2421 printk(KERN_WARNING 2476 printk(KERN_WARNING
2422 "cciss%d: retrying %p\n", h->ctlr, cmd); 2477 "cciss%d: retrying %p\n", h->ctlr, cmd);
2423 cmd->retry_count++; 2478 cmd->retry_count++;
2424 } else 2479 } else
2425 printk(KERN_WARNING 2480 printk(KERN_WARNING
2426 "cciss%d: %p retried too " 2481 "cciss%d: %p retried too "
2427 "many times\n", h->ctlr, cmd); 2482 "many times\n", h->ctlr, cmd);
2428 status = 0; 2483 rq->errors = 1;
2429 break; 2484 break;
2430 case CMD_TIMEOUT: 2485 case CMD_TIMEOUT:
2431 printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); 2486 printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
2432 status = 0; 2487 rq->errors = 1;
2433 break; 2488 break;
2434 default: 2489 default:
2435 printk(KERN_WARNING "cciss: cmd %p returned " 2490 printk(KERN_WARNING "cciss: cmd %p returned "
2436 "unknown status %x\n", cmd, 2491 "unknown status %x\n", cmd,
2437 cmd->err_info->CommandStatus); 2492 cmd->err_info->CommandStatus);
2438 status = 0; 2493 rq->errors = 1;
2439 }
2440 } 2494 }
2495
2496after_error_processing:
2497
2441 /* We need to return this command */ 2498 /* We need to return this command */
2442 if (retry_cmd) { 2499 if (retry_cmd) {
2443 resend_cciss_cmd(h, cmd); 2500 resend_cciss_cmd(h, cmd);
2444 return; 2501 return;
2445 } 2502 }
2446 2503 cmd->rq->data_len = 0;
2447 cmd->rq->completion_data = cmd; 2504 cmd->rq->completion_data = cmd;
2448 cmd->rq->errors = status;
2449 blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE); 2505 blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE);
2450 blk_complete_request(cmd->rq); 2506 blk_complete_request(cmd->rq);
2451} 2507}
@@ -2539,32 +2595,40 @@ static void do_cciss_request(request_queue_t *q)
2539#endif /* CCISS_DEBUG */ 2595#endif /* CCISS_DEBUG */
2540 2596
2541 c->Header.SGList = c->Header.SGTotal = seg; 2597 c->Header.SGList = c->Header.SGTotal = seg;
2542 if(h->cciss_read == CCISS_READ_10) { 2598 if (likely(blk_fs_request(creq))) {
2543 c->Request.CDB[1] = 0; 2599 if(h->cciss_read == CCISS_READ_10) {
2544 c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB 2600 c->Request.CDB[1] = 0;
2545 c->Request.CDB[3] = (start_blk >> 16) & 0xff; 2601 c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
2546 c->Request.CDB[4] = (start_blk >> 8) & 0xff; 2602 c->Request.CDB[3] = (start_blk >> 16) & 0xff;
2547 c->Request.CDB[5] = start_blk & 0xff; 2603 c->Request.CDB[4] = (start_blk >> 8) & 0xff;
2548 c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB 2604 c->Request.CDB[5] = start_blk & 0xff;
2549 c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; 2605 c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
2550 c->Request.CDB[8] = creq->nr_sectors & 0xff; 2606 c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
2551 c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; 2607 c->Request.CDB[8] = creq->nr_sectors & 0xff;
2608 c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
2609 } else {
2610 c->Request.CDBLen = 16;
2611 c->Request.CDB[1]= 0;
2612 c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
2613 c->Request.CDB[3]= (start_blk >> 48) & 0xff;
2614 c->Request.CDB[4]= (start_blk >> 40) & 0xff;
2615 c->Request.CDB[5]= (start_blk >> 32) & 0xff;
2616 c->Request.CDB[6]= (start_blk >> 24) & 0xff;
2617 c->Request.CDB[7]= (start_blk >> 16) & 0xff;
2618 c->Request.CDB[8]= (start_blk >> 8) & 0xff;
2619 c->Request.CDB[9]= start_blk & 0xff;
2620 c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff;
2621 c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff;
2622 c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff;
2623 c->Request.CDB[13]= creq->nr_sectors & 0xff;
2624 c->Request.CDB[14] = c->Request.CDB[15] = 0;
2625 }
2626 } else if (blk_pc_request(creq)) {
2627 c->Request.CDBLen = creq->cmd_len;
2628 memcpy(c->Request.CDB, creq->cmd, BLK_MAX_CDB);
2552 } else { 2629 } else {
2553 c->Request.CDBLen = 16; 2630 printk(KERN_WARNING "cciss%d: bad request type %d\n", h->ctlr, creq->cmd_type);
2554 c->Request.CDB[1]= 0; 2631 BUG();
2555 c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
2556 c->Request.CDB[3]= (start_blk >> 48) & 0xff;
2557 c->Request.CDB[4]= (start_blk >> 40) & 0xff;
2558 c->Request.CDB[5]= (start_blk >> 32) & 0xff;
2559 c->Request.CDB[6]= (start_blk >> 24) & 0xff;
2560 c->Request.CDB[7]= (start_blk >> 16) & 0xff;
2561 c->Request.CDB[8]= (start_blk >> 8) & 0xff;
2562 c->Request.CDB[9]= start_blk & 0xff;
2563 c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff;
2564 c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff;
2565 c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff;
2566 c->Request.CDB[13]= creq->nr_sectors & 0xff;
2567 c->Request.CDB[14] = c->Request.CDB[15] = 0;
2568 } 2632 }
2569 2633
2570 spin_lock_irq(q->queue_lock); 2634 spin_lock_irq(q->queue_lock);