diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2c6116fd4578..0a3a528212c2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -86,6 +86,19 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); | |||
86 | MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); | 86 | MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); |
87 | MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); | 87 | MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); |
88 | 88 | ||
89 | static int sd_revalidate_disk(struct gendisk *); | ||
90 | static int sd_probe(struct device *); | ||
91 | static int sd_remove(struct device *); | ||
92 | static void sd_shutdown(struct device *); | ||
93 | static int sd_suspend(struct device *, pm_message_t state); | ||
94 | static int sd_resume(struct device *); | ||
95 | static void sd_rescan(struct device *); | ||
96 | static int sd_done(struct scsi_cmnd *); | ||
97 | static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); | ||
98 | static void scsi_disk_release(struct class_device *cdev); | ||
99 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); | ||
100 | static void sd_print_result(struct scsi_disk *, int); | ||
101 | |||
89 | static DEFINE_IDR(sd_index_idr); | 102 | static DEFINE_IDR(sd_index_idr); |
90 | static DEFINE_SPINLOCK(sd_index_lock); | 103 | static DEFINE_SPINLOCK(sd_index_lock); |
91 | 104 | ||
@@ -240,7 +253,7 @@ static struct scsi_driver sd_template = { | |||
240 | .shutdown = sd_shutdown, | 253 | .shutdown = sd_shutdown, |
241 | }, | 254 | }, |
242 | .rescan = sd_rescan, | 255 | .rescan = sd_rescan, |
243 | .init_command = sd_init_command, | 256 | .done = sd_done, |
244 | }; | 257 | }; |
245 | 258 | ||
246 | /* | 259 | /* |
@@ -331,14 +344,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
331 | * | 344 | * |
332 | * Returns 1 if successful and 0 if error (or cannot be done now). | 345 | * Returns 1 if successful and 0 if error (or cannot be done now). |
333 | **/ | 346 | **/ |
334 | static int sd_init_command(struct scsi_cmnd * SCpnt) | 347 | static int sd_prep_fn(struct request_queue *q, struct request *rq) |
335 | { | 348 | { |
336 | struct scsi_device *sdp = SCpnt->device; | 349 | struct scsi_cmnd *SCpnt; |
337 | struct request *rq = SCpnt->request; | 350 | struct scsi_device *sdp = q->queuedata; |
338 | struct gendisk *disk = rq->rq_disk; | 351 | struct gendisk *disk = rq->rq_disk; |
339 | sector_t block = rq->sector; | 352 | sector_t block = rq->sector; |
340 | unsigned int this_count = SCpnt->request_bufflen >> 9; | 353 | unsigned int this_count = rq->nr_sectors; |
341 | unsigned int timeout = sdp->timeout; | 354 | unsigned int timeout = sdp->timeout; |
355 | int ret; | ||
356 | |||
357 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { | ||
358 | ret = scsi_setup_blk_pc_cmnd(sdp, rq); | ||
359 | goto out; | ||
360 | } else if (rq->cmd_type != REQ_TYPE_FS) { | ||
361 | ret = BLKPREP_KILL; | ||
362 | goto out; | ||
363 | } | ||
364 | ret = scsi_setup_fs_cmnd(sdp, rq); | ||
365 | if (ret != BLKPREP_OK) | ||
366 | goto out; | ||
367 | SCpnt = rq->special; | ||
368 | |||
369 | /* from here on until we're complete, any goto out | ||
370 | * is used for a killable error condition */ | ||
371 | ret = BLKPREP_KILL; | ||
342 | 372 | ||
343 | SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, | 373 | SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, |
344 | "sd_init_command: block=%llu, " | 374 | "sd_init_command: block=%llu, " |
@@ -353,7 +383,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
353 | rq->nr_sectors)); | 383 | rq->nr_sectors)); |
354 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, | 384 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, |
355 | "Retry with 0x%p\n", SCpnt)); | 385 | "Retry with 0x%p\n", SCpnt)); |
356 | return 0; | 386 | goto out; |
357 | } | 387 | } |
358 | 388 | ||
359 | if (sdp->changed) { | 389 | if (sdp->changed) { |
@@ -362,8 +392,9 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
362 | * the changed bit has been reset | 392 | * the changed bit has been reset |
363 | */ | 393 | */ |
364 | /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ | 394 | /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ |
365 | return 0; | 395 | goto out; |
366 | } | 396 | } |
397 | |||
367 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", | 398 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", |
368 | (unsigned long long)block)); | 399 | (unsigned long long)block)); |
369 | 400 | ||
@@ -382,7 +413,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
382 | if ((block & 1) || (rq->nr_sectors & 1)) { | 413 | if ((block & 1) || (rq->nr_sectors & 1)) { |
383 | scmd_printk(KERN_ERR, SCpnt, | 414 | scmd_printk(KERN_ERR, SCpnt, |
384 | "Bad block number requested\n"); | 415 | "Bad block number requested\n"); |
385 | return 0; | 416 | goto out; |
386 | } else { | 417 | } else { |
387 | block = block >> 1; | 418 | block = block >> 1; |
388 | this_count = this_count >> 1; | 419 | this_count = this_count >> 1; |
@@ -392,7 +423,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
392 | if ((block & 3) || (rq->nr_sectors & 3)) { | 423 | if ((block & 3) || (rq->nr_sectors & 3)) { |
393 | scmd_printk(KERN_ERR, SCpnt, | 424 | scmd_printk(KERN_ERR, SCpnt, |
394 | "Bad block number requested\n"); | 425 | "Bad block number requested\n"); |
395 | return 0; | 426 | goto out; |
396 | } else { | 427 | } else { |
397 | block = block >> 2; | 428 | block = block >> 2; |
398 | this_count = this_count >> 2; | 429 | this_count = this_count >> 2; |
@@ -402,7 +433,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
402 | if ((block & 7) || (rq->nr_sectors & 7)) { | 433 | if ((block & 7) || (rq->nr_sectors & 7)) { |
403 | scmd_printk(KERN_ERR, SCpnt, | 434 | scmd_printk(KERN_ERR, SCpnt, |
404 | "Bad block number requested\n"); | 435 | "Bad block number requested\n"); |
405 | return 0; | 436 | goto out; |
406 | } else { | 437 | } else { |
407 | block = block >> 3; | 438 | block = block >> 3; |
408 | this_count = this_count >> 3; | 439 | this_count = this_count >> 3; |
@@ -410,7 +441,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
410 | } | 441 | } |
411 | if (rq_data_dir(rq) == WRITE) { | 442 | if (rq_data_dir(rq) == WRITE) { |
412 | if (!sdp->writeable) { | 443 | if (!sdp->writeable) { |
413 | return 0; | 444 | goto out; |
414 | } | 445 | } |
415 | SCpnt->cmnd[0] = WRITE_6; | 446 | SCpnt->cmnd[0] = WRITE_6; |
416 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | 447 | SCpnt->sc_data_direction = DMA_TO_DEVICE; |
@@ -419,7 +450,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
419 | SCpnt->sc_data_direction = DMA_FROM_DEVICE; | 450 | SCpnt->sc_data_direction = DMA_FROM_DEVICE; |
420 | } else { | 451 | } else { |
421 | scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags); | 452 | scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags); |
422 | return 0; | 453 | goto out; |
423 | } | 454 | } |
424 | 455 | ||
425 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, | 456 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, |
@@ -470,7 +501,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
470 | */ | 501 | */ |
471 | scmd_printk(KERN_ERR, SCpnt, | 502 | scmd_printk(KERN_ERR, SCpnt, |
472 | "FUA write on READ/WRITE(6) drive\n"); | 503 | "FUA write on READ/WRITE(6) drive\n"); |
473 | return 0; | 504 | goto out; |
474 | } | 505 | } |
475 | 506 | ||
476 | SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); | 507 | SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); |
@@ -492,16 +523,12 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
492 | SCpnt->timeout_per_command = timeout; | 523 | SCpnt->timeout_per_command = timeout; |
493 | 524 | ||
494 | /* | 525 | /* |
495 | * This is the completion routine we use. This is matched in terms | ||
496 | * of capability to this function. | ||
497 | */ | ||
498 | SCpnt->done = sd_rw_intr; | ||
499 | |||
500 | /* | ||
501 | * This indicates that the command is ready from our end to be | 526 | * This indicates that the command is ready from our end to be |
502 | * queued. | 527 | * queued. |
503 | */ | 528 | */ |
504 | return 1; | 529 | ret = BLKPREP_OK; |
530 | out: | ||
531 | return scsi_prep_return(q, rq, ret); | ||
505 | } | 532 | } |
506 | 533 | ||
507 | /** | 534 | /** |
@@ -889,13 +916,13 @@ static struct block_device_operations sd_fops = { | |||
889 | }; | 916 | }; |
890 | 917 | ||
891 | /** | 918 | /** |
892 | * sd_rw_intr - bottom half handler: called when the lower level | 919 | * sd_done - bottom half handler: called when the lower level |
893 | * driver has completed (successfully or otherwise) a scsi command. | 920 | * driver has completed (successfully or otherwise) a scsi command. |
894 | * @SCpnt: mid-level's per command structure. | 921 | * @SCpnt: mid-level's per command structure. |
895 | * | 922 | * |
896 | * Note: potentially run from within an ISR. Must not block. | 923 | * Note: potentially run from within an ISR. Must not block. |
897 | **/ | 924 | **/ |
898 | static void sd_rw_intr(struct scsi_cmnd * SCpnt) | 925 | static int sd_done(struct scsi_cmnd *SCpnt) |
899 | { | 926 | { |
900 | int result = SCpnt->result; | 927 | int result = SCpnt->result; |
901 | unsigned int xfer_size = SCpnt->request_bufflen; | 928 | unsigned int xfer_size = SCpnt->request_bufflen; |
@@ -916,7 +943,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
916 | SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt)); | 943 | SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt)); |
917 | if (sense_valid) { | 944 | if (sense_valid) { |
918 | SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, | 945 | SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, |
919 | "sd_rw_intr: sb[respc,sk,asc," | 946 | "sd_done: sb[respc,sk,asc," |
920 | "ascq]=%x,%x,%x,%x\n", | 947 | "ascq]=%x,%x,%x,%x\n", |
921 | sshdr.response_code, | 948 | sshdr.response_code, |
922 | sshdr.sense_key, sshdr.asc, | 949 | sshdr.sense_key, sshdr.asc, |
@@ -988,7 +1015,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
988 | break; | 1015 | break; |
989 | } | 1016 | } |
990 | out: | 1017 | out: |
991 | scsi_io_completion(SCpnt, good_bytes); | 1018 | return good_bytes; |
992 | } | 1019 | } |
993 | 1020 | ||
994 | static int media_not_present(struct scsi_disk *sdkp, | 1021 | static int media_not_present(struct scsi_disk *sdkp, |
@@ -1669,6 +1696,7 @@ static int sd_probe(struct device *dev) | |||
1669 | 1696 | ||
1670 | sd_revalidate_disk(gd); | 1697 | sd_revalidate_disk(gd); |
1671 | 1698 | ||
1699 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); | ||
1672 | blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush); | 1700 | blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush); |
1673 | 1701 | ||
1674 | gd->driverfs_dev = &sdp->sdev_gendev; | 1702 | gd->driverfs_dev = &sdp->sdev_gendev; |