X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fsd.c;h=e5e7d78564545543925fc6136c6e7c7fc994c028;hb=04489eeb02a40bc15029886cef7285ada3ab0de6;hp=8e08d51a0f0531d8bf661dc0d3bf8f822d35c357;hpb=2acb802b0c5485aedb46e23b2b45e49573454c09;p=linux-2.6 diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8e08d51a0f..e5e7d78564 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) struct gendisk *disk = rq->rq_disk; struct scsi_disk *sdkp; sector_t block = rq->sector; + sector_t threshold; unsigned int this_count = rq->nr_sectors; unsigned int timeout = sdp->timeout; int ret; @@ -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 - * last sector gets read in a larger then 1 sector read. + * Some SD card readers can't handle multi-sector accesses which touch + * the last one or two hardware sectors. Split accesses as needed. */ - 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; + threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS * + (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", (unsigned long long)block));