Commit 48c1a573 authored by Jeff Garzik's avatar Jeff Garzik

[libata sata_sil] Re-fix mod15write bug

Certain early SATA drives have problems with write requests whose
length satisfy the equation "sectors % 15 == 1", on the SiI 3112.
Other drives, and other SiI controllers, are not affected.

The fix for this problem is to avoid such requests, in one of three
ways, for the affect drive+controller combos:
1) Limit all writes to 15 sectors
2) Use block layer features to avoid creating requests whose
   length satisfies the above equation.
3) When a request satisfies the above equation, split the request
   into two writes, neither of which satisfies the equation.

I chose fix #1, the most simple to implement.  After discussion with
Silicon Image and others regarding the impact of this fix, I have
decided to remain with fix #1, and will not be implementing a
"better fix".  This means that the affected SATA drives will see
decreased performance, but set of affected drives is small and will
never grow larger.

Further, the complexity of implementing solution #2 or
solution #3 is rather large.

When implementing lba48 'large request' support, I unintentionally
broke the fix for these affected drives.  Kudos to Ricky Beam for
noticing this.

This change restores the fix, by adding a flag ATA_DFLAG_LOCK_SECTORS
to indicate that the max_sectors value set by the low-level driver
should never be changed.
parent 3e13e3b2
......@@ -182,7 +182,8 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
* 65534 when Jens Axboe's patch for dynamically
* determining max_sectors is merged.
*/
if (dev->flags & ATA_DFLAG_LBA48) {
if ((dev->flags & ATA_DFLAG_LBA48) &&
((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) {
sdev->host->max_sectors = 2048;
blk_queue_max_sectors(sdev->request_queue, 2048);
}
......
......@@ -302,6 +302,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
ap->id, dev->devno);
ap->host->max_sectors = 15;
ap->host->hostt->max_sectors = 15;
dev->flags |= ATA_DFLAG_LOCK_SECTORS;
return;
}
......
......@@ -91,6 +91,7 @@ enum {
ATA_DFLAG_MASTER = (1 << 2), /* is device 0? */
ATA_DFLAG_WCACHE = (1 << 3), /* has write cache we can
* (hopefully) flush? */
ATA_DFLAG_LOCK_SECTORS = (1 << 4), /* don't adjust max_sectors */
ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */
......
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