mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
sata_mv: workaround for multi_count errata sata24
Workaround for errata SATA#24 in sata_mv. This errata affects WRITE_MULTI* commands when the device multi_count produces a DRQ block size >= 4Kbytes. We work around it here by converting such operations into ordinary PIO_WRITEs instead. Note that this might result in a PIO FUA write unavoidably being converted into a non-FUA write. In practice, any system using FUA is also going to be using DMA rather than PIO, so this shouldn't affect anyone in the real world. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
8d2b450d0f
commit
299b3f8df9
1 changed files with 42 additions and 2 deletions
|
@ -1881,6 +1881,39 @@ static u8 mv_bmdma_status(struct ata_port *ap)
|
|||
return status;
|
||||
}
|
||||
|
||||
static void mv_rw_multi_errata_sata24(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_taskfile *tf = &qc->tf;
|
||||
/*
|
||||
* Workaround for 88SX60x1 FEr SATA#24.
|
||||
*
|
||||
* Chip may corrupt WRITEs if multi_count >= 4kB.
|
||||
* Note that READs are unaffected.
|
||||
*
|
||||
* It's not clear if this errata really means "4K bytes",
|
||||
* or if it always happens for multi_count > 7
|
||||
* regardless of device sector_size.
|
||||
*
|
||||
* So, for safety, any write with multi_count > 7
|
||||
* gets converted here into a regular PIO write instead:
|
||||
*/
|
||||
if ((tf->flags & ATA_TFLAG_WRITE) && is_multi_taskfile(tf)) {
|
||||
if (qc->dev->multi_count > 7) {
|
||||
switch (tf->command) {
|
||||
case ATA_CMD_WRITE_MULTI:
|
||||
tf->command = ATA_CMD_PIO_WRITE;
|
||||
break;
|
||||
case ATA_CMD_WRITE_MULTI_FUA_EXT:
|
||||
tf->flags &= ~ATA_TFLAG_FUA; /* ugh */
|
||||
/* fall through */
|
||||
case ATA_CMD_WRITE_MULTI_EXT:
|
||||
tf->command = ATA_CMD_PIO_WRITE_EXT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mv_qc_prep - Host specific command preparation.
|
||||
* @qc: queued command to prepare
|
||||
|
@ -1902,9 +1935,16 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
|
|||
u16 flags = 0;
|
||||
unsigned in_index;
|
||||
|
||||
if ((tf->protocol != ATA_PROT_DMA) &&
|
||||
(tf->protocol != ATA_PROT_NCQ))
|
||||
switch (tf->protocol) {
|
||||
case ATA_PROT_DMA:
|
||||
case ATA_PROT_NCQ:
|
||||
break; /* continue below */
|
||||
case ATA_PROT_PIO:
|
||||
mv_rw_multi_errata_sata24(qc);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill in command request block
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue