diff options
author | Jeff Garzik <jeff@garzik.org> | 2008-02-28 15:43:48 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-03-05 07:53:06 -0500 |
commit | a878539ef994787c447a98c2e3ba0fe3dad984ec (patch) | |
tree | 3c2b16121143c4dad805b048b2cee5d4c410384a /drivers/ata/ahci.c | |
parent | 6ddd68615ae9b21096545d7d6ab0f04113ae8b42 (diff) |
ahci: work around ATI SB600 h/w quirk
This addresses the recent ATI SB600 errata, where the hardware does
not like 256-length PRD entries during FPDMA (aka NCQ).
It hurts performance on SB600, but it is more important to get a
correct patch eliminating the data corruption/lockups, and then later
on tune for performance.
We simply limit each command to a maximum of 255 sectors, on SB600.
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 1db93b619074..8a49835bd0f8 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -186,6 +186,7 @@ enum { | |||
186 | AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ | 186 | AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ |
187 | AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ | 187 | AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ |
188 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ | 188 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ |
189 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ | ||
189 | 190 | ||
190 | /* ap->flags bits */ | 191 | /* ap->flags bits */ |
191 | 192 | ||
@@ -255,6 +256,7 @@ static void ahci_vt8251_error_handler(struct ata_port *ap); | |||
255 | static void ahci_p5wdh_error_handler(struct ata_port *ap); | 256 | static void ahci_p5wdh_error_handler(struct ata_port *ap); |
256 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); | 257 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); |
257 | static int ahci_port_resume(struct ata_port *ap); | 258 | static int ahci_port_resume(struct ata_port *ap); |
259 | static void ahci_dev_config(struct ata_device *dev); | ||
258 | static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); | 260 | static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); |
259 | static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, | 261 | static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, |
260 | u32 opts); | 262 | u32 opts); |
@@ -294,6 +296,8 @@ static const struct ata_port_operations ahci_ops = { | |||
294 | .check_altstatus = ahci_check_status, | 296 | .check_altstatus = ahci_check_status, |
295 | .dev_select = ata_noop_dev_select, | 297 | .dev_select = ata_noop_dev_select, |
296 | 298 | ||
299 | .dev_config = ahci_dev_config, | ||
300 | |||
297 | .tf_read = ahci_tf_read, | 301 | .tf_read = ahci_tf_read, |
298 | 302 | ||
299 | .qc_defer = sata_pmp_qc_defer_cmd_switch, | 303 | .qc_defer = sata_pmp_qc_defer_cmd_switch, |
@@ -425,7 +429,7 @@ static const struct ata_port_info ahci_port_info[] = { | |||
425 | /* board_ahci_sb600 */ | 429 | /* board_ahci_sb600 */ |
426 | { | 430 | { |
427 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | | 431 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | |
428 | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_PMP), | 432 | AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), |
429 | .flags = AHCI_FLAG_COMMON, | 433 | .flags = AHCI_FLAG_COMMON, |
430 | .link_flags = AHCI_LFLAG_COMMON, | 434 | .link_flags = AHCI_LFLAG_COMMON, |
431 | .pio_mask = 0x1f, /* pio0-4 */ | 435 | .pio_mask = 0x1f, /* pio0-4 */ |
@@ -1176,6 +1180,14 @@ static void ahci_init_controller(struct ata_host *host) | |||
1176 | VPRINTK("HOST_CTL 0x%x\n", tmp); | 1180 | VPRINTK("HOST_CTL 0x%x\n", tmp); |
1177 | } | 1181 | } |
1178 | 1182 | ||
1183 | static void ahci_dev_config(struct ata_device *dev) | ||
1184 | { | ||
1185 | struct ahci_host_priv *hpriv = dev->link->ap->host->private_data; | ||
1186 | |||
1187 | if (hpriv->flags & AHCI_HFLAG_SECT255) | ||
1188 | dev->max_sectors = 255; | ||
1189 | } | ||
1190 | |||
1179 | static unsigned int ahci_dev_classify(struct ata_port *ap) | 1191 | static unsigned int ahci_dev_classify(struct ata_port *ap) |
1180 | { | 1192 | { |
1181 | void __iomem *port_mmio = ahci_port_base(ap); | 1193 | void __iomem *port_mmio = ahci_port_base(ap); |