diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-26 02:19:08 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-26 02:19:08 +0100 |
commit | 9b73e76f3cf63379dcf45fcd4f112f5812418d0a (patch) | |
tree | 4e6bef87cd0cd6d848fc39a5ae25b981dbbe035b /drivers/scsi/sd.c | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 (diff) | |
parent | [SCSI] usbstorage: use last_sector_bug flag universally (diff) | |
download | linux-9b73e76f3cf63379dcf45fcd4f112f5812418d0a.tar.xz linux-9b73e76f3cf63379dcf45fcd4f112f5812418d0a.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (200 commits)
[SCSI] usbstorage: use last_sector_bug flag universally
[SCSI] libsas: abstract STP task status into a function
[SCSI] ultrastor: clean up inline asm warnings
[SCSI] aic7xxx: fix firmware build
[SCSI] aacraid: fib context lock for management ioctls
[SCSI] ch: remove forward declarations
[SCSI] ch: fix device minor number management bug
[SCSI] ch: handle class_device_create failure properly
[SCSI] NCR5380: fix section mismatch
[SCSI] sg: fix /proc/scsi/sg/devices when no SCSI devices
[SCSI] IB/iSER: add logical unit reset support
[SCSI] don't use __GFP_DMA for sense buffers if not required
[SCSI] use dynamically allocated sense buffer
[SCSI] scsi.h: add macro for enclosure bit of inquiry data
[SCSI] sd: add fix for devices with last sector access problems
[SCSI] fix pcmcia compile problem
[SCSI] aacraid: add Voodoo Lite class of cards.
[SCSI] aacraid: add new driver features flags
[SCSI] qla2xxx: Update version number to 8.02.00-k7.
[SCSI] qla2xxx: Issue correct MBC_INITIALIZE_FIRMWARE command.
...
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a69b155f39a2..24eba3118b5a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -395,6 +395,15 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) goto out; } + /* + * Some devices (some sdcards for one) don't like it if the + * last sector gets read in a larger then 1 sector read. + */ + if (unlikely(sdp->last_sector_bug && + rq->nr_sectors > sdp->sector_size / 512 && + block + this_count == get_capacity(disk))) + this_count -= sdp->sector_size / 512; + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", (unsigned long long)block)); @@ -736,6 +745,7 @@ static int sd_media_changed(struct gendisk *disk) { struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; + struct scsi_sense_hdr *sshdr = NULL; int retval; SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n")); @@ -749,8 +759,11 @@ static int sd_media_changed(struct gendisk *disk) * can deal with it then. It is only because of unrecoverable errors * that we would ever take a device offline in the first place. */ - if (!scsi_device_online(sdp)) - goto not_present; + if (!scsi_device_online(sdp)) { + set_media_not_present(sdkp); + retval = 1; + goto out; + } /* * Using TEST_UNIT_READY enables differentiation between drive with @@ -762,8 +775,12 @@ static int sd_media_changed(struct gendisk *disk) * sd_revalidate() is called. */ retval = -ENODEV; - if (scsi_block_when_processing_errors(sdp)) - retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES); + + if (scsi_block_when_processing_errors(sdp)) { + sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); + retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, + sshdr); + } /* * Unable to test, unit probably not ready. This usually @@ -771,8 +788,13 @@ static int sd_media_changed(struct gendisk *disk) * and we will figure it out later once the drive is * available again. */ - if (retval) - goto not_present; + if (retval || (scsi_sense_valid(sshdr) && + /* 0x3a is medium not present */ + sshdr->asc == 0x3a)) { + set_media_not_present(sdkp); + retval = 1; + goto out; + } /* * For removable scsi disk we have to recognise the presence @@ -783,12 +805,12 @@ static int sd_media_changed(struct gendisk *disk) retval = sdp->changed; sdp->changed = 0; - +out: + if (retval != sdkp->previous_state) + sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); + sdkp->previous_state = retval; + kfree(sshdr); return retval; - -not_present: - set_media_not_present(sdkp); - return 1; } static int sd_sync_cache(struct scsi_disk *sdkp) |