aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-08-06 00:42:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-06 00:42:21 -0400
commit18351070b86d155713cf790b26af4f21b1fd0b29 (patch)
tree66e98f59de072733af7ae65cebf135c37caab249 /drivers/scsi
parente63e03273b89f7248baa56cf242474f661e776e1 (diff)
Re-introduce "[SCSI] extend the last_sector_bug flag to cover more sectors"
This re-introduces commit 2b142900784c6e38c8d39fa57d5f95ef08e735d8, which was reverted due to the regression it caused by commit fca082c9f1e11ec07efa8d2f9f13688521253f36. That regression was not root-caused by the original commit, it was just uncovered by it, and the real fix was done by Alan Stern in commit 580da34847488b404218d1d7f53b156f245f5555 ("Fix USB storage hang on command abort"). We can thus re-introduce the change that was confirmed by Alan Jenkins to be still required by his odd card reader. Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sd.c21
-rw-r--r--drivers/scsi/sd.h6
2 files changed, 21 insertions, 6 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8e08d51a0f05..e5e7d7856454 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -375,6 +375,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
375 struct gendisk *disk = rq->rq_disk; 375 struct gendisk *disk = rq->rq_disk;
376 struct scsi_disk *sdkp; 376 struct scsi_disk *sdkp;
377 sector_t block = rq->sector; 377 sector_t block = rq->sector;
378 sector_t threshold;
378 unsigned int this_count = rq->nr_sectors; 379 unsigned int this_count = rq->nr_sectors;
379 unsigned int timeout = sdp->timeout; 380 unsigned int timeout = sdp->timeout;
380 int ret; 381 int ret;
@@ -422,13 +423,21 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
422 } 423 }
423 424
424 /* 425 /*
425 * Some devices (some sdcards for one) don't like it if the 426 * Some SD card readers can't handle multi-sector accesses which touch
426 * last sector gets read in a larger then 1 sector read. 427 * the last one or two hardware sectors. Split accesses as needed.
427 */ 428 */
428 if (unlikely(sdp->last_sector_bug && 429 threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS *
429 rq->nr_sectors > sdp->sector_size / 512 && 430 (sdp->sector_size / 512);
430 block + this_count == get_capacity(disk))) 431
431 this_count -= sdp->sector_size / 512; 432 if (unlikely(sdp->last_sector_bug && block + this_count > threshold)) {
433 if (block < threshold) {
434 /* Access up to the threshold but not beyond */
435 this_count = threshold - block;
436 } else {
437 /* Access only a single hardware sector */
438 this_count = sdp->sector_size / 512;
439 }
440 }
432 441
433 SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", 442 SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
434 (unsigned long long)block)); 443 (unsigned long long)block));
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 550b2f70a1f8..95b9f06534d5 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -31,6 +31,12 @@
31 */ 31 */
32#define SD_BUF_SIZE 512 32#define SD_BUF_SIZE 512
33 33
34/*
35 * Number of sectors at the end of the device to avoid multi-sector
36 * accesses to in the case of last_sector_bug
37 */
38#define SD_LAST_BUGGY_SECTORS 8
39
34struct scsi_disk { 40struct scsi_disk {
35 struct scsi_driver *driver; /* always &sd_template */ 41 struct scsi_driver *driver; /* always &sd_template */
36 struct scsi_device *device; 42 struct scsi_device *device;