diff options
Diffstat (limited to 'drivers/scsi/sd.c')
| -rw-r--r-- | drivers/scsi/sd.c | 63 |
1 files changed, 16 insertions, 47 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4c5127ed379c..930db398d107 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <linux/blkpg.h> | 49 | #include <linux/blkpg.h> |
| 50 | #include <linux/kref.h> | 50 | #include <linux/kref.h> |
| 51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
| 52 | #include <linux/mutex.h> | ||
| 52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
| 53 | 54 | ||
| 54 | #include <scsi/scsi.h> | 55 | #include <scsi/scsi.h> |
| @@ -111,7 +112,7 @@ static DEFINE_SPINLOCK(sd_index_lock); | |||
| 111 | /* This semaphore is used to mediate the 0->1 reference get in the | 112 | /* This semaphore is used to mediate the 0->1 reference get in the |
| 112 | * face of object destruction (i.e. we can't allow a get on an | 113 | * face of object destruction (i.e. we can't allow a get on an |
| 113 | * object after last put) */ | 114 | * object after last put) */ |
| 114 | static DECLARE_MUTEX(sd_ref_sem); | 115 | static DEFINE_MUTEX(sd_ref_mutex); |
| 115 | 116 | ||
| 116 | static int sd_revalidate_disk(struct gendisk *disk); | 117 | static int sd_revalidate_disk(struct gendisk *disk); |
| 117 | static void sd_rw_intr(struct scsi_cmnd * SCpnt); | 118 | static void sd_rw_intr(struct scsi_cmnd * SCpnt); |
| @@ -193,9 +194,9 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) | |||
| 193 | { | 194 | { |
| 194 | struct scsi_disk *sdkp; | 195 | struct scsi_disk *sdkp; |
| 195 | 196 | ||
| 196 | down(&sd_ref_sem); | 197 | mutex_lock(&sd_ref_mutex); |
| 197 | sdkp = __scsi_disk_get(disk); | 198 | sdkp = __scsi_disk_get(disk); |
| 198 | up(&sd_ref_sem); | 199 | mutex_unlock(&sd_ref_mutex); |
| 199 | return sdkp; | 200 | return sdkp; |
| 200 | } | 201 | } |
| 201 | 202 | ||
| @@ -203,11 +204,11 @@ static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev) | |||
| 203 | { | 204 | { |
| 204 | struct scsi_disk *sdkp; | 205 | struct scsi_disk *sdkp; |
| 205 | 206 | ||
| 206 | down(&sd_ref_sem); | 207 | mutex_lock(&sd_ref_mutex); |
| 207 | sdkp = dev_get_drvdata(dev); | 208 | sdkp = dev_get_drvdata(dev); |
| 208 | if (sdkp) | 209 | if (sdkp) |
| 209 | sdkp = __scsi_disk_get(sdkp->disk); | 210 | sdkp = __scsi_disk_get(sdkp->disk); |
| 210 | up(&sd_ref_sem); | 211 | mutex_unlock(&sd_ref_mutex); |
| 211 | return sdkp; | 212 | return sdkp; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| @@ -215,10 +216,10 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
| 215 | { | 216 | { |
| 216 | struct scsi_device *sdev = sdkp->device; | 217 | struct scsi_device *sdev = sdkp->device; |
| 217 | 218 | ||
| 218 | down(&sd_ref_sem); | 219 | mutex_lock(&sd_ref_mutex); |
| 219 | kref_put(&sdkp->kref, scsi_disk_release); | 220 | kref_put(&sdkp->kref, scsi_disk_release); |
| 220 | scsi_device_put(sdev); | 221 | scsi_device_put(sdev); |
| 221 | up(&sd_ref_sem); | 222 | mutex_unlock(&sd_ref_mutex); |
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | /** | 225 | /** |
| @@ -231,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
| 231 | **/ | 232 | **/ |
| 232 | static int sd_init_command(struct scsi_cmnd * SCpnt) | 233 | static int sd_init_command(struct scsi_cmnd * SCpnt) |
| 233 | { | 234 | { |
| 234 | unsigned int this_count, timeout; | ||
| 235 | struct gendisk *disk; | ||
| 236 | sector_t block; | ||
| 237 | struct scsi_device *sdp = SCpnt->device; | 235 | struct scsi_device *sdp = SCpnt->device; |
| 238 | struct request *rq = SCpnt->request; | 236 | struct request *rq = SCpnt->request; |
| 239 | 237 | struct gendisk *disk = rq->rq_disk; | |
| 240 | timeout = sdp->timeout; | 238 | sector_t block = rq->sector; |
| 241 | 239 | unsigned int this_count = SCpnt->request_bufflen >> 9; | |
| 242 | /* | 240 | unsigned int timeout = sdp->timeout; |
| 243 | * SG_IO from block layer already setup, just copy cdb basically | ||
| 244 | */ | ||
| 245 | if (blk_pc_request(rq)) { | ||
| 246 | scsi_setup_blk_pc_cmnd(SCpnt); | ||
| 247 | if (rq->timeout) | ||
| 248 | timeout = rq->timeout; | ||
| 249 | |||
| 250 | goto queue; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * we only do REQ_CMD and REQ_BLOCK_PC | ||
| 255 | */ | ||
| 256 | if (!blk_fs_request(rq)) | ||
| 257 | return 0; | ||
| 258 | |||
| 259 | disk = rq->rq_disk; | ||
| 260 | block = rq->sector; | ||
| 261 | this_count = SCpnt->request_bufflen >> 9; | ||
| 262 | 241 | ||
| 263 | SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " | 242 | SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " |
| 264 | "count=%d\n", disk->disk_name, | 243 | "count=%d\n", disk->disk_name, |
| @@ -401,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
| 401 | SCpnt->transfersize = sdp->sector_size; | 380 | SCpnt->transfersize = sdp->sector_size; |
| 402 | SCpnt->underflow = this_count << 9; | 381 | SCpnt->underflow = this_count << 9; |
| 403 | SCpnt->allowed = SD_MAX_RETRIES; | 382 | SCpnt->allowed = SD_MAX_RETRIES; |
| 404 | |||
| 405 | queue: | ||
| 406 | SCpnt->timeout_per_command = timeout; | 383 | SCpnt->timeout_per_command = timeout; |
| 407 | 384 | ||
| 408 | /* | 385 | /* |
| @@ -836,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
| 836 | relatively rare error condition, no care is taken to avoid | 813 | relatively rare error condition, no care is taken to avoid |
| 837 | unnecessary additional work such as memcpy's that could be avoided. | 814 | unnecessary additional work such as memcpy's that could be avoided. |
| 838 | */ | 815 | */ |
| 839 | 816 | if (driver_byte(result) != 0 && | |
| 840 | /* | ||
| 841 | * If SG_IO from block layer then set good_bytes to stop retries; | ||
| 842 | * else if errors, check them, and if necessary prepare for | ||
| 843 | * (partial) retries. | ||
| 844 | */ | ||
| 845 | if (blk_pc_request(SCpnt->request)) | ||
| 846 | good_bytes = this_count; | ||
| 847 | else if (driver_byte(result) != 0 && | ||
| 848 | sense_valid && !sense_deferred) { | 817 | sense_valid && !sense_deferred) { |
| 849 | switch (sshdr.sense_key) { | 818 | switch (sshdr.sense_key) { |
| 850 | case MEDIUM_ERROR: | 819 | case MEDIUM_ERROR: |
| @@ -1635,10 +1604,10 @@ static int sd_remove(struct device *dev) | |||
| 1635 | del_gendisk(sdkp->disk); | 1604 | del_gendisk(sdkp->disk); |
| 1636 | sd_shutdown(dev); | 1605 | sd_shutdown(dev); |
| 1637 | 1606 | ||
| 1638 | down(&sd_ref_sem); | 1607 | mutex_lock(&sd_ref_mutex); |
| 1639 | dev_set_drvdata(dev, NULL); | 1608 | dev_set_drvdata(dev, NULL); |
| 1640 | kref_put(&sdkp->kref, scsi_disk_release); | 1609 | kref_put(&sdkp->kref, scsi_disk_release); |
| 1641 | up(&sd_ref_sem); | 1610 | mutex_unlock(&sd_ref_mutex); |
| 1642 | 1611 | ||
| 1643 | return 0; | 1612 | return 0; |
| 1644 | } | 1613 | } |
| @@ -1647,7 +1616,7 @@ static int sd_remove(struct device *dev) | |||
| 1647 | * scsi_disk_release - Called to free the scsi_disk structure | 1616 | * scsi_disk_release - Called to free the scsi_disk structure |
| 1648 | * @kref: pointer to embedded kref | 1617 | * @kref: pointer to embedded kref |
| 1649 | * | 1618 | * |
| 1650 | * sd_ref_sem must be held entering this routine. Because it is | 1619 | * sd_ref_mutex must be held entering this routine. Because it is |
| 1651 | * called on last put, you should always use the scsi_disk_get() | 1620 | * called on last put, you should always use the scsi_disk_get() |
| 1652 | * scsi_disk_put() helpers which manipulate the semaphore directly | 1621 | * scsi_disk_put() helpers which manipulate the semaphore directly |
| 1653 | * and never do a direct kref_put(). | 1622 | * and never do a direct kref_put(). |
