Commit 464cf177 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

libata: always use polling SETXFER

Several people have reported LITE-ON LTR-48246S detection failed
because SETXFER fails.  It seems the device raises IRQ too early after
SETXFER.  This is controller independent.  The same problem has been
reported for different controllers.

So, now we have pata_via where the controller raises IRQ before it's
ready after SETXFER and a device which does similar thing.  This patch
makes libata always execute SETXFER via polling.  As this only happens
during EH, performance impact is nil.  Setting ATA_TFLAG_POLLING is
also moved from issue hot path to ata_dev_set_xfermode() - the only
place where SETXFER can be issued.

Note that ATA_TFLAG_POLLING applies only to drivers which implement
SFF TF interface and use libata HSM.  More advanced controllers ignore
the flag.  This doesn't matter for this fix as SFF TF controllers are
the problematic ones.
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent a862b5c8
...@@ -3933,10 +3933,13 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) ...@@ -3933,10 +3933,13 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
/* set up set-features taskfile */ /* set up set-features taskfile */
DPRINTK("set features - xfer mode\n"); DPRINTK("set features - xfer mode\n");
/* Some controllers and ATAPI devices show flaky interrupt
* behavior after setting xfer mode. Use polling instead.
*/
ata_tf_init(dev, &tf); ata_tf_init(dev, &tf);
tf.command = ATA_CMD_SET_FEATURES; tf.command = ATA_CMD_SET_FEATURES;
tf.feature = SETFEATURES_XFER; tf.feature = SETFEATURES_XFER;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING;
tf.protocol = ATA_PROT_NODATA; tf.protocol = ATA_PROT_NODATA;
tf.nsect = dev->xfer_mode; tf.nsect = dev->xfer_mode;
...@@ -5414,14 +5417,6 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ...@@ -5414,14 +5417,6 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
} }
} }
/* Some controllers show flaky interrupt behavior after
* setting xfer mode. Use polling instead.
*/
if (unlikely(qc->tf.command == ATA_CMD_SET_FEATURES &&
qc->tf.feature == SETFEATURES_XFER) &&
(ap->flags & ATA_FLAG_SETXFER_POLLING))
qc->tf.flags |= ATA_TFLAG_POLLING;
/* select the device */ /* select the device */
ata_dev_select(ap, qc->dev->devno, 1, 0); ata_dev_select(ap, qc->dev->devno, 1, 0);
......
...@@ -452,7 +452,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -452,7 +452,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Early VIA without UDMA support */ /* Early VIA without UDMA support */
static const struct ata_port_info via_mwdma_info = { static const struct ata_port_info via_mwdma_info = {
.sht = &via_sht, .sht = &via_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.port_ops = &via_port_ops .port_ops = &via_port_ops
...@@ -460,7 +460,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -460,7 +460,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Ditto with IRQ masking required */ /* Ditto with IRQ masking required */
static const struct ata_port_info via_mwdma_info_borked = { static const struct ata_port_info via_mwdma_info_borked = {
.sht = &via_sht, .sht = &via_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.port_ops = &via_port_ops_noirq, .port_ops = &via_port_ops_noirq,
...@@ -468,7 +468,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -468,7 +468,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* VIA UDMA 33 devices (and borked 66) */ /* VIA UDMA 33 devices (and borked 66) */
static const struct ata_port_info via_udma33_info = { static const struct ata_port_info via_udma33_info = {
.sht = &via_sht, .sht = &via_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.udma_mask = 0x7, .udma_mask = 0x7,
...@@ -477,7 +477,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -477,7 +477,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* VIA UDMA 66 devices */ /* VIA UDMA 66 devices */
static const struct ata_port_info via_udma66_info = { static const struct ata_port_info via_udma66_info = {
.sht = &via_sht, .sht = &via_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.udma_mask = 0x1f, .udma_mask = 0x1f,
...@@ -486,7 +486,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -486,7 +486,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* VIA UDMA 100 devices */ /* VIA UDMA 100 devices */
static const struct ata_port_info via_udma100_info = { static const struct ata_port_info via_udma100_info = {
.sht = &via_sht, .sht = &via_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.udma_mask = 0x3f, .udma_mask = 0x3f,
...@@ -495,7 +495,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -495,7 +495,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* UDMA133 with bad AST (All current 133) */ /* UDMA133 with bad AST (All current 133) */
static const struct ata_port_info via_udma133_info = { static const struct ata_port_info via_udma133_info = {
.sht = &via_sht, .sht = &via_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
.mwdma_mask = 0x07, .mwdma_mask = 0x07,
.udma_mask = 0x7f, /* FIXME: should check north bridge */ .udma_mask = 0x7f, /* FIXME: should check north bridge */
......
...@@ -171,7 +171,6 @@ enum { ...@@ -171,7 +171,6 @@ enum {
ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
* Register FIS clearing BSY */ * Register FIS clearing BSY */
ATA_FLAG_DEBUGMSG = (1 << 13), ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
......
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