Commit 18351070 authored by Linus Torvalds's avatar Linus Torvalds

Re-introduce "[SCSI] extend the last_sector_bug flag to cover more sectors"

This re-introduces commit 2b142900,
which was reverted due to the regression it caused by commit
fca082c9.

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
580da348 ("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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e63e0327
...@@ -375,6 +375,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) ...@@ -375,6 +375,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
struct gendisk *disk = rq->rq_disk; struct gendisk *disk = rq->rq_disk;
struct scsi_disk *sdkp; struct scsi_disk *sdkp;
sector_t block = rq->sector; sector_t block = rq->sector;
sector_t threshold;
unsigned int this_count = rq->nr_sectors; unsigned int this_count = rq->nr_sectors;
unsigned int timeout = sdp->timeout; unsigned int timeout = sdp->timeout;
int ret; int ret;
...@@ -422,13 +423,21 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) ...@@ -422,13 +423,21 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
} }
/* /*
* Some devices (some sdcards for one) don't like it if the * Some SD card readers can't handle multi-sector accesses which touch
* last sector gets read in a larger then 1 sector read. * the last one or two hardware sectors. Split accesses as needed.
*/ */
if (unlikely(sdp->last_sector_bug && threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS *
rq->nr_sectors > sdp->sector_size / 512 && (sdp->sector_size / 512);
block + this_count == get_capacity(disk)))
this_count -= sdp->sector_size / 512; if (unlikely(sdp->last_sector_bug && block + this_count > threshold)) {
if (block < threshold) {
/* Access up to the threshold but not beyond */
this_count = threshold - block;
} else {
/* Access only a single hardware sector */
this_count = sdp->sector_size / 512;
}
}
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
(unsigned long long)block)); (unsigned long long)block));
......
...@@ -31,6 +31,12 @@ ...@@ -31,6 +31,12 @@
*/ */
#define SD_BUF_SIZE 512 #define SD_BUF_SIZE 512
/*
* Number of sectors at the end of the device to avoid multi-sector
* accesses to in the case of last_sector_bug
*/
#define SD_LAST_BUGGY_SECTORS 8
struct scsi_disk { struct scsi_disk {
struct scsi_driver *driver; /* always &sd_template */ struct scsi_driver *driver; /* always &sd_template */
struct scsi_device *device; struct scsi_device *device;
......
...@@ -140,7 +140,8 @@ struct scsi_device { ...@@ -140,7 +140,8 @@ struct scsi_device {
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */ unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */
unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */ unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
unsigned last_sector_bug:1; /* Always read last sector in a 1 sector read */ unsigned last_sector_bug:1; /* do not use multisector accesses on
SD_LAST_BUGGY_SECTORS */
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
struct list_head event_list; /* asserted events */ struct list_head event_list; /* asserted events */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment