summaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2009-03-27 16:14:38 +0100
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2009-03-27 16:14:38 +0100
commitb92efa9abffc4a634cd2e7a0f81f8aa6310d67c9 (patch)
tree9847508d9b8d4e585f90db4a453bfbc3700c997e /drivers/ata
parenta16fffdd8eb95ebab7dc22414896fe6493951e0e (diff)
parentbe0ea69674ed95e1e98cb3687a241badc756d228 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into avr32-arch
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/Kconfig15
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci.c96
-rw-r--r--drivers/ata/ata_generic.c4
-rw-r--r--drivers/ata/ata_piix.c131
-rw-r--r--drivers/ata/libata-core.c197
-rw-r--r--drivers/ata/libata-eh.c113
-rw-r--r--drivers/ata/libata-pmp.c2
-rw-r--r--drivers/ata/libata-scsi.c38
-rw-r--r--drivers/ata/libata-sff.c137
-rw-r--r--drivers/ata/libata.h6
-rw-r--r--drivers/ata/pata_acpi.c6
-rw-r--r--drivers/ata/pata_ali.c56
-rw-r--r--drivers/ata/pata_amd.c146
-rw-r--r--drivers/ata/pata_artop.c49
-rw-r--r--drivers/ata/pata_at32.c4
-rw-r--r--drivers/ata/pata_atiixp.c38
-rw-r--r--drivers/ata/pata_bf54x.c2
-rw-r--r--drivers/ata/pata_cmd640.c2
-rw-r--r--drivers/ata/pata_cmd64x.c24
-rw-r--r--drivers/ata/pata_cs5520.c2
-rw-r--r--drivers/ata/pata_cs5530.c8
-rw-r--r--drivers/ata/pata_cs5535.c4
-rw-r--r--drivers/ata/pata_cs5536.c4
-rw-r--r--drivers/ata/pata_cypress.c4
-rw-r--r--drivers/ata/pata_efar.c6
-rw-r--r--drivers/ata/pata_hpt366.c4
-rw-r--r--drivers/ata/pata_hpt37x.c28
-rw-r--r--drivers/ata/pata_hpt3x2n.c4
-rw-r--r--drivers/ata/pata_hpt3x3.c6
-rw-r--r--drivers/ata/pata_icside.c4
-rw-r--r--drivers/ata/pata_isapnp.c14
-rw-r--r--drivers/ata/pata_it8213.c4
-rw-r--r--drivers/ata/pata_it821x.c19
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c2
-rw-r--r--drivers/ata/pata_jmicron.c4
-rw-r--r--drivers/ata/pata_legacy.c9
-rw-r--r--drivers/ata/pata_marvell.c8
-rw-r--r--drivers/ata/pata_mpc52xx.c4
-rw-r--r--drivers/ata/pata_mpiix.c2
-rw-r--r--drivers/ata/pata_netcell.c4
-rw-r--r--drivers/ata/pata_ninja32.c2
-rw-r--r--drivers/ata/pata_ns87410.c2
-rw-r--r--drivers/ata/pata_ns87415.c8
-rw-r--r--drivers/ata/pata_octeon_cf.c965
-rw-r--r--drivers/ata/pata_oldpiix.c4
-rw-r--r--drivers/ata/pata_opti.c2
-rw-r--r--drivers/ata/pata_optidma.c10
-rw-r--r--drivers/ata/pata_pcmcia.c36
-rw-r--r--drivers/ata/pata_pdc2027x.c12
-rw-r--r--drivers/ata/pata_pdc202xx_old.c12
-rw-r--r--drivers/ata/pata_qdi.c6
-rw-r--r--drivers/ata/pata_radisys.c6
-rw-r--r--drivers/ata/pata_rb532_cf.c66
-rw-r--r--drivers/ata/pata_rz1000.c2
-rw-r--r--drivers/ata/pata_sc1200.c35
-rw-r--r--drivers/ata/pata_scc.c4
-rw-r--r--drivers/ata/pata_sch.c6
-rw-r--r--drivers/ata/pata_serverworks.c20
-rw-r--r--drivers/ata/pata_sil680.c8
-rw-r--r--drivers/ata/pata_sis.c32
-rw-r--r--drivers/ata/pata_sl82c105.c6
-rw-r--r--drivers/ata/pata_triflex.c4
-rw-r--r--drivers/ata/pata_via.c50
-rw-r--r--drivers/ata/pata_winbond.c2
-rw-r--r--drivers/ata/pdc_adma.c4
-rw-r--r--drivers/ata/sata_fsl.c6
-rw-r--r--drivers/ata/sata_inic162x.c4
-rw-r--r--drivers/ata/sata_mv.c931
-rw-r--r--drivers/ata/sata_nv.c98
-rw-r--r--drivers/ata/sata_promise.c30
-rw-r--r--drivers/ata/sata_qstor.c3
-rw-r--r--drivers/ata/sata_sil.c55
-rw-r--r--drivers/ata/sata_sil24.c18
-rw-r--r--drivers/ata/sata_sis.c4
-rw-r--r--drivers/ata/sata_svw.c16
-rw-r--r--drivers/ata/sata_sx4.c4
-rw-r--r--drivers/ata/sata_uli.c2
-rw-r--r--drivers/ata/sata_via.c18
-rw-r--r--drivers/ata/sata_vsc.c7
80 files changed, 2927 insertions, 784 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 1a7be96d627..0bcf2646467 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -112,11 +112,11 @@ config ATA_PIIX
If unsure, say N.
config SATA_MV
- tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ tristate "Marvell SATA support"
help
This option enables support for the Marvell Serial ATA family.
- Currently supports 88SX[56]0[48][01] chips.
+ Currently supports 88SX[56]0[48][01] PCI(-X) chips,
+ as well as the newer [67]042 PCI-X/PCIe and SOC devices.
If unsure, say N.
@@ -698,6 +698,15 @@ config PATA_IXP4XX_CF
If unsure, say N.
+config PATA_OCTEON_CF
+ tristate "OCTEON Boot Bus Compact Flash support"
+ depends on CPU_CAVIUM_OCTEON
+ help
+ This option enables a polled compact flash driver for use with
+ compact flash cards attached to the OCTEON boot bus.
+
+ If unsure, say N.
+
config PATA_SCC
tristate "Toshiba's Cell Reference Set IDE support"
depends on PCI && PPC_CELLEB
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 674965fa326..7f1ecf99528 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_SCH) += pata_sch.o
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
+obj-$(CONFIG_PATA_OCTEON_CF) += pata_octeon_cf.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 96039671e3b..788bba2b1e1 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -61,9 +61,14 @@
#define EM_MSG_LED_VALUE_ON 0x00010000
static int ahci_skip_host_reset;
+static int ahci_ignore_sss;
+
module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
+module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
+MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
+
static int ahci_enable_alpm(struct ata_port *ap,
enum link_pm policy);
static void ahci_disable_alpm(struct ata_port *ap);
@@ -399,7 +404,7 @@ static const struct ata_port_info ahci_port_info[] = {
/* board_ahci */
{
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
@@ -407,7 +412,7 @@ static const struct ata_port_info ahci_port_info[] = {
{
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_vt8251_ops,
},
@@ -415,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = {
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
@@ -425,7 +430,7 @@ static const struct ata_port_info ahci_port_info[] = {
AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
AHCI_HFLAG_SECT255),
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_sb600_ops,
},
@@ -435,7 +440,7 @@ static const struct ata_port_info ahci_port_info[] = {
AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
@@ -443,7 +448,7 @@ static const struct ata_port_info ahci_port_info[] = {
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_sb600_ops,
},
@@ -451,7 +456,7 @@ static const struct ata_port_info ahci_port_info[] = {
{
AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
@@ -459,7 +464,7 @@ static const struct ata_port_info ahci_port_info[] = {
{
AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
.flags = AHCI_FLAG_COMMON,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
@@ -577,18 +582,18 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
- { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */
- { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */
+ { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */
+ { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */
/* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
@@ -1343,7 +1348,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
writel(message[1], mmio + hpriv->em_loc+4);
/* save off new led state for port/slot */
- emp->led_state = message[1];
+ emp->led_state = state;
/*
* tell hardware to transmit the message
@@ -2548,6 +2553,41 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
}
}
+static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
+{
+ static const struct dmi_system_id broken_systems[] = {
+ {
+ .ident = "HP Compaq nx6310",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x1FUL,
+ },
+ {
+ .ident = "HP Compaq 6720s",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x1FUL,
+ },
+
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+ if (dmi) {
+ unsigned long slot = (unsigned long)dmi->driver_data;
+ /* apply the quirk only to on-board controllers */
+ return slot == PCI_SLOT(pdev->devfn);
+ }
+
+ return false;
+}
+
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
@@ -2616,8 +2656,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
- if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
- pci_intx(pdev, 1);
+ if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
+ pci_enable_msi(pdev);
/* save initial config */
ahci_save_initial_config(pdev, hpriv);
@@ -2647,6 +2687,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
+ if (ahci_broken_system_poweroff(pdev)) {
+ pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
+ dev_info(&pdev->dev,
+ "quirky BIOS, skipping spindown on poweroff\n");
+ }
+
/* CAP.NP sometimes indicate the index of the last enabled
* port, at other times, that of the last possible port, so
* determining the maximum port number requires looking at
@@ -2660,8 +2706,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->iomap = pcim_iomap_table(pdev);
host->private_data = hpriv;
- if (!(hpriv->cap & HOST_CAP_SSS))
+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
host->flags |= ATA_HOST_PARALLEL_SCAN;
+ else
+ printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
if (pi.flags & ATA_FLAG_EM)
ahci_reset_em(host);
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index dc48a6398ab..ecfd22b4f1c 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -118,8 +118,8 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
u16 command;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &generic_port_ops
};
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 887d8f46a28..e5cbe80ce17 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -446,34 +446,34 @@ static struct ata_port_info piix_port_info[] = {
[piix_pata_mwdma] = /* PIIX3 MWDMA only */
{
.flags = PIIX_PATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
.port_ops = &piix_pata_ops,
},
[piix_pata_33] = /* PIIX4 at 33MHz */
{
.flags = PIIX_PATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
- .udma_mask = ATA_UDMA_MASK_40C,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+ .udma_mask = ATA_UDMA2,
.port_ops = &piix_pata_ops,
},
[ich_pata_33] = /* ICH0 - ICH at 33Mhz*/
{
.flags = PIIX_PATA_FLAGS,
- .pio_mask = 0x1f, /* pio 0-4 */
- .mwdma_mask = 0x06, /* Check: maybe 0x07 */
- .udma_mask = ATA_UDMA2, /* UDMA33 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok */
+ .udma_mask = ATA_UDMA2,
.port_ops = &ich_pata_ops,
},
[ich_pata_66] = /* ICH controllers up to 66MHz */
{
.flags = PIIX_PATA_FLAGS,
- .pio_mask = 0x1f, /* pio 0-4 */
- .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */
.udma_mask = ATA_UDMA4,
.port_ops = &ich_pata_ops,
},
@@ -481,17 +481,17 @@ static struct ata_port_info piix_port_info[] = {
[ich_pata_100] =
{
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x06, /* mwdma1-2 */
- .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+ .udma_mask = ATA_UDMA5,
.port_ops = &ich_pata_ops,
},
[ich5_sata] =
{
.flags = PIIX_SATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -499,8 +499,8 @@ static struct ata_port_info piix_port_info[] = {
[ich6_sata] =
{
.flags = PIIX_SATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -508,8 +508,8 @@ static struct ata_port_info piix_port_info[] = {
[ich6m_sata] =
{
.flags = PIIX_SATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -517,8 +517,8 @@ static struct ata_port_info piix_port_info[] = {
[ich8_sata] =
{
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -526,8 +526,8 @@ static struct ata_port_info piix_port_info[] = {
[ich8_2port_sata] =
{
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -535,8 +535,8 @@ static struct ata_port_info piix_port_info[] = {
[tolapai_sata] =
{
.flags = PIIX_SATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -544,8 +544,8 @@ static struct ata_port_info piix_port_info[] = {
[ich8m_apple_sata] =
{
.flags = PIIX_SATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -553,9 +553,9 @@ static struct ata_port_info piix_port_info[] = {
[piix_pata_vmw] =
{
.flags = PIIX_PATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
- .udma_mask = ATA_UDMA_MASK_40C,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+ .udma_mask = ATA_UDMA2,
.port_ops = &piix_vmw_ops,
},
@@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
return map;
}
+static bool piix_no_sidpr(struct ata_host *host)
+{
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+
+ /*
+ * Samsung DB-P70 only has three ATA ports exposed and
+ * curiously the unconnected first port reports link online
+ * while not responding to SRST protocol causing excessive
+ * detection delay.
+ *
+ * Unfortunately, the system doesn't carry enough DMI
+ * information to identify the machine but does have subsystem
+ * vendor and device set. As it's unclear whether the
+ * subsystem vendor/device is used only for this specific
+ * board, the port can't be disabled solely with the
+ * information; however, turning off SIDPR access works around
+ * the problem. Turn it off.
+ *
+ * This problem is reported in bnc#441240.
+ *
+ * https://bugzilla.novell.com/show_bug.cgi?id=441420
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&
+ pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
+ pdev->subsystem_device == 0xb049) {
+ dev_printk(KERN_WARNING, host->dev,
+ "Samsung DB-P70 detected, disabling SIDPR\n");
+ return true;
+ }
+
+ return false;
+}
+
static int __devinit piix_init_sidpr(struct ata_host *host)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
@@ -1302,6 +1335,10 @@ static int __devinit piix_init_sidpr(struct ata_host *host)
if (hpriv->map[i] == IDE)
return 0;
+ /* is it blacklisted? */
+ if (piix_no_sidpr(host))
+ return 0;
+
if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
return 0;
@@ -1387,6 +1424,32 @@ static void piix_iocfg_bit18_quirk(struct ata_host *host)
}
}
+static bool piix_broken_system_poweroff(struct pci_dev *pdev)
+{
+ static const struct dmi_system_id broken_systems[] = {
+ {
+ .ident = "HP Compaq 2510p",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x1FUL,
+ },
+
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+ if (dmi) {
+ unsigned long slot = (unsigned long)dmi->driver_data;
+ /* apply the quirk only to on-board controllers */
+ return slot == PCI_SLOT(pdev->devfn);
+ }
+
+ return false;
+}
+
/**
* piix_init_one - Register PIIX ATA PCI device with kernel services
* @pdev: PCI device to register
@@ -1422,6 +1485,14 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
if (!in_module_init)
return -ENODEV;
+ if (piix_broken_system_poweroff(pdev)) {
+ piix_port_info[ent->driver_data].flags |=
+ ATA_FLAG_NO_POWEROFF_SPINDOWN |
+ ATA_FLAG_NO_HIBERNATE_SPINDOWN;
+ dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
+ "on poweroff and hibernation\n");
+ }
+
port_info[0] = piix_port_info[ent->driver_data];
port_info[1] = piix_port_info[ent->driver_data];
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 71218d76d75..e7ea77cf606 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -57,6 +57,7 @@
#include <linux/scatterlist.h>
#include <linux/io.h>
#include <linux/async.h>
+#include <linux/log2.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
@@ -164,6 +165,11 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+static bool ata_sstatus_online(u32 sstatus)
+{
+ return (sstatus & 0xf) == 0x3;
+}
+
/**
* ata_link_next - link iteration helper
* @link: the previous link, NULL to start
@@ -1015,18 +1021,6 @@ static const char *sata_spd_string(unsigned int spd)
return spd_str[spd - 1];
}
-void ata_dev_disable(struct ata_device *dev)
-{
- if (ata_dev_enabled(dev)) {
- if (ata_msg_drv(dev->link->ap))
- ata_dev_printk(dev, KERN_WARNING, "disabled\n");
- ata_acpi_on_disable(dev);
- ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
- ATA_DNXFER_QUIET);
- dev->class++;
- }
-}
-
static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
{
struct ata_link *link = dev->link;
@@ -1329,14 +1323,16 @@ static u64 ata_id_n_sectors(const u16 *id)
{
if (ata_id_has_lba(id)) {
if (ata_id_has_lba48(id))
- return ata_id_u64(id, 100);
+ return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
else
- return ata_id_u32(id, 60);
+ return ata_id_u32(id, ATA_ID_LBA_CAPACITY);
} else {
if (ata_id_current_chs_valid(id))
- return ata_id_u32(id, 57);
+ return id[ATA_ID_CUR_CYLS] * id[ATA_ID_CUR_HEADS] *
+ id[ATA_ID_CUR_SECTORS];
else
- return id[1] * id[3] * id[6];
+ return id[ATA_ID_CYLS] * id[ATA_ID_HEADS] *
+ id[ATA_ID_SECTORS];
}
}
@@ -2239,6 +2235,40 @@ retry:
return rc;
}
+static int ata_do_link_spd_horkage(struct ata_device *dev)
+{
+ struct ata_link *plink = ata_dev_phys_link(dev);
+ u32 target, target_limit;
+
+ if (!sata_scr_valid(plink))
+ return 0;
+
+ if (dev->horkage & ATA_HORKAGE_1_5_GBPS)
+ target = 1;
+ else
+ return 0;
+
+ target_limit = (1 << target) - 1;
+
+ /* if already on stricter limit, no need to push further */
+ if (plink->sata_spd_limit <= target_limit)
+ return 0;
+
+ plink->sata_spd_limit = target_limit;
+
+ /* Request another EH round by returning -EAGAIN if link is
+ * going faster than the target speed. Forward progress is
+ * guaranteed by setting sata_spd_limit to target_limit above.
+ */
+ if (plink->sata_spd > target) {
+ ata_dev_printk(dev, KERN_INFO,
+ "applying link speed limit horkage to %s\n",
+ sata_spd_string(target));
+ return -EAGAIN;
+ }
+ return 0;
+}
+
static inline u8 ata_dev_knobble(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
@@ -2329,6 +2359,10 @@ int ata_dev_configure(struct ata_device *dev)
return 0;
}
+ rc = ata_do_link_spd_horkage(dev);
+ if (rc)
+ return rc;
+
/* let ACPI work its magic */
rc = ata_acpi_on_devcfg(dev);
if (rc)
@@ -2356,6 +2390,7 @@ int ata_dev_configure(struct ata_device *dev)
dev->cylinders = 0;
dev->heads = 0;
dev->sectors = 0;
+ dev->multi_count = 0;
/*
* common ATA, ATAPI feature tests
@@ -2393,8 +2428,15 @@ int ata_dev_configure(struct ata_device *dev)
dev->n_sectors = ata_id_n_sectors(id);
- if (dev->id[59] & 0x100)
- dev->multi_count = dev->id[59] & 0xff;
+ /* get current R/W Multiple count setting */
+ if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) {
+ unsigned int max = dev->id[47] & 0xff;
+ unsigned int cnt = dev->id[59] & 0xff;
+ /* only recognize/allow powers of two here */
+ if (is_power_of_2(max) && is_power_of_2(cnt))
+ if (cnt <= max)
+ dev->multi_count = cnt;
+ }
if (ata_id_has_lba(id)) {
const char *lba_desc;
@@ -2784,7 +2826,7 @@ int ata_bus_probe(struct ata_port *ap)
/* This is the last chance, better to slow
* down than lose it.
*/
- sata_down_spd_limit(&ap->link);
+ sata_down_spd_limit(&ap->link, 0);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
@@ -2880,21 +2922,27 @@ void ata_port_disable(struct ata_port *ap)
/**
* sata_down_spd_limit - adjust SATA spd limit downward
* @link: Link to adjust SATA spd limit for
+ * @spd_limit: Additional limit
*
* Adjust SATA spd limit of @link downward. Note that this
* function only adjusts the limit. The change must be applied
* using sata_set_spd().
*
+ * If @spd_limit is non-zero, the speed is limited to equal to or
+ * lower than @spd_limit if such speed is supported. If
+ * @spd_limit is slower than any supported speed, only the lowest
+ * supported speed is allowed.
+ *
* LOCKING:
* Inherited from caller.
*
* RETURNS:
* 0 on success, negative errno on failure
*/
-int sata_down_spd_limit(struct ata_link *link)
+int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
{
u32 sstatus, spd, mask;
- int rc, highbit;
+ int rc, bit;
if (!sata_scr_valid(link))
return -EOPNOTSUPP;
@@ -2903,7 +2951,7 @@ int sata_down_spd_limit(struct ata_link *link)
* If not, use cached value in link->sata_spd.
*/
rc = sata_scr_read(link, SCR_STATUS, &sstatus);
- if (rc == 0)
+ if (rc == 0 && ata_sstatus_online(sstatus))
spd = (sstatus >> 4) & 0xf;
else
spd = link->sata_spd;
@@ -2913,8 +2961,8 @@ int sata_down_spd_limit(struct ata_link *link)
return -EINVAL;
/* unconditionally mask off the highest bit */
- highbit = fls(mask) - 1;
- mask &= ~(1 << highbit);
+ bit = fls(mask) - 1;
+ mask &= ~(1 << bit);
/* Mask off all speeds higher than or equal to the current
* one. Force 1.5Gbps if current SPD is not available.
@@ -2928,6 +2976,15 @@ int sata_down_spd_limit(struct ata_link *link)
if (!mask)
return -EINVAL;
+ if (spd_limit) {
+ if (mask & ((1 << spd_limit) - 1))
+ mask &= (1 << spd_limit) - 1;
+ else {
+ bit = ffs(mask) - 1;
+ mask = 1 << bit;
+ }
+ }
+
link->sata_spd_limit = mask;
ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
@@ -3029,33 +3086,33 @@ int sata_set_spd(struct ata_link *link)
*/
static const struct ata_timing ata_timing[] = {
-/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
- { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
- { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
- { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
- { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
- { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
- { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 },
- { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 },
-
- { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
- { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
- { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
-
- { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
- { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
- { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
- { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 },
- { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 },
-
-/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */
- { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
- { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
- { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
- { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
- { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
- { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
- { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 0, 960, 0 }, */
+ { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 0, 600, 0 },
+ { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 0, 383, 0 },
+ { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 0, 240, 0 },
+ { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 0, 180, 0 },
+ { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 0, 120, 0 },
+ { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 0, 100, 0 },
+ { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 0, 80, 0 },
+
+ { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 50, 960, 0 },
+ { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 30, 480, 0 },
+ { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 20, 240, 0 },
+
+ { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 20, 480, 0 },
+ { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 5, 150, 0 },
+ { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 5, 120, 0 },
+ { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 5, 100, 0 },
+ { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 5, 80, 0 },
+
+/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 0, 150 }, */
+ { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 0, 120 },
+ { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 0, 80 },
+ { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 0, 60 },
+ { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 0, 45 },
+ { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 0, 30 },
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 0, 20 },
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 0, 15 },
{ 0xFF }
};
@@ -3065,14 +3122,15 @@ static const struct ata_timing ata_timing[] = {
static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
{
- q->setup = EZ(t->setup * 1000, T);
- q->act8b = EZ(t->act8b * 1000, T);
- q->rec8b = EZ(t->rec8b * 1000, T);
- q->cyc8b = EZ(t->cyc8b * 1000, T);
- q->active = EZ(t->active * 1000, T);
- q->recover = EZ(t->recover * 1000, T);
- q->cycle = EZ(t->cycle * 1000, T);
- q->udma = EZ(t->udma * 1000, UT);
+ q->setup = EZ(t->setup * 1000, T);
+ q->act8b = EZ(t->act8b * 1000, T);
+ q->rec8b = EZ(t->rec8b * 1000, T);
+ q->cyc8b = EZ(t->cyc8b * 1000, T);
+ q->active = EZ(t->active * 1000, T);
+ q->recover = EZ(t->recover * 1000, T);
+ q->dmack_hold = EZ(t->dmack_hold * 1000, T);
+ q->cycle = EZ(t->cycle * 1000, T);
+ q->udma = EZ(t->udma * 1000, UT);
}
void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
@@ -3084,6 +3142,7 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
if (what & ATA_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
if (what & ATA_TIMING_ACTIVE ) m->active = max(a->active, b->active);
if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+ if (what & ATA_TIMING_DMACK_HOLD) m->dmack_hold = max(a->dmack_hold, b->dmack_hold);
if (what & ATA_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
@@ -4213,6 +4272,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
+ /* Devices which aren't very happy with higher link speeds */
+ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
+
/* End Marker */
{ }
};
@@ -4561,7 +4623,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
if (qc->n_elem)
- dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+ dma_unmap_sg(ap->dev, sg, qc->orig_n_elem, dir);
qc->flags &= ~ATA_QCFLAG_DMAMAP;
qc->sg = NULL;
@@ -4676,7 +4738,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
return -1;
DPRINTK("%d sg elements mapped\n", n_elem);
-
+ qc->orig_n_elem = qc->n_elem;
qc->n_elem = n_elem;
qc->flags |= ATA_QCFLAG_DMAMAP;
@@ -4707,8 +4769,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
/**
* ata_qc_new - Request an available ATA command, for queueing
- * @ap: Port associated with device @dev
- * @dev: Device from whom we request an available command structure
+ * @ap: target port
*
* LOCKING:
* None.
@@ -5173,7 +5234,7 @@ bool ata_phys_link_online(struct ata_link *link)
u32 sstatus;
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
- (sstatus & 0xf) == 0x3)
+ ata_sstatus_online(sstatus))
return true;
return false;
}
@@ -5197,7 +5258,7 @@ bool ata_phys_link_offline(struct ata_link *link)
u32 sstatus;
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
- (sstatus & 0xf) != 0x3)
+ !ata_sstatus_online(sstatus))
return true;
return false;
}
@@ -5410,8 +5471,8 @@ void ata_dev_init(struct ata_device *dev)
dev->horkage = 0;
spin_unlock_irqrestore(ap->lock, flags);
- memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
- sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
+ memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0,
+ ATA_DEVICE_CLEAR_END - ATA_DEVICE_CLEAR_BEGIN);
dev->pio_mask = UINT_MAX;
dev->mwdma_mask = UINT_MAX;
dev->udma_mask = UINT_MAX;
@@ -6638,7 +6699,6 @@ EXPORT_SYMBOL_GPL(ata_dev_pair);
EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
-EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
@@ -6658,6 +6718,7 @@ EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_do_dev_read_id);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_pio_queue_task);
EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
EXPORT_SYMBOL_GPL(ata_timing_find_mode);
EXPORT_SYMBOL_GPL(ata_timing_compute);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 8147a838637..01831312c36 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -82,6 +82,10 @@ enum {
ATA_EH_FASTDRAIN_INTERVAL = 3000,
ATA_EH_UA_TRIES = 5,
+
+ /* probe speed down parameters, see ata_eh_schedule_probe() */
+ ATA_EH_PROBE_TRIAL_INTERVAL = 60000, /* 1 min */
+ ATA_EH_PROBE_TRIALS = 2,
};
/* The following table determines how we sequence resets. Each entry
@@ -543,7 +547,7 @@ void ata_scsi_error(struct Scsi_Host *host)
/* For new EH, all qcs are finished in one of three ways -
* normal completion, error completion, and SCSI timeout.
- * Both cmpletions can race against SCSI timeout. When normal
+ * Both completions can race against SCSI timeout. When normal
* completion wins, the qc never reaches EH. When error
* completion wins, the qc has ATA_QCFLAG_FAILED set.
*
@@ -558,7 +562,19 @@ void ata_scsi_error(struct Scsi_Host *host)
int nr_timedout = 0;
spin_lock_irqsave(ap->lock, flags);
-
+
+ /* This must occur under the ap->lock as we don't want
+ a polled recovery to race the real interrupt handler
+
+ The lost_interrupt handler checks for any completed but
+ non-notified command and completes much like an IRQ handler.
+
+ We then fall into the error recovery code which will treat
+ this as if normal completion won the race */
+
+ if (ap->ops->lost_interrupt)
+ ap->ops->lost_interrupt(ap);
+
list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
struct ata_queued_cmd *qc;
@@ -602,6 +618,9 @@ void ata_scsi_error(struct Scsi_Host *host)
ap->eh_tries = ATA_EH_MAX_TRIES;
} else
spin_unlock_wait(ap->lock);
+
+ /* If we timed raced normal completion and there is nothing to
+ recover nr_timedout == 0 why exactly are we doing error recovery ? */
repeat:
/* invoke error handler */
@@ -1176,6 +1195,32 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc)
}
/**
+ * ata_dev_disable - disable ATA device
+ * @dev: ATA device to disable
+ *
+ * Disable @dev.
+ *
+ * Locking:
+ * EH context.
+ */
+void ata_dev_disable(struct ata_device *dev)
+{
+ if (!ata_dev_enabled(dev))
+ return;
+
+ if (ata_msg_drv(dev->link->ap))
+ ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+ ata_acpi_on_disable(dev);
+ ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
+ dev->class++;
+
+ /* From now till the next successful probe, ering is used to
+ * track probe failures. Clear accumulated device error info.
+ */
+ ata_ering_clear(&dev->ering);
+}
+
+/**
* ata_eh_detach_dev - detach ATA device
* @dev: ATA device to detach
*
@@ -1849,7 +1894,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
/* speed down? */
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
/* speed down SATA link speed if possible */
- if (sata_down_spd_limit(link) == 0) {
+ if (sata_down_spd_limit(link, 0) == 0) {
action |= ATA_EH_RESET;
goto done;
}
@@ -2393,11 +2438,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
}
/* prereset() might have cleared ATA_EH_RESET. If so,
- * bang classes and return.
+ * bang classes, thaw and return.
*/
if (reset && !(ehc->i.action & ATA_EH_RESET)) {
ata_for_each_dev(dev, link, ALL)
classes[dev->devno] = ATA_DEV_NONE;
+ if ((ap->pflags & ATA_PFLAG_FROZEN) &&
+ ata_is_host_link(link))
+ ata_eh_thaw_port(ap);
rc = 0;
goto out;
}
@@ -2601,11 +2649,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
}
if (try == max_tries - 1) {
- sata_down_spd_limit(link);
+ sata_down_spd_limit(link, 0);
if (slave)
- sata_down_spd_limit(slave);
+ sata_down_spd_limit(slave, 0);
} else if (rc == -EPIPE)
- sata_down_spd_limit(failed_link);
+ sata_down_spd_limit(failed_link, 0);
if (hardreset)
reset = hardreset;
@@ -2744,6 +2792,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
readid_flags, dev->id);
switch (rc) {
case 0:
+ /* clear error info accumulated during probe */
+ ata_ering_clear(&dev->ering);
new_mask |= 1 << dev->devno;
break;
case -ENOENT:
@@ -2869,7 +2919,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
int i;
for (i = 0; i < ATA_EH_UA_TRIES; i++) {
- u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+ u8 *sense_buffer = dev->link->ap->sector_buf;
u8 sense_key = 0;
unsigned int err_mask;
@@ -2947,9 +2997,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
return 1;
}
+static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+ u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL);
+ u64 now = get_jiffies_64();
+ int *trials = void_arg;
+
+ if (ent->timestamp < now - min(now, interval))
+ return -1;
+
+ (*trials)++;
+ return 0;
+}
+
static int ata_eh_schedule_probe(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
+ struct ata_link *link = ata_dev_phys_link(dev);
+ int trials = 0;
if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
(ehc->did_probe_mask & (1 << dev->devno)))
@@ -2962,6 +3027,25 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
ehc->saved_xfer_mode[dev->devno] = 0;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);
+ /* Record and count probe trials on the ering. The specific
+ * error mask used is irrelevant. Because a successful device
+ * detection clears the ering, this count accumulates only if
+ * there are consecutive failed probes.
+ *
+ * If the count is equal to or higher than ATA_EH_PROBE_TRIALS
+ * in the last ATA_EH_PROBE_TRIAL_INTERVAL, link speed is
+ * forced to 1.5Gbps.
+ *
+ * This is to work around cases where failed link speed
+ * negotiation results in device misdetection leading to
+ * infinite DEVXCHG or PHRDY CHG events.
+ */
+ ata_ering_record(&dev->ering, 0, AC_ERR_OTHER);
+ ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials);
+
+ if (trials > ATA_EH_PROBE_TRIALS)
+ sata_down_spd_limit(link, 1);
+
return 1;
}
@@ -2969,7 +3053,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
- ehc->tries[dev->devno]--;
+ /* -EAGAIN from EH routine indicates retry without prejudice.
+ * The requester is responsible for ensuring forward progress.
+ */
+ if (err != -EAGAIN)
+ ehc->tries[dev->devno]--;
switch (err) {
case -ENODEV:
@@ -2979,12 +3067,13 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
- if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) {
+ if (ehc->tries[dev->devno] == 1) {
/* This is the last chance, better to slow
* down than lose it.
*/
- sata_down_spd_limit(ata_dev_phys_link(dev));
- ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+ sata_down_spd_limit(ata_dev_phys_link(dev), 0);
+ if (dev->pio_mode > XFER_PIO_0)
+ ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 98ca07a2db8..619f2c33950 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
if (tries) {
/* consecutive revalidation failures? speed down */
if (reval_failed)
- sata_down_spd_limit(link);
+ sata_down_spd_limit(link, 0);
else
reval_failed = 1;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 9e92107691f..b9747fa59e5 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -46,6 +46,7 @@
#include <linux/libata.h>
#include <linux/hdreg.h>
#include <linux/uaccess.h>
+#include <linux/suspend.h>
#include "libata.h"
@@ -414,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
/**
* ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
+ * @ap: target port
* @sdev: SCSI device to get identify data for
* @arg: User buffer area for identify data
*
@@ -423,9 +425,9 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
* RETURNS:
* Zero on success, negative errno on error.
*/
-static int ata_get_identity(struct scsi_device *sdev, void __user *arg)
+static int ata_get_identity(struct ata_port *ap, struct scsi_device *sdev,
+ void __user *arg)
{
- struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
u16 __user *dst = arg;
char buf[40];
@@ -645,7 +647,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
return rc;
}
-int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
+ int cmd, void __user *arg)
{
int val = -EINVAL, rc = -EINVAL;
@@ -663,7 +666,7 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
return 0;
case HDIO_GET_IDENTITY:
- return ata_get_identity(scsidev, arg);
+ return ata_get_identity(ap, scsidev, arg);
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -682,6 +685,14 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
return rc;
}
+EXPORT_SYMBOL_GPL(ata_sas_scsi_ioctl);
+
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+ return ata_sas_scsi_ioctl(ata_shost_to_port(scsidev->host),
+ scsidev, cmd, arg);
+}
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
/**
* ata_scsi_qc_new - acquire new ata_queued_cmd reference
@@ -1294,6 +1305,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
} else {
+ /* Some odd clown BIOSen issue spindown on power off (ACPI S4
+ * or S5) causing some drives to spin up and down again.
+ */
+ if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
+ system_state == SYSTEM_POWER_OFF)
+ goto skip;
+
+ if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
+ system_entering_hibernation())
+ goto skip;
+
/* XXX: This is for backward compatibility, will be
* removed. Read Documentation/feature-removal-schedule.txt
* for more info.
@@ -1317,8 +1339,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
scmd->scsi_done = qc->scsidone;
qc->scsidone = ata_delayed_done;
}
- scmd->result = SAM_STAT_GOOD;
- return 1;
+ goto skip;
}
/* Issue ATA STANDBY IMMEDIATE command */
@@ -1334,10 +1355,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
return 0;
-invalid_fld:
+ invalid_fld:
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
/* "Invalid field in cbd" */
return 1;
+ skip:
+ scmd->result = SAM_STAT_GOOD;
+ return 1;
}
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 5a4aad123c4..8332e97a9de 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -52,6 +52,7 @@ const struct ata_port_operations ata_sff_port_ops = {
.softreset = ata_sff_softreset,
.hardreset = sata_sff_hardreset,
.postreset = ata_sff_postreset,
+ .drain_fifo = ata_sff_drain_fifo,
.error_handler = ata_sff_error_handler,
.post_internal_cmd = ata_sff_post_internal_cmd,
@@ -64,6 +65,8 @@ const struct ata_port_operations ata_sff_port_ops = {
.sff_irq_on = ata_sff_irq_on,
.sff_irq_clear = ata_sff_irq_clear,
+ .lost_interrupt = ata_sff_lost_interrupt,
+
.port_start = ata_sff_port_start,
};
EXPORT_SYMBOL_GPL(ata_sff_port_ops);
@@ -773,18 +776,32 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
else
iowrite32_rep(data_addr, buf, words);
+ /* Transfer trailing bytes, if any */
if (unlikely(slop)) {
- __le32 pad;
+ unsigned char pad[4];
+
+ /* Point buf to the tail of buffer */
+ buf += buflen - slop;
+
+ /*
+ * Use io*_rep() accessors here as well to avoid pointlessly
+ * swapping bytes to and fro on the big endian machines...
+ */
if (rw == READ) {
- pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- memcpy(buf + buflen - slop, &pad, slop);
+ if (slop < 3)
+ ioread16_rep(data_addr, pad, 1);
+ else
+ ioread32_rep(data_addr, pad, 1);
+ memcpy(buf, pad, slop);
} else {
- memcpy(&pad, buf + buflen - slop, slop);
- iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ memcpy(pad, buf, slop);
+ if (slop < 3)
+ iowrite16_rep(data_addr, pad, 1);
+ else
+ iowrite32_rep(data_addr, pad, 1);
}
- words++;
}
- return words << 2;
+ return (buflen + 1) & ~1;
}
EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
@@ -1322,7 +1339,7 @@ fsm_start:
* condition. Mark hint.
*/
ata_ehi_push_desc(ehi, "ST-ATA: "
- "DRQ=1 with device error, "
+ "DRQ=0 without device error, "
"dev_stat 0x%X", status);
qc->err_mask |= AC_ERR_HSM |
AC_ERR_NODEV_HINT;
@@ -1358,6 +1375,16 @@ fsm_start:
qc->err_mask |= AC_ERR_HSM;
}
+ /* There are oddball controllers with
+ * status register stuck at 0x7f and
+ * lbal/m/h at zero which makes it
+ * pass all other presence detection
+ * mechanisms we have. Set NODEV_HINT
+ * for it. Kernel bz#7241.
+ */
+ if (status == 0x7f)
+ qc->err_mask |= AC_ERR_NODEV_HINT;
+
/* ata_pio_sectors() might change the
* state to HSM_ST_LAST. so, the state
* is changed after ata_pio_sectors().
@@ -1622,7 +1649,7 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
* RETURNS:
* One if interrupt was handled, zero if not (shared irq).
*/
-inline unsigned int ata_sff_host_intr(struct ata_port *ap,
+unsigned int ata_sff_host_intr(struct ata_port *ap,
struct ata_queued_cmd *qc)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
@@ -1751,6 +1778,48 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
EXPORT_SYMBOL_GPL(ata_sff_interrupt);
/**
+ * ata_sff_lost_interrupt - Check for an apparent lost interrupt
+ * @ap: port that appears to have timed out
+ *
+ * Called from the libata error handlers when the core code suspects
+ * an interrupt has been lost. If it has complete anything we can and
+ * then return. Interface must support altstatus for this faster
+ * recovery to occur.
+ *
+ * Locking:
+ * Caller holds host lock
+ */
+
+void ata_sff_lost_interrupt(struct ata_port *ap)
+{
+ u8 status;
+ struct ata_queued_cmd *qc;
+
+ /* Only one outstanding command per SFF channel */
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ /* Check we have a live one.. */
+ if (qc == NULL || !(qc->flags & ATA_QCFLAG_ACTIVE))
+ return;
+ /* We cannot lose an interrupt on a polled command */
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ return;
+ /* See if the controller thinks it is still busy - if so the command
+ isn't a lost IRQ but is still in progress */
+ status = ata_sff_altstatus(ap);
+ if (status & ATA_BUSY)
+ return;
+
+ /* There was a command running, we are no longer busy and we have
+ no interrupt. */
+ ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
+ status);
+ /* Run the host interrupt logic as if the interrupt had not been
+ lost */
+ ata_sff_host_intr(ap, qc);
+}
+EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
+
+/**
* ata_sff_freeze - Freeze SFF controller port
* @ap: port to freeze
*
@@ -2042,6 +2111,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
udelay(20); /* FIXME: flush */
iowrite8(ap->ctl, ioaddr->ctl_addr);
+ ap->last_ctl = ap->ctl;
/* wait the port to become ready */
return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
@@ -2166,12 +2236,47 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
}
/* set up device control */
- if (ap->ioaddr.ctl_addr)
+ if (ap->ioaddr.ctl_addr) {
iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+ ap->last_ctl = ap->ctl;
+ }
}
EXPORT_SYMBOL_GPL(ata_sff_postreset);
/**
+ * ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers
+ * @qc: command
+ *
+ * Drain the FIFO and device of any stuck data following a command
+ * failing to complete. In some cases this is neccessary before a
+ * reset will recover the device.
+ *
+ */
+
+void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
+{
+ int count;
+ struct ata_port *ap;
+
+ /* We only need to flush incoming data when a command was running */
+ if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
+ return;
+
+ ap = qc->ap;
+ /* Drain up to 64K of data before we give up this recovery method */
+ for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
+ && count < 32768; count++)
+ ioread16(ap->ioaddr.data_addr);
+
+ /* Can become DEBUG later */
+ if (count)
+ ata_port_printk(ap, KERN_DEBUG,
+ "drained %d bytes to clear DRQ.\n", count);
+
+}
+EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
+
+/**
* ata_sff_error_handler - Stock error handler for BMDMA controller
* @ap: port to handle error for
*
@@ -2212,7 +2317,8 @@ void ata_sff_error_handler(struct ata_port *ap)
* really a timeout event, adjust error mask and
* cancel frozen state.
*/
- if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) {
+ if (qc->err_mask == AC_ERR_TIMEOUT
+ && (host_stat & ATA_DMA_ERR)) {
qc->err_mask = AC_ERR_HOST_BUS;
thaw = 1;
}
@@ -2223,6 +2329,13 @@ void ata_sff_error_handler(struct ata_port *ap)
ata_sff_sync(ap); /* FIXME: We don't need this */
ap->ops->sff_check_status(ap);
ap->ops->sff_irq_clear(ap);
+ /* We *MUST* do FIFO draining before we issue a reset as several
+ * devices helpfully clear their internal state and will lock solid
+ * if we touch the data port post reset. Pass qc in case anyone wants
+ * to do different PIO/DMA recovery or has per command fixups
+ */
+ if (ap->ops->drain_fifo)
+ ap->ops->drain_fifo(qc);
spin_unlock_irqrestore(ap->lock, flags);
@@ -2510,6 +2623,7 @@ void ata_bus_reset(struct ata_port *ap)
if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
/* set up device control for ATA_FLAG_SATA_RESET */
iowrite8(ap->ctl, ioaddr->ctl_addr);
+ ap->last_ctl = ap->ctl;
}
DPRINTK("EXIT\n");
@@ -2931,4 +3045,3 @@ out:
EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
#endif /* CONFIG_PCI */
-
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index fe2839e5877..89a1e0018e7 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -79,9 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
unsigned int tag);
extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
-extern void ata_dev_disable(struct ata_device *dev);
-extern void ata_pio_queue_task(struct ata_port *ap, void *data,
- unsigned long delay);
extern void ata_port_flush_task(struct ata_port *ap);
extern unsigned ata_exec_internal(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb,
@@ -100,7 +97,7 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
unsigned int readid_flags);
extern int ata_dev_configure(struct ata_device *dev);
-extern int sata_down_spd_limit(struct ata_link *link);
+extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
extern void ata_sg_clean(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
@@ -160,6 +157,7 @@ extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_port_wait_eh(struct ata_port *ap);
extern void ata_eh_fastdrain_timerfn(unsigned long arg);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
+extern void ata_dev_disable(struct ata_device *dev);
extern void ata_eh_detach_dev(struct ata_device *dev);
extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
unsigned int action);
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 8b77a9802df..d8f35fe4442 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -246,9 +246,9 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
.port_ops = &pacpi_ops,
};
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index a7999c19f0c..751b7ea4816 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -41,7 +41,7 @@ static int ali_atapi_dma = 0;
module_param_named(atapi_dma, ali_atapi_dma, int, 0644);
MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)");
-static struct pci_dev *isa_bridge;
+static struct pci_dev *ali_isa_bridge;
/*
* Cable special cases
@@ -346,13 +346,13 @@ static void ali_c2_c3_postreset(struct ata_link *link, unsigned int *classes)
int port_bit = 4 << link->ap->port_no;
/* If our bridge is an ALI 1533 then do the extra work */
- if (isa_bridge) {
+ if (ali_isa_bridge) {
/* Tristate and re-enable the bus signals */
- pci_read_config_byte(isa_bridge, 0x58, &r);
+ pci_read_config_byte(ali_isa_bridge, 0x58, &r);
r &= ~port_bit;
- pci_write_config_byte(isa_bridge, 0x58, r);
+ pci_write_config_byte(ali_isa_bridge, 0x58, r);
r |= port_bit;
- pci_write_config_byte(isa_bridge, 0x58, r);
+ pci_write_config_byte(ali_isa_bridge, 0x58, r);
}
ata_sff_postreset(link, classes);
}
@@ -467,14 +467,14 @@ static void ali_init_chipset(struct pci_dev *pdev)
pci_write_config_byte(pdev, 0x53, tmp);
}
north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
- if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) {
+ if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) {
/* Configure the ALi bridge logic. For non ALi rely on BIOS.
Set the south bridge enable bit */
- pci_read_config_byte(isa_bridge, 0x79, &tmp);
+ pci_read_config_byte(ali_isa_bridge, 0x79, &tmp);
if (pdev->revision == 0xC2)
- pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
+ pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04);
else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
- pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
+ pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
}
pci_dev_put(north);
ata_pci_bmdma_clear_simplex(pdev);
@@ -492,53 +492,53 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info_early = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &ali_early_port_ops
};
/* Revision 0x20 added DMA */
static const struct ata_port_info info_20 = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &ali_20_port_ops
};
/* Revision 0x20 with support logic added UDMA */
static const struct ata_port_info info_20_udma = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x07, /* UDMA33 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &ali_20_port_ops
};
/* Revision 0xC2 adds UDMA66 */
static const struct ata_port_info info_c2 = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &ali_c2_port_ops
};
/* Revision 0xC3 is UDMA66 for now */
static const struct ata_port_info info_c3 = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &ali_c2_port_ops
};
/* Revision 0xC4 is UDMA100 */
static const struct ata_port_info info_c4 = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &ali_c4_port_ops
};
/* Revision 0xC5 is UDMA133 with LBA48 DMA */
static const struct ata_port_info info_c5 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &ali_c5_port_ops
};
@@ -571,9 +571,9 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
ali_init_chipset(pdev);
- if (isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
+ if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
/* Are we paired with a UDMA capable chip */
- pci_read_config_byte(isa_bridge, 0x5E, &tmp);
+ pci_read_config_byte(ali_isa_bridge, 0x5E, &tmp);
if ((tmp & 0x1E) == 0x12)
ppi[0] = &info_20_udma;
}
@@ -617,11 +617,11 @@ static struct pci_driver ali_pci_driver = {
static int __init ali_init(void)
{
int ret;
- isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+ ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
ret = pci_register_driver(&ali_pci_driver);
if (ret < 0)
- pci_dev_put(isa_bridge);
+ pci_dev_put(ali_isa_bridge);
return ret;
}
@@ -629,7 +629,7 @@ static int __init ali_init(void)
static void __exit ali_exit(void)
{
pci_unregister_driver(&ali_pci_driver);
- pci_dev_put(isa_bridge);
+ pci_dev_put(ali_isa_bridge);
}
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 63719ab9ea4..33a74f11171 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.3.11"
+#define DRV_VERSION "0.4.1"
/**
* timing_setup - shared timing computation and load
@@ -145,6 +145,13 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
return ata_sff_prereset(link, deadline);
}
+/**
+ * amd_cable_detect - report cable type
+ * @ap: port
+ *
+ * AMD controller/BIOS setups record the cable type in word 0x42
+ */
+
static int amd_cable_detect(struct ata_port *ap)
{
static const u32 bitmask[2] = {0x03, 0x0C};
@@ -158,6 +165,40 @@ static int amd_cable_detect(struct ata_port *ap)
}
/**
+ * amd_fifo_setup - set the PIO FIFO for ATA/ATAPI
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Set the PCI fifo for this device according to the devices present
+ * on the bus at this point in time. We need to turn the post write buffer
+ * off for ATAPI devices as we may need to issue a word sized write to the
+ * device as the final I/O
+ */
+
+static void amd_fifo_setup(struct ata_port *ap)
+{
+ struct ata_device *adev;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ static const u8 fifobit[2] = { 0xC0, 0x30};
+ u8 fifo = fifobit[ap->port_no];
+ u8 r;
+
+
+ ata_for_each_dev(adev, &ap->link, ENABLED) {
+ if (adev->class == ATA_DEV_ATAPI)
+ fifo = 0;
+ }
+ if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */
+ fifo = 0;
+
+ /* On the later chips the read prefetch bits become no-op bits */
+ pci_read_config_byte(pdev, 0x41, &r);
+ r &= ~fifobit[ap->port_no];
+ r |= fifo;
+ pci_write_config_byte(pdev, 0x41, r);
+}
+
+/**
* amd33_set_piomode - set initial PIO mode data
* @ap: ATA interface
* @adev: ATA device
@@ -167,21 +208,25 @@ static int amd_cable_detect(struct ata_port *ap)
static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
+ amd_fifo_setup(ap);
timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
}
static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
+ amd_fifo_setup(ap);
timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
}
static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
+ amd_fifo_setup(ap);
timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
}
static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
+ amd_fifo_setup(ap);
timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
}
@@ -397,77 +442,87 @@ static struct ata_port_operations nv133_port_ops = {
.set_dmamode = nv133_set_dmamode,
};
+static void amd_clear_fifo(struct pci_dev *pdev)
+{
+ u8 fifo;
+ /* Disable the FIFO, the FIFO logic will re-enable it as
+ appropriate */
+ pci_read_config_byte(pdev, 0x41, &fifo);
+ fifo &= 0x0F;
+ pci_write_config_byte(pdev, 0x41, fifo);
+}
+
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info[10] = {
- { /* 0: AMD 7401 */
+ { /* 0: AMD 7401 - no swdma */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07, /* No SWDMA */
- .udma_mask = 0x07, /* UDMA 33 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &amd33_port_ops
},
{ /* 1: Early AMD7409 - no swdma */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA4, /* UDMA 66 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
.port_ops = &amd66_port_ops
},
- { /* 2: AMD 7409, no swdma errata */
+ { /* 2: AMD 7409 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA4, /* UDMA 66 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
.port_ops = &amd66_port_ops
},
{ /* 3: AMD 7411 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA5, /* UDMA 100 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &amd100_port_ops
},
{ /* 4: AMD 7441 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA5, /* UDMA 100 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &amd100_port_ops
},
- { /* 5: AMD 8111*/
+ { /* 5: AMD 8111 - no swdma */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
.port_ops = &amd133_port_ops
},
- { /* 6: AMD 8111 UDMA 100 (Serenade) */
+ { /* 6: AMD 8111 UDMA 100 (Serenade) - no swdma */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA5, /* UDMA 100, no swdma */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &amd133_port_ops
},
{ /* 7: Nvidia Nforce */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA5, /* UDMA 100 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &nv100_port_ops
},
- { /* 8: Nvidia Nforce2 and later */
+ { /* 8: Nvidia Nforce2 and later - no swdma */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
.port_ops = &nv133_port_ops
},
{ /* 9: AMD CS5536 (Geode companion) */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA5, /* UDMA 100 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &amd100_port_ops
}
};
@@ -503,14 +558,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (type < 3)
ata_pci_bmdma_clear_simplex(pdev);
-
- /* Check for AMD7411 */
- if (type == 3)
- /* FIFO is broken */
- pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
- else
- pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
-
+ if (pdev->vendor == PCI_VENDOR_ID_AMD)
+ amd_clear_fifo(pdev);
/* Cable detection on Nvidia chips doesn't work too well,
* cache BIOS programmed UDMA mode.
*/
@@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
return rc;
if (pdev->vendor == PCI_VENDOR_ID_AMD) {
- u8 fifo;
- pci_read_config_byte(pdev, 0x41, &fifo);
- if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
- /* FIFO is broken */
- pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
- else
- pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+ amd_clear_fifo(pdev);
if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
ata_pci_bmdma_clear_simplex(pdev);
}
-
ata_host_resume(host);
return 0;
}
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 6b3092c75ff..d332cfdb0f3 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -12,7 +12,6 @@
* performance Alessandro Zummo <alessandro.zummo@towertech.it>
*
* TODO
- * 850 serialization once the core supports it
* Investigate no_dsc on 850R
* Clock detect
*/
@@ -29,7 +28,7 @@
#include <linux/ata.h>
#define DRV_NAME "pata_artop"
-#define DRV_VERSION "0.4.4"
+#define DRV_VERSION "0.4.5"
/*
* The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -283,6 +282,31 @@ static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra);
}
+/**
+ * artop_6210_qc_defer - implement serialization
+ * @qc: command
+ *
+ * Issue commands per host on this chip.
+ */
+
+static int artop6210_qc_defer(struct ata_queued_cmd *qc)
+{
+ struct ata_host *host = qc->ap->host;
+ struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
+ int rc;
+
+ /* First apply the usual rules */
+ rc = ata_std_qc_defer(qc);
+ if (rc != 0)
+ return rc;
+
+ /* Now apply serialization rules. Only allow a command if the
+ other channel state machine is idle */
+ if (alt && alt->qc_active)
+ return ATA_DEFER_PORT;
+ return 0;
+}
+
static struct scsi_host_template artop_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
@@ -293,6 +317,7 @@ static struct ata_port_operations artop6210_ops = {
.set_piomode = artop6210_set_piomode,
.set_dmamode = artop6210_set_dmamode,
.prereset = artop6210_pre_reset,
+ .qc_defer = artop6210_qc_defer,
};
static struct ata_port_operations artop6260_ops = {
@@ -323,29 +348,29 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
static int printed_version;
static const struct ata_port_info info_6210 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
.port_ops = &artop6210_ops,
};
static const struct ata_port_info info_626x = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &artop6260_ops,
};
static const struct ata_port_info info_628x = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &artop6260_ops,
};
static const struct ata_port_info info_628x_fast = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &artop6260_ops,
};
@@ -362,12 +387,8 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
if (id->driver_data == 0) { /* 6210 variant */
ppi[0] = &info_6210;
- ppi[1] = &ata_dummy_port_info;
/* BIOS may have left us in UDMA, clear it before libata probe */
pci_write_config_byte(pdev, 0x54, 0);
- /* For the moment (also lacks dsc) */
- printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n");
- printk(KERN_WARNING "Secondary ATA ports will not be activated.\n");
}
else if (id->driver_data == 1) /* 6260 */
ppi[0] = &info_626x;
diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
index ab61095093b..5c129f99a7e 100644
--- a/drivers/ata/pata_at32.c
+++ b/drivers/ata/pata_at32.c
@@ -67,7 +67,9 @@
*
* Alter PIO_MASK below according to table to set maximal PIO mode.
*/
-#define PIO_MASK (0x1f)
+enum {
+ PIO_MASK = ATA_PIO4,
+};
/*
* Struct containing private information about device.
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 0e2cde8f997..bec0b8ade66 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -32,21 +32,6 @@ enum {
ATIIXP_IDE_UDMA_MODE = 0x56
};
-static int atiixp_pre_reset(struct ata_link *link, unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- static const struct pci_bits atiixp_enable_bits[] = {
- { 0x48, 1, 0x01, 0x00 },
- { 0x48, 1, 0x08, 0x00 }
- };
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
- if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
- return -ENOENT;
-
- return ata_sff_prereset(link, deadline);
-}
-
static int atiixp_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -229,20 +214,29 @@ static struct ata_port_operations atiixp_port_ops = {
.cable_detect = atiixp_cable_detect,
.set_piomode = atiixp_set_piomode,
.set_dmamode = atiixp_set_dmamode,
- .prereset = atiixp_pre_reset,
};
-static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x06, /* No MWDMA0 support */
- .udma_mask = 0x3F,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+ .udma_mask = ATA_UDMA5,
.port_ops = &atiixp_port_ops
};
- const struct ata_port_info *ppi[] = { &info, NULL };
- return ata_pci_sff_init_one(dev, ppi, &atiixp_sht, NULL);
+ static const struct pci_bits atiixp_enable_bits[] = {
+ { 0x48, 1, 0x01, 0x00 },
+ { 0x48, 1, 0x08, 0x00 }
+ };
+ const struct ata_port_info *ppi[] = { &info, &info };
+ int i;
+
+ for (i = 0; i < 2; i++)
+ if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
+ ppi[i] = &ata_dummy_port_info;
+
+ return ata_pci_sff_init_one(pdev, ppi, &atiixp_sht, NULL);
}
static const struct pci_device_id atiixp[] = {
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 1050fed96b2..c4b47a3e544 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1502,7 +1502,7 @@ static struct ata_port_info bfin_port_info[] = {
.flags = ATA_FLAG_SLAVE_POSS
| ATA_FLAG_MMIO
| ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.mwdma_mask = 0,
.udma_mask = 0,
.port_ops = &bfin_pata_ops,
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 34a394264c3..5acf9fa9b39 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -211,7 +211,7 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &cmd640_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 3167d8fed2f..f98dffedf4b 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -299,40 +299,40 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info cmd_info[6] = {
{ /* CMD 643 - no UDMA */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 with broken UDMA */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 with working UDMA */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 rev 1 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &cmd646r1_port_ops
},
{ /* CMD 648 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &cmd648_port_ops
},
{ /* CMD 649 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &cmd648_port_ops
}
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 1186bcd2781..db6a96984f3 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -158,7 +158,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
static const unsigned int ctl_port[] = { 0x3F6, 0x376 };
struct ata_port_info pi = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &cs5520_port_ops,
};
const struct ata_port_info *ppi[2];
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index bba453381f4..c974b05e412 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -298,15 +298,15 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &cs5530_port_ops
};
/* The docking connector doesn't do UDMA, and it seems not MWDMA */
static const struct ata_port_info info_palmax_secondary = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &cs5530_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 8b236af84c2..d33aa28239a 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -181,8 +181,8 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &cs5535_port_ops
};
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index afed9297619..6da4cb486c8 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -241,8 +241,8 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &cs5536_port_ops,
};
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index d546425cd38..8fb040bf736 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -124,8 +124,8 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &cy82c693_port_ops
};
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index ac6392ea35b..2085e0a3a05 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -251,9 +251,9 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma1-2 */
- .udma_mask = 0x0f, /* UDMA 66 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
.port_ops = &efar_ops,
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 65c28e5a6cd..d7f2da127d1 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -336,8 +336,8 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info_hpt366 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &hpt366_port_ops
};
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 42163998de9..81ab57003ab 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -753,55 +753,55 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT370 - UDMA100 */
static const struct ata_port_info info_hpt370 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &hpt370_port_ops
};
/* HPT370A - UDMA100 */
static const struct ata_port_info info_hpt370a = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT370 - UDMA100 */
static const struct ata_port_info info_hpt370_33 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &hpt370_port_ops
};
/* HPT370A - UDMA100 */
static const struct ata_port_info info_hpt370a_33 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT371, 372 and friends - UDMA133 */
static const struct ata_port_info info_hpt372 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt372_port_ops
};
/* HPT374 - UDMA100, function 1 uses different prereset method */
static const struct ata_port_info info_hpt374_fn0 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &hpt372_port_ops
};
static const struct ata_port_info info_hpt374_fn1 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &hpt374_fn1_port_ops
};
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index d5c9fd7b82b..3d59fe0a408 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -441,8 +441,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT372N and friends - UDMA133 */
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt3x2n_port_ops
};
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index f19cc645881..7e310253b36 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -188,11 +188,11 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
#if defined(CONFIG_PATA_HPT3X3_DMA)
/* Further debug needed */
- .mwdma_mask = 0x07,
- .udma_mask = 0x07,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
#endif
.port_ops = &hpt3x3_port_ops
};
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index cf9e9848f8b..e7347db5b6c 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -297,7 +297,7 @@ static int icside_dma_init(struct pata_icside_info *info)
if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
state->dma = ec->dma;
- info->mwdma_mask = 0x07; /* MW0..2 */
+ info->mwdma_mask = ATA_MWDMA2;
}
return 0;
@@ -473,7 +473,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
for (i = 0; i < info->nr_ports; i++) {
struct ata_port *ap = host->ports[i];
- ap->pio_mask = 0x1f;
+ ap->pio_mask = ATA_PIO4;
ap->mwdma_mask = info->mwdma_mask;
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ops = &pata_icside_port_ops;
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 15cdb9148aa..4bceb8803a1 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -17,7 +17,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_isapnp"
-#define DRV_VERSION "0.2.2"
+#define DRV_VERSION "0.2.5"
static struct scsi_host_template isapnp_sht = {
ATA_PIO_SHT(DRV_NAME),
@@ -28,6 +28,13 @@ static struct ata_port_operations isapnp_port_ops = {
.cable_detect = ata_cable_40wire,
};
+static struct ata_port_operations isapnp_noalt_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ /* No altstatus so we don't want to use the lost interrupt poll */
+ .lost_interrupt = ATA_OP_NULL,
+};
+
/**
* isapnp_init_one - attach an isapnp interface
* @idev: PnP device
@@ -65,8 +72,8 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
ap = host->ports[0];
- ap->ops = &isapnp_port_ops;
- ap->pio_mask = 1;
+ ap->ops = &isapnp_noalt_port_ops;
+ ap->pio_mask = ATA_PIO0;
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ioaddr.cmd_addr = cmd_addr;
@@ -76,6 +83,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
pnp_port_start(idev, 1), 1);
ap->ioaddr.altstatus_addr = ctl_addr;
ap->ioaddr.ctl_addr = ctl_addr;
+ ap->ops = &isapnp_port_ops;
}
ata_sff_std_ports(&ap->ioaddr);
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index c113d7c079c..f156da8076f 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -262,8 +262,8 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */
.port_ops = &it8213_ops,
};
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index f1bb2f9fecb..188bc2fcd22 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -557,6 +557,9 @@ static unsigned int it821x_read_id(struct ata_device *adev,
id[83] |= 0x4400; /* Word 83 is valid and LBA48 */
id[86] |= 0x0400; /* LBA48 on */
id[ATA_ID_MAJOR_VER] |= 0x1F;
+ /* Clear the serial number because it's different each boot
+ which breaks validation on resume */
+ memset(&id[ATA_ID_SERNO], 0x20, ATA_ID_SERNO_LEN);
}
return err_mask;
}
@@ -872,29 +875,29 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info info_smart = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &it821x_smart_port_ops
};
static const struct ata_port_info info_passthru = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &it821x_passthru_port_ops
};
static const struct ata_port_info info_rdc = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &it821x_rdc_port_ops
};
static const struct ata_port_info info_rdc_11 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
/* No UDMA */
.port_ops = &it821x_rdc_port_ops
};
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index b173c157ab0..19fdecf319a 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -176,7 +176,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
ap = host->ports[0];
ap->ops = &ixp4xx_port_ops;
- ap->pio_mask = 0x1f; /* PIO4 */
+ ap->pio_mask = ATA_PIO4;
ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 38cf1ab2d28..3a1474ac883 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -136,8 +136,8 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &jmicron_ops,
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 6c1d778b63a..3f830f0fe2c 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -129,7 +129,7 @@ static int qdi; /* Set to probe QDI controllers */
static int winbond; /* Set to probe Winbond controllers,
give I/O port if non standard */
static int autospeed; /* Chip present which snoops speed changes */
-static int pio_mask = 0x1F; /* PIO range for autospeed devices */
+static int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */
static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */
/**
@@ -283,9 +283,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
unsigned char *buf, unsigned int buflen, int rw)
{
- if (ata_id_has_dword_io(dev->id)) {
+ int slop = buflen & 3;
+ /* 32bit I/O capable *and* we need to write a whole number of dwords */
+ if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) {
struct ata_port *ap = dev->link->ap;
- int slop = buflen & 3;
unsigned long flags;
local_irq_save(flags);
@@ -735,7 +736,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
struct ata_port *ap = adev->link->ap;
int slop = buflen & 3;
- if (ata_id_has_dword_io(adev->id)) {
+ if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) {
if (rw == WRITE)
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
else
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index 76e399bf8c1..2096fb737f8 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -126,8 +126,8 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &marvell_ops,
@@ -136,8 +136,8 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
/* Slave possible as its magically mapped not real */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &marvell_ops,
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 50ae6d13078..68d27bc70d0 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -737,10 +737,10 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
*/
prop = of_get_property(op->node, "mwdma-mode", &proplen);
if ((prop) && (proplen >= 4))
- mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1);
+ mwdma_mask = ATA_MWDMA2 & ((1 << (*prop + 1)) - 1);
prop = of_get_property(op->node, "udma-mode", &proplen);
if ((prop) && (proplen >= 4))
- udma_mask = 0x7 & ((1 << (*prop + 1)) - 1);
+ udma_mask = ATA_UDMA2 & ((1 << (*prop + 1)) - 1);
ata_irq = irq_of_parse_and_map(op->node, 0);
if (ata_irq == NO_IRQ) {
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index aa576cac4d1..b21f0021f54 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -200,7 +200,7 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
the MPIIX your box goes castors up */
ap->ops = &mpiix_port_ops;
- ap->pio_mask = 0x1F;
+ ap->pio_mask = ATA_PIO4;
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ioaddr.cmd_addr = cmd_addr;
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 9dc05e1656a..bdb236957cb 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -51,8 +51,8 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
.flags = ATA_FLAG_SLAVE_POSS,
/* Actually we don't really care about these as the
firmware deals with it */
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5, /* UDMA 133 */
.port_ops = &netcell_ops,
};
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index 4dd9a3b031e..0fb6b1b1e63 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -136,7 +136,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
if (!base)
return -ENOMEM;
ap->ops = &ninja32_port_ops;
- ap->pio_mask = 0x1F;
+ ap->pio_mask = ATA_PIO4;
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ioaddr.cmd_addr = base + 0x10;
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 40d411c460d..ca53fac0671 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -144,7 +144,7 @@ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x0F,
+ .pio_mask = ATA_PIO3,
.port_ops = &ns87410_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index 89bf5f865d6..773b1590b49 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -346,8 +346,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &ns87415_pata_ops,
};
const struct ata_port_info *ppi[] = { &info, NULL };
@@ -355,8 +355,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
#if defined(CONFIG_SUPERIO)
static const struct ata_port_info info87560 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &ns87560_pata_ops,
};
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
new file mode 100644
index 00000000000..efe2c1985af
--- /dev/null
+++ b/drivers/ata/pata_octeon_cf.c
@@ -0,0 +1,965 @@
+/*
+ * Driver for the Octeon bootbus compact flash.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 - 2009 Cavium Networks
+ * Copyright (C) 2008 Wind River Systems
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/libata.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <scsi/scsi_host.h>
+
+#include <asm/octeon/octeon.h>
+
+/*
+ * The Octeon bootbus compact flash interface is connected in at least
+ * 3 different configurations on various evaluation boards:
+ *
+ * -- 8 bits no irq, no DMA
+ * -- 16 bits no irq, no DMA
+ * -- 16 bits True IDE mode with DMA, but no irq.
+ *
+ * In the last case the DMA engine can generate an interrupt when the
+ * transfer is complete. For the first two cases only PIO is supported.
+ *
+ */
+
+#define DRV_NAME "pata_octeon_cf"
+#define DRV_VERSION "2.1"
+
+
+struct octeon_cf_port {
+ struct workqueue_struct *wq;
+ struct delayed_work delayed_finish;
+ struct ata_port *ap;
+ int dma_finished;
+};
+
+static struct scsi_host_template octeon_cf_sht = {
+ ATA_PIO_SHT(DRV_NAME),
+};
+
+/**
+ * Convert nanosecond based time to setting used in the
+ * boot bus timing register, based on timing multiple
+ */
+static unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs)
+{
+ unsigned int val;
+
+ /*
+ * Compute # of eclock periods to get desired duration in
+ * nanoseconds.
+ */
+ val = DIV_ROUND_UP(nsecs * (octeon_get_clock_rate() / 1000000),
+ 1000 * tim_mult);
+
+ return val;
+}
+
+static void octeon_cf_set_boot_reg_cfg(int cs)
+{
+ union cvmx_mio_boot_reg_cfgx reg_cfg;
+ reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
+ reg_cfg.s.dmack = 0; /* Don't assert DMACK on access */
+ reg_cfg.s.tim_mult = 2; /* Timing mutiplier 2x */
+ reg_cfg.s.rd_dly = 0; /* Sample on falling edge of BOOT_OE */
+ reg_cfg.s.sam = 0; /* Don't combine write and output enable */
+ reg_cfg.s.we_ext = 0; /* No write enable extension */
+ reg_cfg.s.oe_ext = 0; /* No read enable extension */
+ reg_cfg.s.en = 1; /* Enable this region */
+ reg_cfg.s.orbit = 0; /* Don't combine with previous region */
+ reg_cfg.s.ale = 0; /* Don't do address multiplexing */
+ cvmx_write_csr(CVMX_MIO_BOOT_REG_CFGX(cs), reg_cfg.u64);
+}
+
+/**
+ * Called after libata determines the needed PIO mode. This
+ * function programs the Octeon bootbus regions to support the
+ * timing requirements of the PIO mode.
+ *
+ * @ap: ATA port information
+ * @dev: ATA device
+ */
+static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
+{
+ struct octeon_cf_data *ocd = ap->dev->platform_data;
+ union cvmx_mio_boot_reg_timx reg_tim;
+ int cs = ocd->base_region;
+ int T;
+ struct ata_timing timing;
+
+ int use_iordy;
+ int trh;
+ int pause;
+ /* These names are timing parameters from the ATA spec */
+ int t1;
+ int t2;
+ int t2i;
+
+ T = (int)(2000000000000LL / octeon_get_clock_rate());
+
+ if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T))
+ BUG();
+
+ t1 = timing.setup;
+ if (t1)
+ t1--;
+ t2 = timing.active;
+ if (t2)
+ t2--;
+ t2i = timing.act8b;
+ if (t2i)
+ t2i--;
+
+ trh = ns_to_tim_reg(2, 20);
+ if (trh)
+ trh--;
+
+ pause = timing.cycle - timing.active - timing.setup - trh;
+ if (pause)
+ pause--;
+
+ octeon_cf_set_boot_reg_cfg(cs);
+ if (ocd->dma_engine >= 0)
+ /* True IDE mode, program both chip selects. */
+ octeon_cf_set_boot_reg_cfg(cs + 1);
+
+
+ use_iordy = ata_pio_need_iordy(dev);
+
+ reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cs));
+ /* Disable page mode */
+ reg_tim.s.pagem = 0;
+ /* Enable dynamic timing */
+ reg_tim.s.waitm = use_iordy;
+ /* Pages are disabled */
+ reg_tim.s.pages = 0;
+ /* We don't use multiplexed address mode */
+ reg_tim.s.ale = 0;
+ /* Not used */
+ reg_tim.s.page = 0;
+ /* Time after IORDY to coninue to assert the data */
+ reg_tim.s.wait = 0;
+ /* Time to wait to complete the cycle. */
+ reg_tim.s.pause = pause;
+ /* How long to hold after a write to de-assert CE. */
+ reg_tim.s.wr_hld = trh;
+ /* How long to wait after a read to de-assert CE. */
+ reg_tim.s.rd_hld = trh;
+ /* How long write enable is asserted */
+ reg_tim.s.we = t2;
+ /* How long read enable is asserted */
+ reg_tim.s.oe = t2;
+ /* Time after CE that read/write starts */
+ reg_tim.s.ce = ns_to_tim_reg(2, 5);
+ /* Time before CE that address is valid */
+ reg_tim.s.adr = 0;
+
+ /* Program the bootbus region timing for the data port chip select. */
+ cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs), reg_tim.u64);
+ if (ocd->dma_engine >= 0)
+ /* True IDE mode, program both chip selects. */
+ cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs + 1), reg_tim.u64);
+}
+
+static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)
+{
+ struct octeon_cf_data *ocd = dev->link->ap->dev->platform_data;
+ union cvmx_mio_boot_dma_timx dma_tim;
+ unsigned int oe_a;
+ unsigned int oe_n;
+ unsigned int dma_ackh;
+ unsigned int dma_arq;
+ unsigned int pause;
+ unsigned int T0, Tkr, Td;
+ unsigned int tim_mult;
+
+ const struct ata_timing *timing;
+
+ timing = ata_timing_find_mode(dev->dma_mode);
+ T0 = timing->cycle;
+ Td = timing->active;
+ Tkr = timing->recover;
+ dma_ackh = timing->dmack_hold;
+
+ dma_tim.u64 = 0;
+ /* dma_tim.s.tim_mult = 0 --> 4x */
+ tim_mult = 4;
+
+ /* not spec'ed, value in eclocks, not affected by tim_mult */
+ dma_arq = 8;
+ pause = 25 - dma_arq * 1000 /
+ (octeon_get_clock_rate() / 1000000); /* Tz */
+
+ oe_a = Td;
+ /* Tkr from cf spec, lengthened to meet T0 */
+ oe_n = max(T0 - oe_a, Tkr);
+
+ dma_tim.s.dmack_pi = 1;
+
+ dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n);
+ dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a);
+
+ /*
+ * This is tI, C.F. spec. says 0, but Sony CF card requires
+ * more, we use 20 nS.
+ */
+ dma_tim.s.dmack_s = ns_to_tim_reg(tim_mult, 20);;
+ dma_tim.s.dmack_h = ns_to_tim_reg(tim_mult, dma_ackh);
+
+ dma_tim.s.dmarq = dma_arq;
+ dma_tim.s.pause = ns_to_tim_reg(tim_mult, pause);
+
+ dma_tim.s.rd_dly = 0; /* Sample right on edge */
+
+ /* writes only */
+ dma_tim.s.we_n = ns_to_tim_reg(tim_mult, oe_n);
+ dma_tim.s.we_a = ns_to_tim_reg(tim_mult, oe_a);
+
+ pr_debug("ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60,
+ ns_to_tim_reg(tim_mult, 60));
+ pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: "
+ "%d, dmarq: %d, pause: %d\n",
+ dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s,
+ dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause);
+
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_TIMX(ocd->dma_engine),
+ dma_tim.u64);
+
+}
+
+/**
+ * Handle an 8 bit I/O request.
+ *
+ * @dev: Device to access
+ * @buffer: Data buffer
+ * @buflen: Length of the buffer.
+ * @rw: True to write.
+ */
+static unsigned int octeon_cf_data_xfer8(struct ata_device *dev,
+ unsigned char *buffer,
+ unsigned int buflen,
+ int rw)
+{
+ struct ata_port *ap = dev->link->ap;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
+ unsigned long words;
+ int count;
+
+ words = buflen;
+ if (rw) {
+ count = 16;
+ while (words--) {
+ iowrite8(*buffer, data_addr);
+ buffer++;
+ /*
+ * Every 16 writes do a read so the bootbus
+ * FIFO doesn't fill up.
+ */
+ if (--count == 0) {
+ ioread8(ap->ioaddr.altstatus_addr);
+ count = 16;
+ }
+ }
+ } else {
+ ioread8_rep(data_addr, buffer, words);
+ }
+ return buflen;
+}
+
+/**
+ * Handle a 16 bit I/O request.
+ *
+ * @dev: Device to access
+ * @buffer: Data buffer
+ * @buflen: Length of the buffer.
+ * @rw: True to write.
+ */
+static unsigned int octeon_cf_data_xfer16(struct ata_device *dev,
+ unsigned char *buffer,
+ unsigned int buflen,
+ int rw)
+{
+ struct ata_port *ap = dev->link->ap;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
+ unsigned long words;
+ int count;
+
+ words = buflen / 2;
+ if (rw) {
+ count = 16;
+ while (words--) {
+ iowrite16(*(uint16_t *)buffer, data_addr);
+ buffer += sizeof(uint16_t);
+ /*
+ * Every 16 writes do a read so the bootbus
+ * FIFO doesn't fill up.
+ */
+ if (--count == 0) {
+ ioread8(ap->ioaddr.altstatus_addr);
+ count = 16;
+ }
+ }
+ } else {
+ while (words--) {
+ *(uint16_t *)buffer = ioread16(data_addr);
+ buffer += sizeof(uint16_t);
+ }
+ }
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ __le16 align_buf[1] = { 0 };
+
+ if (rw == READ) {
+ align_buf[0] = cpu_to_le16(ioread16(data_addr));
+ memcpy(buffer, align_buf, 1);
+ } else {
+ memcpy(align_buf, buffer, 1);
+ iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+ }
+ words++;
+ }
+ return buflen;
+}
+
+/**
+ * Read the taskfile for 16bit non-True IDE only.
+ */
+static void octeon_cf_tf_read16(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ u16 blob;
+ /* The base of the registers is at ioaddr.data_addr. */
+ void __iomem *base = ap->ioaddr.data_addr;
+
+ blob = __raw_readw(base + 0xc);
+ tf->feature = blob >> 8;
+
+ blob = __raw_readw(base + 2);
+ tf->nsect = blob & 0xff;
+ tf->lbal = blob >> 8;
+
+ blob = __raw_readw(base + 4);
+ tf->lbam = blob & 0xff;
+ tf->lbah = blob >> 8;
+
+ blob = __raw_readw(base + 6);
+ tf->device = blob & 0xff;
+ tf->command = blob >> 8;
+
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ if (likely(ap->ioaddr.ctl_addr)) {
+ iowrite8(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr);
+
+ blob = __raw_readw(base + 0xc);
+ tf->hob_feature = blob >> 8;
+
+ blob = __raw_readw(base + 2);
+ tf->hob_nsect = blob & 0xff;
+ tf->hob_lbal = blob >> 8;
+
+ blob = __raw_readw(base + 4);
+ tf->hob_lbam = blob & 0xff;
+ tf->hob_lbah = blob >> 8;
+
+ iowrite8(tf->ctl, ap->ioaddr.ctl_addr);
+ ap->last_ctl = tf->ctl;
+ } else {
+ WARN_ON(1);
+ }
+ }
+}
+
+static u8 octeon_cf_check_status16(struct ata_port *ap)
+{
+ u16 blob;
+ void __iomem *base = ap->ioaddr.data_addr;
+
+ blob = __raw_readw(base + 6);
+ return blob >> 8;
+}
+
+static int octeon_cf_softreset16(struct ata_link *link, unsigned int *classes,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ void __iomem *base = ap->ioaddr.data_addr;
+ int rc;
+ u8 err;
+
+ DPRINTK("about to softreset\n");
+ __raw_writew(ap->ctl, base + 0xe);
+ udelay(20);
+ __raw_writew(ap->ctl | ATA_SRST, base + 0xe);
+ udelay(20);
+ __raw_writew(ap->ctl, base + 0xe);
+
+ rc = ata_sff_wait_after_reset(link, 1, deadline);
+ if (rc) {
+ ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+ return rc;
+ }
+
+ /* determine by signature whether we have ATA or ATAPI devices */
+ classes[0] = ata_sff_dev_classify(&link->device[0], 1, &err);
+ DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+ return 0;
+}
+
+/**
+ * Load the taskfile for 16bit non-True IDE only. The device_addr is
+ * not loaded, we do this as part of octeon_cf_exec_command16.
+ */
+static void octeon_cf_tf_load16(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+ /* The base of the registers is at ioaddr.data_addr. */
+ void __iomem *base = ap->ioaddr.data_addr;
+
+ if (tf->ctl != ap->last_ctl) {
+ iowrite8(tf->ctl, ap->ioaddr.ctl_addr);
+ ap->last_ctl = tf->ctl;
+ ata_wait_idle(ap);
+ }
+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ __raw_writew(tf->hob_feature << 8, base + 0xc);
+ __raw_writew(tf->hob_nsect | tf->hob_lbal << 8, base + 2);
+ __raw_writew(tf->hob_lbam | tf->hob_lbah << 8, base + 4);
+ VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+ tf->hob_feature,
+ tf->hob_nsect,
+ tf->hob_lbal,
+ tf->hob_lbam,
+ tf->hob_lbah);
+ }
+ if (is_addr) {
+ __raw_writew(tf->feature << 8, base + 0xc);
+ __raw_writew(tf->nsect | tf->lbal << 8, base + 2);
+ __raw_writew(tf->lbam | tf->lbah << 8, base + 4);
+ VPRINTK("feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+ tf->feature,
+ tf->nsect,
+ tf->lbal,
+ tf->lbam,
+ tf->lbah);
+ }
+ ata_wait_idle(ap);
+}
+
+
+static void octeon_cf_dev_select(struct ata_port *ap, unsigned int device)
+{
+/* There is only one device, do nothing. */
+ return;
+}
+
+/*
+ * Issue ATA command to host controller. The device_addr is also sent
+ * as it must be written in a combined write with the command.
+ */
+static void octeon_cf_exec_command16(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ /* The base of the registers is at ioaddr.data_addr. */
+ void __iomem *base = ap->ioaddr.data_addr;
+ u16 blob;
+
+ if (tf->flags & ATA_TFLAG_DEVICE) {
+ VPRINTK("device 0x%X\n", tf->device);
+ blob = tf->device;
+ } else {
+ blob = 0;
+ }
+
+ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+ blob |= (tf->command << 8);
+ __raw_writew(blob, base + 6);
+
+
+ ata_wait_idle(ap);
+}
+
+static u8 octeon_cf_irq_on(struct ata_port *ap)
+{
+ return 0;
+}
+
+static void octeon_cf_irq_clear(struct ata_port *ap)
+{
+ return;
+}
+
+static void octeon_cf_dma_setup(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct octeon_cf_port *cf_port;
+
+ cf_port = (struct octeon_cf_port *)ap->private_data;
+ DPRINTK("ENTER\n");
+ /* issue r/w command */
+ qc->cursg = qc->sg;
+ cf_port->dma_finished = 0;
+ ap->ops->sff_exec_command(ap, &qc->tf);
+ DPRINTK("EXIT\n");
+}
+
+/**
+ * Start a DMA transfer that was already setup
+ *
+ * @qc: Information about the DMA
+ */
+static void octeon_cf_dma_start(struct ata_queued_cmd *qc)
+{
+ struct octeon_cf_data *ocd = qc->ap->dev->platform_data;
+ union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg;
+ union cvmx_mio_boot_dma_intx mio_boot_dma_int;
+ struct scatterlist *sg;
+
+ VPRINTK("%d scatterlists\n", qc->n_elem);
+
+ /* Get the scatter list entry we need to DMA into */
+ sg = qc->cursg;
+ BUG_ON(!sg);
+
+ /*
+ * Clear the DMA complete status.
+ */
+ mio_boot_dma_int.u64 = 0;
+ mio_boot_dma_int.s.done = 1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine),
+ mio_boot_dma_int.u64);
+
+ /* Enable the interrupt. */
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine),
+ mio_boot_dma_int.u64);
+
+ /* Set the direction of the DMA */
+ mio_boot_dma_cfg.u64 = 0;
+ mio_boot_dma_cfg.s.en = 1;
+ mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0);
+
+ /*
+ * Don't stop the DMA if the device deasserts DMARQ. Many
+ * compact flashes deassert DMARQ for a short time between
+ * sectors. Instead of stopping and restarting the DMA, we'll
+ * let the hardware do it. If the DMA is really stopped early
+ * due to an error condition, a later timeout will force us to
+ * stop.
+ */
+ mio_boot_dma_cfg.s.clr = 0;
+
+ /* Size is specified in 16bit words and minus one notation */
+ mio_boot_dma_cfg.s.size = sg_dma_len(sg) / 2 - 1;
+
+ /* We need to swap the high and low bytes of every 16 bits */
+ mio_boot_dma_cfg.s.swap8 = 1;
+
+ mio_boot_dma_cfg.s.adr = sg_dma_address(sg);
+
+ VPRINTK("%s %d bytes address=%p\n",
+ (mio_boot_dma_cfg.s.rw) ? "write" : "read", sg->length,
+ (void *)(unsigned long)mio_boot_dma_cfg.s.adr);
+
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine),
+ mio_boot_dma_cfg.u64);
+}
+
+/**
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ *
+ */
+static unsigned int octeon_cf_dma_finished(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
+{
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ struct octeon_cf_data *ocd = ap->dev->platform_data;
+ union cvmx_mio_boot_dma_cfgx dma_cfg;
+ union cvmx_mio_boot_dma_intx dma_int;
+ struct octeon_cf_port *cf_port;
+ u8 status;
+
+ VPRINTK("ata%u: protocol %d task_state %d\n",
+ ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+
+
+ if (ap->hsm_task_state != HSM_ST_LAST)
+ return 0;
+
+ cf_port = (struct octeon_cf_port *)ap->private_data;
+
+ dma_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine));
+ if (dma_cfg.s.size != 0xfffff) {
+ /* Error, the transfer was not complete. */
+ qc->err_mask |= AC_ERR_HOST_BUS;
+ ap->hsm_task_state = HSM_ST_ERR;
+ }
+
+ /* Stop and clear the dma engine. */
+ dma_cfg.u64 = 0;
+ dma_cfg.s.size = -1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), dma_cfg.u64);
+
+ /* Disable the interrupt. */
+ dma_int.u64 = 0;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), dma_int.u64);
+
+ /* Clear the DMA complete status */
+ dma_int.s.done = 1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), dma_int.u64);
+
+ status = ap->ops->sff_check_status(ap);
+
+ ata_sff_hsm_move(ap, qc, status, 0);
+
+ if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA))
+ ata_ehi_push_desc(ehi, "DMA stat 0x%x", status);
+
+ return 1;
+}
+
+/*
+ * Check if any queued commands have more DMAs, if so start the next
+ * transfer, else do end of transfer handling.
+ */
+static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance)
+{
+ struct ata_host *host = dev_instance;
+ struct octeon_cf_port *cf_port;
+ int i;
+ unsigned int handled = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ DPRINTK("ENTER\n");
+ for (i = 0; i < host->n_ports; i++) {
+ u8 status;
+ struct ata_port *ap;
+ struct ata_queued_cmd *qc;
+ union cvmx_mio_boot_dma_intx dma_int;
+ union cvmx_mio_boot_dma_cfgx dma_cfg;
+ struct octeon_cf_data *ocd;
+
+ ap = host->ports[i];
+ ocd = ap->dev->platform_data;
+ if (!ap || (ap->flags & ATA_FLAG_DISABLED))
+ continue;
+
+ ocd = ap->dev->platform_data;
+ cf_port = (struct octeon_cf_port *)ap->private_data;
+ dma_int.u64 =
+ cvmx_read_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine));
+ dma_cfg.u64 =
+ cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine));
+
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+ (qc->flags & ATA_QCFLAG_ACTIVE)) {
+ if (dma_int.s.done && !dma_cfg.s.en) {
+ if (!sg_is_last(qc->cursg)) {
+ qc->cursg = sg_next(qc->cursg);
+ handled = 1;
+ octeon_cf_dma_start(qc);
+ continue;
+ } else {
+ cf_port->dma_finished = 1;
+ }
+ }
+ if (!cf_port->dma_finished)
+ continue;
+ status = ioread8(ap->ioaddr.altstatus_addr);
+ if (status & (ATA_BUSY | ATA_DRQ)) {
+ /*
+ * We are busy, try to handle it
+ * later. This is the DMA finished
+ * interrupt, and it could take a
+ * little while for the card to be
+ * ready for more commands.
+ */
+ /* Clear DMA irq. */
+ dma_int.u64 = 0;
+ dma_int.s.done = 1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine),
+ dma_int.u64);
+
+ queue_delayed_work(cf_port->wq,
+ &cf_port->delayed_finish, 1);
+ handled = 1;
+ } else {
+ handled |= octeon_cf_dma_finished(ap, qc);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ DPRINTK("EXIT\n");
+ return IRQ_RETVAL(handled);
+}
+
+static void octeon_cf_delayed_finish(struct work_struct *work)
+{
+ struct octeon_cf_port *cf_port = container_of(work,
+ struct octeon_cf_port,
+ delayed_finish.work);
+ struct ata_port *ap = cf_port->ap;
+ struct ata_host *host = ap->host;
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ u8 status;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ /*
+ * If the port is not waiting for completion, it must have
+ * handled it previously. The hsm_task_state is
+ * protected by host->lock.
+ */
+ if (ap->hsm_task_state != HSM_ST_LAST || !cf_port->dma_finished)
+ goto out;
+
+ status = ioread8(ap->ioaddr.altstatus_addr);
+ if (status & (ATA_BUSY | ATA_DRQ)) {
+ /* Still busy, try again. */
+ queue_delayed_work(cf_port->wq,
+ &cf_port->delayed_finish, 1);
+ goto out;
+ }
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+ (qc->flags & ATA_QCFLAG_ACTIVE))
+ octeon_cf_dma_finished(ap, qc);
+out:
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void octeon_cf_dev_config(struct ata_device *dev)
+{
+ /*
+ * A maximum of 2^20 - 1 16 bit transfers are possible with
+ * the bootbus DMA. So we need to throttle max_sectors to
+ * (2^12 - 1 == 4095) to assure that this can never happen.
+ */
+ dev->max_sectors = min(dev->max_sectors, 4095U);
+}
+
+/*
+ * Trap if driver tries to do standard bmdma commands. They are not
+ * supported.
+ */
+static void unreachable_qc(struct ata_queued_cmd *qc)
+{
+ BUG();
+}
+
+static u8 unreachable_port(struct ata_port *ap)
+{
+ BUG();
+}
+
+/*
+ * We don't do ATAPI DMA so return 0.
+ */
+static int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ return 0;
+}
+
+static unsigned int octeon_cf_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+
+ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
+ octeon_cf_dma_setup(qc); /* set up dma */
+ octeon_cf_dma_start(qc); /* initiate dma */
+ ap->hsm_task_state = HSM_ST_LAST;
+ break;
+
+ case ATAPI_PROT_DMA:
+ dev_err(ap->dev, "Error, ATAPI not supported\n");
+ BUG();
+
+ default:
+ return ata_sff_qc_issue(qc);
+ }
+
+ return 0;
+}
+
+static struct ata_port_operations octeon_cf_ops = {
+ .inherits = &ata_sff_port_ops,
+ .check_atapi_dma = octeon_cf_check_atapi_dma,
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = octeon_cf_qc_issue,
+ .sff_dev_select = octeon_cf_dev_select,
+ .sff_irq_on = octeon_cf_irq_on,
+ .sff_irq_clear = octeon_cf_irq_clear,
+ .bmdma_setup = unreachable_qc,
+ .bmdma_start = unreachable_qc,
+ .bmdma_stop = unreachable_qc,
+ .bmdma_status = unreachable_port,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = octeon_cf_set_piomode,
+ .set_dmamode = octeon_cf_set_dmamode,
+ .dev_config = octeon_cf_dev_config,
+};
+
+static int __devinit octeon_cf_probe(struct platform_device *pdev)
+{
+ struct resource *res_cs0, *res_cs1;
+
+ void __iomem *cs0;
+ void __iomem *cs1 = NULL;
+ struct ata_host *host;
+ struct ata_port *ap;
+ struct octeon_cf_data *ocd;
+ int irq = 0;
+ irq_handler_t irq_handler = NULL;
+ void __iomem *base;
+ struct octeon_cf_port *cf_port;
+
+ res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res_cs0)
+ return -EINVAL;
+
+ ocd = pdev->dev.platform_data;
+
+ cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start,
+ res_cs0->end - res_cs0->start + 1);
+
+ if (!cs0)
+ return -ENOMEM;
+
+ /* Determine from availability of DMA if True IDE mode or not */
+ if (ocd->dma_engine >= 0) {
+ res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res_cs1)
+ return -EINVAL;
+
+ cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
+ res_cs0->end - res_cs1->start + 1);
+
+ if (!cs1)
+ return -ENOMEM;
+ }
+
+ cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL);
+ if (!cf_port)
+ return -ENOMEM;
+
+ /* allocate host */
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto free_cf_port;
+
+ ap = host->ports[0];
+ ap->private_data = cf_port;
+ cf_port->ap = ap;
+ ap->ops = &octeon_cf_ops;
+ ap->pio_mask = ATA_PIO6;
+ ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
+ | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
+
+ base = cs0 + ocd->base_region_bias;
+ if (!ocd->is16bit) {
+ ap->ioaddr.cmd_addr = base;
+ ata_sff_std_ports(&ap->ioaddr);
+
+ ap->ioaddr.altstatus_addr = base + 0xe;
+ ap->ioaddr.ctl_addr = base + 0xe;
+ octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8;
+ } else if (cs1) {
+ /* Presence of cs1 indicates True IDE mode. */
+ ap->ioaddr.cmd_addr = base + (ATA_REG_CMD << 1) + 1;
+ ap->ioaddr.data_addr = base + (ATA_REG_DATA << 1);
+ ap->ioaddr.error_addr = base + (ATA_REG_ERR << 1) + 1;
+ ap->ioaddr.feature_addr = base + (ATA_REG_FEATURE << 1) + 1;
+ ap->ioaddr.nsect_addr = base + (ATA_REG_NSECT << 1) + 1;
+ ap->ioaddr.lbal_addr = base + (ATA_REG_LBAL << 1) + 1;
+ ap->ioaddr.lbam_addr = base + (ATA_REG_LBAM << 1) + 1;
+ ap->ioaddr.lbah_addr = base + (ATA_REG_LBAH << 1) + 1;
+ ap->ioaddr.device_addr = base + (ATA_REG_DEVICE << 1) + 1;
+ ap->ioaddr.status_addr = base + (ATA_REG_STATUS << 1) + 1;
+ ap->ioaddr.command_addr = base + (ATA_REG_CMD << 1) + 1;
+ ap->ioaddr.altstatus_addr = cs1 + (6 << 1) + 1;
+ ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1;
+ octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16;
+
+ ap->mwdma_mask = ATA_MWDMA4;
+ irq = platform_get_irq(pdev, 0);
+ irq_handler = octeon_cf_interrupt;
+
+ /* True IDE mode needs delayed work to poll for not-busy. */
+ cf_port->wq = create_singlethread_workqueue(DRV_NAME);
+ if (!cf_port->wq)
+ goto free_cf_port;
+ INIT_DELAYED_WORK(&cf_port->delayed_finish,
+ octeon_cf_delayed_finish);
+
+ } else {
+ /* 16 bit but not True IDE */
+ octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16;
+ octeon_cf_ops.softreset = octeon_cf_softreset16;
+ octeon_cf_ops.sff_check_status = octeon_cf_check_status16;
+ octeon_cf_ops.sff_tf_read = octeon_cf_tf_read16;
+ octeon_cf_ops.sff_tf_load = octeon_cf_tf_load16;
+ octeon_cf_ops.sff_exec_command = octeon_cf_exec_command16;
+
+ ap->ioaddr.data_addr = base + ATA_REG_DATA;
+ ap->ioaddr.nsect_addr = base + ATA_REG_NSECT;
+ ap->ioaddr.lbal_addr = base + ATA_REG_LBAL;
+ ap->ioaddr.ctl_addr = base + 0xe;
+ ap->ioaddr.altstatus_addr = base + 0xe;
+ }
+
+ ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
+
+
+ dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n",
+ (ocd->is16bit) ? 16 : 8,
+ (cs1) ? ", True IDE" : "");
+
+
+ return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht);
+
+free_cf_port:
+ kfree(cf_port);
+ return -ENOMEM;
+}
+
+static struct platform_driver octeon_cf_driver = {
+ .probe = octeon_cf_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init octeon_cf_init(void)
+{
+ return platform_driver_register(&octeon_cf_driver);
+}
+
+
+MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
+MODULE_DESCRIPTION("low-level driver for Cavium OCTEON Compact Flash PATA");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:" DRV_NAME);
+
+module_init(octeon_cf_init);
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 2c1a91c40c1..84ac5033ac8 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -238,8 +238,8 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma1-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &oldpiix_pata_ops,
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index e4fa4d565e9..99eddda2d2e 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -163,7 +163,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &opti_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 93bb6e91973..86885a445f9 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -399,15 +399,15 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info_82c700 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &optidma_port_ops
};
static const struct ata_port_info info_82c700_udma = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &optiplus_port_ops
};
const struct ata_port_info *ppi[] = { &info_82c700, NULL };
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 64b2e2281ee..f4d009ed50a 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -42,7 +42,7 @@
#define DRV_NAME "pata_pcmcia"
-#define DRV_VERSION "0.3.3"
+#define DRV_VERSION "0.3.5"
/*
* Private data structure to glue stuff together
@@ -126,6 +126,37 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
return buflen;
}
+/**
+ * pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers
+ * @qc: command
+ *
+ * Drain the FIFO and device of any stuck data following a command
+ * failing to complete. In some cases this is neccessary before a
+ * reset will recover the device.
+ *
+ */
+
+void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
+{
+ int count;
+ struct ata_port *ap;
+
+ /* We only need to flush incoming data when a command was running */
+ if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
+ return;
+
+ ap = qc->ap;
+
+ /* Drain up to 64K of data before we give up this recovery method */
+ for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
+ && count++ < 65536;)
+ ioread8(ap->ioaddr.data_addr);
+
+ if (count)
+ ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n",
+ count);
+
+}
static struct scsi_host_template pcmcia_sht = {
ATA_PIO_SHT(DRV_NAME),
@@ -143,6 +174,7 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
.sff_data_xfer = ata_data_xfer_8bit,
.cable_detect = ata_cable_40wire,
.set_mode = pcmcia_set_mode_8bit,
+ .drain_fifo = pcmcia_8bit_drain_fifo,
};
#define CS_CHECK(fn, ret) \
@@ -299,7 +331,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
ap = host->ports[p];
ap->ops = ops;
- ap->pio_mask = 1; /* ISA so PIO 0 cycles */
+ ap->pio_mask = ATA_PIO0; /* ISA so PIO 0 cycles */
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index e94efccaa48..ca5cad0fd80 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -152,18 +152,18 @@ static struct ata_port_info pdc2027x_port_info[] = {
{
.flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_MMIO,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &pdc2027x_pata100_ops,
},
/* PDC_UDMA_133 */
{
.flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_MMIO,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = ATA_UDMA6, /* udma0-6 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc2027x_pata133_ops,
},
};
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index 799a6a09871..5fedb3d4032 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -291,22 +291,22 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
static const struct ata_port_info info[3] = {
{
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
.port_ops = &pdc2024x_port_ops
},
{
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &pdc2026x_port_ops
},
{
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &pdc2026x_port_ops
}
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 3080f371222..45879dc6fa4 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -12,7 +12,7 @@
*
* Probe code based on drivers/ide/legacy/qd65xx.c
* Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@fnac.net>
+ * Samuel Thibault <samuel.thibault@ens-lyon.org>
*/
#include <linux/kernel.h>
@@ -212,11 +212,11 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
if (type == 6580) {
ap->ops = &qdi6580_port_ops;
- ap->pio_mask = 0x1F;
+ ap->pio_mask = ATA_PIO4;
ap->flags |= ATA_FLAG_SLAVE_POSS;
} else {
ap->ops = &qdi6500_port_ops;
- ap->pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */
+ ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */
ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
}
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 695d44ae52c..4401b332eaa 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -216,9 +216,9 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma1-2 */
- .udma_mask = 0x14, /* UDMA33/66 only */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+ .udma_mask = ATA_UDMA24_ONLY,
.port_ops = &radisys_pata_ops,
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index c2e6fb9f2ef..8e3cdef8a25 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -48,65 +48,11 @@
struct rb532_cf_info {
void __iomem *iobase;
unsigned int gpio_line;
- int frozen;
unsigned int irq;
};
/* ------------------------------------------------------------------------ */
-static inline void rb532_pata_finish_io(struct ata_port *ap)
-{
- struct ata_host *ah = ap->host;
- struct rb532_cf_info *info = ah->private_data;
-
- /* FIXME: Keep previous delay. If this is merely a fence then
- ata_sff_sync might be sufficient. */
- ata_sff_dma_pause(ap);
- ndelay(RB500_CF_IO_DELAY);
-
- set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
-}
-
-static void rb532_pata_exec_command(struct ata_port *ap,
- const struct ata_taskfile *tf)
-{
- writeb(tf->command, ap->ioaddr.command_addr);
- rb532_pata_finish_io(ap);
-}
-
-static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
- unsigned int buflen, int write_data)
-{
- struct ata_port *ap = adev->link->ap;
- void __iomem *ioaddr = ap->ioaddr.data_addr;
- int retlen = buflen;
-
- if (write_data) {
- for (; buflen > 0; buflen--, buf++)
- writeb(*buf, ioaddr);
- } else {
- for (; buflen > 0; buflen--, buf++)
- *buf = readb(ioaddr);
- }
-
- rb532_pata_finish_io(adev->link->ap);
- return retlen;
-}
-
-static void rb532_pata_freeze(struct ata_port *ap)
-{
- struct rb532_cf_info *info = ap->host->private_data;
-
- info->frozen = 1;
-}
-
-static void rb532_pata_thaw(struct ata_port *ap)
-{
- struct rb532_cf_info *info = ap->host->private_data;
-
- info->frozen = 0;
-}
-
static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
{
struct ata_host *ah = dev_instance;
@@ -114,8 +60,7 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
if (gpio_get_value(info->gpio_line)) {
set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
- if (!info->frozen)
- ata_sff_interrupt(info->irq, dev_instance);
+ ata_sff_interrupt(info->irq, dev_instance);
} else {
set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
}
@@ -125,10 +70,7 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
static struct ata_port_operations rb532_pata_port_ops = {
.inherits = &ata_sff_port_ops,
- .sff_exec_command = rb532_pata_exec_command,
- .sff_data_xfer = rb532_pata_data_xfer,
- .freeze = rb532_pata_freeze,
- .thaw = rb532_pata_thaw,
+ .sff_data_xfer = ata_sff_data_xfer32,
};
/* ------------------------------------------------------------------------ */
@@ -147,7 +89,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah)
ap = ah->ports[0];
ap->ops = &rb532_pata_port_ops;
- ap->pio_mask = 0x1f; /* PIO4 */
+ ap->pio_mask = ATA_PIO4;
ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_BASE;
@@ -162,7 +104,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah)
static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
{
- unsigned int irq;
+ int irq;
int gpio;
struct resource *res;
struct ata_host *ah;
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 46d6bc1bf1e..0c574c065c6 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -88,7 +88,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
static int printed_version;
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &rz1000_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 9a4bdca5461..f49814d6fd2 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -2,7 +2,6 @@
* New ATA layer SC1200 driver Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* TODO: Mode selection filtering
- * TODO: Can't enable second channel until ATA core has serialize
* TODO: Needs custom DMA cleanup code
*
* Based very heavily on
@@ -178,6 +177,31 @@ static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc)
return ata_sff_qc_issue(qc);
}
+/**
+ * sc1200_qc_defer - implement serialization
+ * @qc: command
+ *
+ * Serialize command issue on this controller.
+ */
+
+static int sc1200_qc_defer(struct ata_queued_cmd *qc)
+{
+ struct ata_host *host = qc->ap->host;
+ struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
+ int rc;
+
+ /* First apply the usual rules */
+ rc = ata_std_qc_defer(qc);
+ if (rc != 0)
+ return rc;
+
+ /* Now apply serialization rules. Only allow a command if the
+ other channel state machine is idle */
+ if (alt && alt->qc_active)
+ return ATA_DEFER_PORT;
+ return 0;
+}
+
static struct scsi_host_template sc1200_sht = {
ATA_BMDMA_SHT(DRV_NAME),
.sg_tablesize = LIBATA_DUMB_MAX_PRD,
@@ -187,6 +211,7 @@ static struct ata_port_operations sc1200_port_ops = {
.inherits = &ata_bmdma_port_ops,
.qc_prep = ata_sff_dumb_qc_prep,
.qc_issue = sc1200_qc_issue,
+ .qc_defer = sc1200_qc_defer,
.cable_detect = ata_cable_40wire,
.set_piomode = sc1200_set_piomode,
.set_dmamode = sc1200_set_dmamode,
@@ -205,13 +230,13 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &sc1200_port_ops
};
/* Can't enable port 2 yet, see top comments */
- const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+ const struct ata_port_info *ppi[] = { &info, };
return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
}
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index d447f1cb46e..4257d6b40af 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -1001,8 +1001,8 @@ static struct ata_port_operations scc_pata_ops = {
static struct ata_port_info scc_port_info[] = {
{
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x00,
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA6,
.port_ops = &scc_pata_ops,
},
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index 6aeeeeb3412..99cceb458e2 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -84,9 +84,9 @@ static struct ata_port_operations sch_pata_ops = {
static struct ata_port_info sch_port_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = ATA_PIO4, /* pio0-4 */
- .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */
- .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &sch_pata_ops,
};
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 8d2fd9dd40c..beaed12d50e 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -398,26 +398,26 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
static const struct ata_port_info info[4] = {
{ /* OSB4 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &serverworks_osb4_port_ops
}, { /* OSB4 no UDMA */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
- .udma_mask = 0x00,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ /* No UDMA */
.port_ops = &serverworks_osb4_port_ops
}, { /* CSB5 */
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &serverworks_csb_port_ops
}, { /* CSB5 - later revisions*/
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &serverworks_csb_port_ops
}
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 9e764e5747e..4cb649d8d38 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -282,15 +282,15 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &sil680_port_ops
};
static const struct ata_port_info info_slow = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &sil680_port_ops
};
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 27ceb42a774..488e77bcd22 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -552,51 +552,57 @@ static struct ata_port_operations sis_old_ops = {
static const struct ata_port_info sis_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07,
- .udma_mask = 0,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ /* No UDMA */
.port_ops = &sis_old_ops,
};
static const struct ata_port_info sis_info33 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07,
- .udma_mask = ATA_UDMA2, /* UDMA 33 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
.port_ops = &sis_old_ops,
};
static const struct ata_port_info sis_info66 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = ATA_UDMA4, /* UDMA 66 */
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
+ .udma_mask = ATA_UDMA4,
.port_ops = &sis_66_ops,
};
static const struct ata_port_info sis_info100 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA5,
.port_ops = &sis_100_ops,
};
static const struct ata_port_info sis_info100_early = {
.flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA5,
- .pio_mask = 0x1f, /* pio0-4 */
.port_ops = &sis_66_ops,
};
static const struct ata_port_info sis_info133 = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_ops,
};
const struct ata_port_info sis_info133_for_sata = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_for_sata_ops,
};
static const struct ata_port_info sis_info133_early = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_early_ops,
};
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 1b0e7b6d8ef..29f733c3206 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -283,13 +283,13 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
{
static const struct ata_port_info info_dma = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &sl82c105_port_ops
};
static const struct ata_port_info info_early = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
+ .pio_mask = ATA_PIO4,
.port_ops = &sl82c105_port_ops
};
/* for now use only the first port */
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index ef9597517cd..f1f13ff222f 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -191,8 +191,8 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &triflex_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 681169c9c64..b08e6e0f82b 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -86,6 +86,10 @@ enum {
VIA_SATA_PATA = 0x800, /* SATA/PATA combined configuration */
};
+enum {
+ VIA_IDFLAG_SINGLE = (1 << 0), /* single channel controller) */
+};
+
/*
* VIA SouthBridge chips.
*/
@@ -97,12 +101,17 @@ static const struct via_isa_bridge {
u8 rev_max;
u16 flags;
} via_isa_bridges[] = {
+ { "vx855", PCI_DEVICE_ID_VIA_VX855, 0x00, 0x2f,
+ VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
{ "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, VIA_UDMA_133 |
VIA_BAD_AST | VIA_SATA_PATA },
+ { "vt8261", PCI_DEVICE_ID_VIA_8261, 0x00, 0x2f,
+ VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
- { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
+ { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
+ { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
{ "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
@@ -122,6 +131,8 @@ static const struct via_isa_bridge {
{ "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
{ "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
{ "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+ { "vtxxxx", PCI_DEVICE_ID_VIA_ANON, 0x00, 0x2f,
+ VIA_UDMA_133 | VIA_BAD_AST },
{ NULL }
};
@@ -411,46 +422,46 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Early VIA without UDMA support */
static const struct ata_port_info via_mwdma_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &via_port_ops
};
/* Ditto with IRQ masking required */
static const struct ata_port_info via_mwdma_info_borked = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.port_ops = &via_port_ops_noirq,
};
/* VIA UDMA 33 devices (and borked 66) */
static const struct ata_port_info via_udma33_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
.port_ops = &via_port_ops
};
/* VIA UDMA 66 devices */
static const struct ata_port_info via_udma66_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
.port_ops = &via_port_ops
};
/* VIA UDMA 100 devices */
static const struct ata_port_info via_udma100_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &via_port_ops
};
/* UDMA133 with bad AST (All current 133) */
static const struct ata_port_info via_udma133_info = {
.flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */
.port_ops = &via_port_ops
};
@@ -460,6 +471,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int printed_version;
u8 enable;
u32 timing;
+ unsigned long flags = id->driver_data;
int rc;
if (!printed_version++)
@@ -469,9 +481,13 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
+ if (flags & VIA_IDFLAG_SINGLE)
+ ppi[1] = &ata_dummy_port_info;
+
/* To find out how the IDE will behave and what features we
actually have to look at the bridge not the IDE controller */
- for (config = via_isa_bridges; config->id; config++)
+ for (config = via_isa_bridges; config->id != PCI_DEVICE_ID_VIA_ANON;
+ config++)
if ((isa = pci_get_device(PCI_VENDOR_ID_VIA +
!!(config->flags & VIA_BAD_ID),
config->id, NULL))) {
@@ -482,10 +498,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_dev_put(isa);
}
- if (!config->id) {
- printk(KERN_WARNING "via: Unknown VIA SouthBridge, disabling.\n");
- return -ENODEV;
- }
pci_dev_put(isa);
if (!(config->flags & VIA_NO_ENABLES)) {
@@ -582,11 +594,13 @@ static int via_reinit_one(struct pci_dev *pdev)
#endif
static const struct pci_device_id via[] = {
+ { PCI_VDEVICE(VIA, 0x0415), },
{ PCI_VDEVICE(VIA, 0x0571), },
{ PCI_VDEVICE(VIA, 0x0581), },
{ PCI_VDEVICE(VIA, 0x1571), },
{ PCI_VDEVICE(VIA, 0x3164), },
{ PCI_VDEVICE(VIA, 0x5324), },
+ { PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE },
{ },
};
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index 319e164a3d7..6d8619b6f67 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -193,7 +193,7 @@ static __init int winbond_init_one(unsigned long port)
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port);
ap->ops = &winbond_port_ops;
- ap->pio_mask = 0x1F;
+ ap->pio_mask = ATA_PIO4;
ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ioaddr.cmd_addr = cmd_addr;
ap->ioaddr.altstatus_addr = ctl_addr;
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index be53545c9f6..39588178d02 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -148,6 +148,8 @@ static struct scsi_host_template adma_ata_sht = {
static struct ata_port_operations adma_ata_ops = {
.inherits = &ata_sff_port_ops,
+ .lost_interrupt = ATA_OP_NULL,
+
.check_atapi_dma = adma_check_atapi_dma,
.qc_prep = adma_qc_prep,
.qc_issue = adma_qc_issue,
@@ -166,7 +168,7 @@ static struct ata_port_info adma_port_info[] = {
.flags = ATA_FLAG_SLAVE_POSS |
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
ATA_FLAG_PIO_POLLING,
- .pio_mask = 0x10, /* pio4 */
+ .pio_mask = ATA_PIO4_ONLY,
.udma_mask = ATA_UDMA4,
.port_ops = &adma_ata_ops,
},
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 1a56db92ff7..c2e90e1fece 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1279,8 +1279,8 @@ static struct ata_port_operations sata_fsl_ops = {
static const struct ata_port_info sata_fsl_port_info[] = {
{
.flags = SATA_FSL_HOST_FLAGS,
- .pio_mask = 0x1f, /* pio 0-4 */
- .udma_mask = 0x7f, /* udma 0-6 */
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
.port_ops = &sata_fsl_ops,
},
};
@@ -1288,7 +1288,7 @@ static const struct ata_port_info sata_fsl_port_info[] = {
static int sata_fsl_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
- int retval = 0;
+ int retval = -ENXIO;
void __iomem *hcr_base = NULL;
void __iomem *ssr_base = NULL;
void __iomem *csr_base = NULL;
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index fbbd87c96f1..305a4f825f5 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -744,8 +744,8 @@ static struct ata_port_operations inic_port_ops = {
static struct ata_port_info inic_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &inic_port_ops
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 86918634a4c..a377226b81c 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1,10 +1,13 @@
/*
* sata_mv.c - Marvell SATA support
*
- * Copyright 2008: Marvell Corporation, all rights reserved.
+ * Copyright 2008-2009: Marvell Corporation, all rights reserved.
* Copyright 2005: EMC Corporation, all rights reserved.
* Copyright 2005 Red Hat, Inc. All rights reserved.
*
+ * Originally written by Brett Russ.
+ * Extensive overhaul and enhancement by Mark Lord <mlord@pobox.com>.
+ *
* Please ALWAYS copy linux-ide@vger.kernel.org on emails.
*
* This program is free software; you can redistribute it and/or modify
@@ -25,24 +28,13 @@
/*
* sata_mv TODO list:
*
- * --> Errata workaround for NCQ device errors.
- *
* --> More errata workarounds for PCI-X.
*
* --> Complete a full errata audit for all chipsets to identify others.
*
- * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
- *
- * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
- *
- * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
- *
* --> Develop a low-power-consumption strategy, and implement it.
*
- * --> [Experiment, low priority] Investigate interrupt coalescing.
- * Quite often, especially with PCI Message Signalled Interrupts (MSI),
- * the overhead reduced by interrupt mitigation is quite often not
- * worth the latency cost.
+ * --> Add sysfs attributes for per-chip / per-HC IRQ coalescing thresholds.
*
* --> [Experiment, Marvell value added] Is it possible to use target
* mode to cross-connect two Linux boxes with Marvell cards? If so,
@@ -72,7 +64,27 @@
#include <linux/libata.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "1.24"
+#define DRV_VERSION "1.27"
+
+/*
+ * module options
+ */
+
+static int msi;
+#ifdef CONFIG_PCI
+module_param(msi, int, S_IRUGO);
+MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+#endif
+
+static int irq_coalescing_io_count;
+module_param(irq_coalescing_io_count, int, S_IRUGO);
+MODULE_PARM_DESC(irq_coalescing_io_count,
+ "IRQ coalescing I/O count threshold (0..255)");
+
+static int irq_coalescing_usecs;
+module_param(irq_coalescing_usecs, int, S_IRUGO);
+MODULE_PARM_DESC(irq_coalescing_usecs,
+ "IRQ coalescing time threshold in usecs");
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -83,13 +95,32 @@ enum {
MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */
MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */
+ /* For use with both IRQ coalescing methods ("all ports" or "per-HC" */
+ COAL_CLOCKS_PER_USEC = 150, /* for calculating COAL_TIMEs */
+ MAX_COAL_TIME_THRESHOLD = ((1 << 24) - 1), /* internal clocks count */
+ MAX_COAL_IO_COUNT = 255, /* completed I/O count */
+
MV_PCI_REG_BASE = 0,
- MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
- MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08),
- MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88),
- MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c),
- MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc),
- MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0),
+
+ /*
+ * Per-chip ("all ports") interrupt coalescing feature.
+ * This is only for GEN_II / GEN_IIE hardware.
+ *
+ * Coalescing defers the interrupt until either the IO_THRESHOLD
+ * (count of completed I/Os) is met, or the TIME_THRESHOLD is met.
+ */
+ MV_COAL_REG_BASE = 0x18000,
+ MV_IRQ_COAL_CAUSE = (MV_COAL_REG_BASE + 0x08),
+ ALL_PORTS_COAL_IRQ = (1 << 4), /* all ports irq event */
+
+ MV_IRQ_COAL_IO_THRESHOLD = (MV_COAL_REG_BASE + 0xcc),
+ MV_IRQ_COAL_TIME_THRESHOLD = (MV_COAL_REG_BASE + 0xd0),
+
+ /*
+ * Registers for the (unused here) transaction coalescing feature:
+ */
+ MV_TRAN_COAL_CAUSE_LO = (MV_COAL_REG_BASE + 0x88),
+ MV_TRAN_COAL_CAUSE_HI = (MV_COAL_REG_BASE + 0x8c),
MV_SATAHC0_REG_BASE = 0x20000,
MV_FLASH_CTL_OFS = 0x1046c,
@@ -121,17 +152,16 @@ enum {
/* Host Flags */
MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
- MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
- ATA_FLAG_PIO_POLLING,
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
- MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
+ MV_GEN_I_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI,
- MV_GENIIE_FLAGS = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
- ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
- ATA_FLAG_NCQ | ATA_FLAG_AN,
+ MV_GEN_II_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NCQ |
+ ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA,
+
+ MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN,
CRQB_FLAG_READ = (1 << 0),
CRQB_TAG_SHIFT = 1,
@@ -184,16 +214,18 @@ enum {
PCI_HC_MAIN_IRQ_MASK_OFS = 0x1d64,
SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020,
SOC_HC_MAIN_IRQ_MASK_OFS = 0x20024,
- ERR_IRQ = (1 << 0), /* shift by port # */
- DONE_IRQ = (1 << 1), /* shift by port # */
+ ERR_IRQ = (1 << 0), /* shift by (2 * port #) */
+ DONE_IRQ = (1 << 1), /* shift by (2 * port #) */
HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
HC_SHIFT = 9, /* bits 9-17 = HC1's ports */
+ DONE_IRQ_0_3 = 0x000000aa, /* DONE_IRQ ports 0,1,2,3 */
+ DONE_IRQ_4_7 = (DONE_IRQ_0_3 << HC_SHIFT), /* 4,5,6,7 */
PCI_ERR = (1 << 18),
- TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */
- TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */
- PORTS_0_3_COAL_DONE = (1 << 8),
- PORTS_4_7_COAL_DONE = (1 << 17),
- PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */
+ TRAN_COAL_LO_DONE = (1 << 19), /* transaction coalescing */
+ TRAN_COAL_HI_DONE = (1 << 20), /* transaction coalescing */
+ PORTS_0_3_COAL_DONE = (1 << 8), /* HC0 IRQ coalescing */
+ PORTS_4_7_COAL_DONE = (1 << 17), /* HC1 IRQ coalescing */
+ ALL_PORTS_COAL_DONE = (1 << 21), /* GEN_II(E) IRQ coalescing */
GPIO_INT = (1 << 22),
SELF_INT = (1 << 23),
TWSI_INT = (1 << 24),
@@ -209,6 +241,21 @@ enum {
HC_COAL_IRQ = (1 << 4), /* IRQ coalescing */
DEV_IRQ = (1 << 8), /* shift by port # */
+ /*
+ * Per-HC (Host-Controller) interrupt coalescing feature.
+ * This is present on all chip generations.
+ *
+ * Coalescing defers the interrupt until either the IO_THRESHOLD
+ * (count of completed I/Os) is met, or the TIME_THRESHOLD is met.
+ */
+ HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c,
+ HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010,
+
+ SOC_LED_CTRL_OFS = 0x2c,
+ SOC_LED_CTRL_BLINK = (1 << 0), /* Active LED blink */
+ SOC_LED_CTRL_ACT_PRESENCE = (1 << 2), /* Multiplex dev presence */
+ /* with dev activity LED */
+
/* Shadow block registers */
SHD_BLK_OFS = 0x100,
SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */
@@ -350,8 +397,12 @@ enum {
EDMA_ARB_CFG_OFS = 0x38,
EDMA_HALTCOND_OFS = 0x60, /* GenIIe halt conditions */
+ EDMA_UNKNOWN_RSVD_OFS = 0x6C, /* GenIIe unknown/reserved */
- GEN_II_NCQ_MAX_SECTORS = 256, /* max sects/io on Gen2 w/NCQ */
+ BMDMA_CMD_OFS = 0x224, /* bmdma command register */
+ BMDMA_STATUS_OFS = 0x228, /* bmdma status register */
+ BMDMA_PRD_LOW_OFS = 0x22c, /* bmdma PRD addr 31:0 */
+ BMDMA_PRD_HIGH_OFS = 0x230, /* bmdma PRD addr 63:32 */
/* Host private flags (hp_flags) */
MV_HP_FLAG_MSI = (1 << 0),
@@ -365,12 +416,14 @@ enum {
MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */
MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */
MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */
+ MV_HP_QUIRK_LED_BLINK_EN = (1 << 12), /* is led blinking enabled? */
/* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */
MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */
MV_PP_FLAG_DELAYED_EH = (1 << 3), /* delayed dev err handling */
+ MV_PP_FLAG_FAKE_ATA_BUSY = (1 << 4), /* ignore initial ATA_DRDY */
};
#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
@@ -439,6 +492,18 @@ struct mv_sg {
__le32 reserved;
};
+/*
+ * We keep a local cache of a few frequently accessed port
+ * registers here, to avoid having to read them (very slow)
+ * when switching between EDMA and non-EDMA modes.
+ */
+struct mv_cached_regs {
+ u32 fiscfg;
+ u32 ltmode;
+ u32 haltcond;
+ u32 unknown_rsvd;
+};
+
struct mv_port_priv {
struct mv_crqb *crqb;
dma_addr_t crqb_dma;
@@ -451,6 +516,7 @@ struct mv_port_priv {
unsigned int resp_idx;
u32 pp_flags;
+ struct mv_cached_regs cached;
unsigned int delayed_eh_pmp_map;
};
@@ -541,7 +607,7 @@ static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
unsigned int port_no);
static int mv_stop_edma(struct ata_port *ap);
static int mv_stop_edma_engine(void __iomem *port_mmio);
-static void mv_edma_cfg(struct ata_port *ap, int want_ncq);
+static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma);
static void mv_pmp_select(struct ata_port *ap, int pmp);
static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
@@ -552,6 +618,14 @@ static void mv_pmp_error_handler(struct ata_port *ap);
static void mv_process_crpb_entries(struct ata_port *ap,
struct mv_port_priv *pp);
+static void mv_sff_irq_clear(struct ata_port *ap);
+static int mv_check_atapi_dma(struct ata_queued_cmd *qc);
+static void mv_bmdma_setup(struct ata_queued_cmd *qc);
+static void mv_bmdma_start(struct ata_queued_cmd *qc);
+static void mv_bmdma_stop(struct ata_queued_cmd *qc);
+static u8 mv_bmdma_status(struct ata_port *ap);
+static u8 mv_sff_check_status(struct ata_port *ap);
+
/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
* because we have to allow room for worst case splitting of
* PRDs for 64K boundaries in mv_fill_sg().
@@ -572,6 +646,8 @@ static struct scsi_host_template mv6_sht = {
static struct ata_port_operations mv5_ops = {
.inherits = &ata_sff_port_ops,
+ .lost_interrupt = ATA_OP_NULL,
+
.qc_defer = mv_qc_defer,
.qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue,
@@ -599,6 +675,14 @@ static struct ata_port_operations mv6_ops = {
.pmp_softreset = mv_softreset,
.softreset = mv_softreset,
.error_handler = mv_pmp_error_handler,
+
+ .sff_check_status = mv_sff_check_status,
+ .sff_irq_clear = mv_sff_irq_clear,
+ .check_atapi_dma = mv_check_atapi_dma,
+ .bmdma_setup = mv_bmdma_setup,
+ .bmdma_start = mv_bmdma_start,
+ .bmdma_stop = mv_bmdma_stop,
+ .bmdma_status = mv_bmdma_status,
};
static struct ata_port_operations mv_iie_ops = {
@@ -609,53 +693,49 @@ static struct ata_port_operations mv_iie_ops = {
static const struct ata_port_info mv_port_info[] = {
{ /* chip_504x */
- .flags = MV_COMMON_FLAGS,
+ .flags = MV_GEN_I_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_508x */
- .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
+ .flags = MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_5080 */
- .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
+ .flags = MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_604x */
- .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
- ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
- ATA_FLAG_NCQ,
+ .flags = MV_GEN_II_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv6_ops,
},
{ /* chip_608x */
- .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
- ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
- ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
+ .flags = MV_GEN_II_FLAGS | MV_FLAG_DUAL_HC,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv6_ops,
},
{ /* chip_6042 */
- .flags = MV_GENIIE_FLAGS,
+ .flags = MV_GEN_IIE_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
},
{ /* chip_7042 */
- .flags = MV_GENIIE_FLAGS,
+ .flags = MV_GEN_IIE_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
},
{ /* chip_soc */
- .flags = MV_GENIIE_FLAGS,
+ .flags = MV_GEN_IIE_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
@@ -669,8 +749,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
/* RocketRAID 1720/174x have different identifiers */
{ PCI_VDEVICE(TTI, 0x1720), chip_6042 },
- { PCI_VDEVICE(TTI, 0x1740), chip_508x },
- { PCI_VDEVICE(TTI, 0x1742), chip_508x },
+ { PCI_VDEVICE(TTI, 0x1740), chip_6042 },
+ { PCI_VDEVICE(TTI, 0x1742), chip_6042 },
{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
@@ -800,6 +880,44 @@ static inline int mv_get_hc_count(unsigned long port_flags)
return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
}
+/**
+ * mv_save_cached_regs - (re-)initialize cached port registers
+ * @ap: the port whose registers we are caching
+ *
+ * Initialize the local cache of port registers,
+ * so that reading them over and over again can
+ * be avoided on the hotter paths of this driver.
+ * This saves a few microseconds each time we switch
+ * to/from EDMA mode to perform (eg.) a drive cache flush.
+ */
+static void mv_save_cached_regs(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_port_priv *pp = ap->private_data;
+
+ pp->cached.fiscfg = readl(port_mmio + FISCFG_OFS);
+ pp->cached.ltmode = readl(port_mmio + LTMODE_OFS);
+ pp->cached.haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
+ pp->cached.unknown_rsvd = readl(port_mmio + EDMA_UNKNOWN_RSVD_OFS);
+}
+
+/**
+ * mv_write_cached_reg - write to a cached port register
+ * @addr: hardware address of the register
+ * @old: pointer to cached value of the register
+ * @new: new value for the register
+ *
+ * Write a new value to a cached register,
+ * but only if the value is different from before.
+ */
+static inline void mv_write_cached_reg(void __iomem *addr, u32 *old, u32 new)
+{
+ if (new != *old) {
+ *old = new;
+ writel(new, addr);
+ }
+}
+
static void mv_set_edma_ptrs(void __iomem *port_mmio,
struct mv_host_priv *hpriv,
struct mv_port_priv *pp)
@@ -831,6 +949,23 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
}
+static void mv_write_main_irq_mask(u32 mask, struct mv_host_priv *hpriv)
+{
+ /*
+ * When writing to the main_irq_mask in hardware,
+ * we must ensure exclusivity between the interrupt coalescing bits
+ * and the corresponding individual port DONE_IRQ bits.
+ *
+ * Note that this register is really an "IRQ enable" register,
+ * not an "IRQ mask" register as Marvell's naming might suggest.
+ */
+ if (mask & (ALL_PORTS_COAL_DONE | PORTS_0_3_COAL_DONE))
+ mask &= ~DONE_IRQ_0_3;
+ if (mask & (ALL_PORTS_COAL_DONE | PORTS_4_7_COAL_DONE))
+ mask &= ~DONE_IRQ_4_7;
+ writelfl(mask, hpriv->main_irq_mask_addr);
+}
+
static void mv_set_main_irq_mask(struct ata_host *host,
u32 disable_bits, u32 enable_bits)
{
@@ -841,7 +976,7 @@ static void mv_set_main_irq_mask(struct ata_host *host,
new_mask = (old_mask & ~disable_bits) | enable_bits;
if (new_mask != old_mask) {
hpriv->main_irq_mask = new_mask;
- writelfl(new_mask, hpriv->main_irq_mask_addr);
+ mv_write_main_irq_mask(new_mask, hpriv);
}
}
@@ -858,8 +993,94 @@ static void mv_enable_port_irqs(struct ata_port *ap,
mv_set_main_irq_mask(ap->host, disable_bits, enable_bits);
}
+static void mv_clear_and_enable_port_irqs(struct ata_port *ap,
+ void __iomem *port_mmio,
+ unsigned int port_irqs)
+{
+ struct mv_host_priv *hpriv = ap->host->private_data;
+ int hardport = mv_hardport_from_port(ap->port_no);
+ void __iomem *hc_mmio = mv_hc_base_from_port(
+ mv_host_base(ap->host), ap->port_no);
+ u32 hc_irq_cause;
+
+ /* clear EDMA event indicators, if any */
+ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ /* clear pending irq events */
+ hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport);
+ writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+
+ /* clear FIS IRQ Cause */
+ if (IS_GEN_IIE(hpriv))
+ writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+
+ mv_enable_port_irqs(ap, port_irqs);
+}
+
+static void mv_set_irq_coalescing(struct ata_host *host,
+ unsigned int count, unsigned int usecs)
+{
+ struct mv_host_priv *hpriv = host->private_data;
+ void __iomem *mmio = hpriv->base, *hc_mmio;
+ u32 coal_enable = 0;
+ unsigned long flags;
+ unsigned int clks, is_dual_hc = hpriv->n_ports > MV_PORTS_PER_HC;
+ const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+ ALL_PORTS_COAL_DONE;
+
+ /* Disable IRQ coalescing if either threshold is zero */
+ if (!usecs || !count) {
+ clks = count = 0;
+ } else {
+ /* Respect maximum limits of the hardware */
+ clks = usecs * COAL_CLOCKS_PER_USEC;
+ if (clks > MAX_COAL_TIME_THRESHOLD)
+ clks = MAX_COAL_TIME_THRESHOLD;
+ if (count > MAX_COAL_IO_COUNT)
+ count = MAX_COAL_IO_COUNT;
+ }
+
+ spin_lock_irqsave(&host->lock, flags);
+ mv_set_main_irq_mask(host, coal_disable, 0);
+
+ if (is_dual_hc && !IS_GEN_I(hpriv)) {
+ /*
+ * GEN_II/GEN_IIE with dual host controllers:
+ * one set of global thresholds for the entire chip.
+ */
+ writel(clks, mmio + MV_IRQ_COAL_TIME_THRESHOLD);
+ writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD);
+ /* clear leftover coal IRQ bit */
+ writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE);
+ if (count)
+ coal_enable = ALL_PORTS_COAL_DONE;
+ clks = count = 0; /* force clearing of regular regs below */
+ }
+
+ /*
+ * All chips: independent thresholds for each HC on the chip.
+ */
+ hc_mmio = mv_hc_base_from_port(mmio, 0);
+ writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS);
+ writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS);
+ writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS);
+ if (count)
+ coal_enable |= PORTS_0_3_COAL_DONE;
+ if (is_dual_hc) {
+ hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC);
+ writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS);
+ writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS);
+ writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS);
+ if (count)
+ coal_enable |= PORTS_4_7_COAL_DONE;
+ }
+
+ mv_set_main_irq_mask(host, 0, coal_enable);
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
/**
- * mv_start_dma - Enable eDMA engine
+ * mv_start_edma - Enable eDMA engine
* @base: port base address
* @pp: port private data
*
@@ -869,7 +1090,7 @@ static void mv_enable_port_irqs(struct ata_port *ap,
* LOCKING:
* Inherited from caller.
*/
-static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+static void mv_start_edma(struct ata_port *ap, void __iomem *port_mmio,
struct mv_port_priv *pp, u8 protocol)
{
int want_ncq = (protocol == ATA_PROT_NCQ);
@@ -881,30 +1102,11 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
}
if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
struct mv_host_priv *hpriv = ap->host->private_data;
- int hardport = mv_hardport_from_port(ap->port_no);
- void __iomem *hc_mmio = mv_hc_base_from_port(
- mv_host_base(ap->host), hardport);
- u32 hc_irq_cause, ipending;
-
- /* clear EDMA event indicators, if any */
- writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
- /* clear EDMA interrupt indicator, if any */
- hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
- ipending = (DEV_IRQ | DMA_IRQ) << hardport;
- if (hc_irq_cause & ipending) {
- writelfl(hc_irq_cause & ~ipending,
- hc_mmio + HC_IRQ_CAUSE_OFS);
- }
- mv_edma_cfg(ap, want_ncq);
-
- /* clear FIS IRQ Cause */
- if (IS_GEN_IIE(hpriv))
- writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+ mv_edma_cfg(ap, want_ncq, 1);
mv_set_edma_ptrs(port_mmio, hpriv, pp);
- mv_enable_port_irqs(ap, DONE_IRQ|ERR_IRQ);
+ mv_clear_and_enable_port_irqs(ap, port_mmio, DONE_IRQ|ERR_IRQ);
writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
@@ -962,6 +1164,7 @@ static int mv_stop_edma(struct ata_port *ap)
{
void __iomem *port_mmio = mv_ap_base(ap);
struct mv_port_priv *pp = ap->private_data;
+ int err = 0;
if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN))
return 0;
@@ -969,9 +1172,10 @@ static int mv_stop_edma(struct ata_port *ap)
mv_wait_for_edma_empty_idle(ap);
if (mv_stop_edma_engine(port_mmio)) {
ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
- return -EIO;
+ err = -EIO;
}
- return 0;
+ mv_edma_cfg(ap, 0, 0);
+ return err;
}
#ifdef ATA_DEBUG
@@ -1099,20 +1303,12 @@ static void mv6_dev_config(struct ata_device *adev)
*
* Gen-II does not support NCQ over a port multiplier
* (no FIS-based switching).
- *
- * We don't have hob_nsect when doing NCQ commands on Gen-II.
- * See mv_qc_prep() for more info.
*/
if (adev->flags & ATA_DFLAG_NCQ) {
if (sata_pmp_attached(adev->link->ap)) {
adev->flags &= ~ATA_DFLAG_NCQ;
ata_dev_printk(adev, KERN_INFO,
"NCQ disabled for command-based switching\n");
- } else if (adev->max_sectors > GEN_II_NCQ_MAX_SECTORS) {
- adev->max_sectors = GEN_II_NCQ_MAX_SECTORS;
- ata_dev_printk(adev, KERN_INFO,
- "max_sectors limited to %u for NCQ\n",
- adev->max_sectors);
}
}
}
@@ -1148,35 +1344,33 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
return ATA_DEFER_PORT;
}
-static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs)
+static void mv_config_fbs(struct ata_port *ap, int want_ncq, int want_fbs)
{
- u32 new_fiscfg, old_fiscfg;
- u32 new_ltmode, old_ltmode;
- u32 new_haltcond, old_haltcond;
+ struct mv_port_priv *pp = ap->private_data;
+ void __iomem *port_mmio;
- old_fiscfg = readl(port_mmio + FISCFG_OFS);
- old_ltmode = readl(port_mmio + LTMODE_OFS);
- old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
+ u32 fiscfg, *old_fiscfg = &pp->cached.fiscfg;
+ u32 ltmode, *old_ltmode = &pp->cached.ltmode;
+ u32 haltcond, *old_haltcond = &pp->cached.haltcond;
- new_fiscfg = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
- new_ltmode = old_ltmode & ~LTMODE_BIT8;
- new_haltcond = old_haltcond | EDMA_ERR_DEV;
+ ltmode = *old_ltmode & ~LTMODE_BIT8;
+ haltcond = *old_haltcond | EDMA_ERR_DEV;
if (want_fbs) {
- new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC;
- new_ltmode = old_ltmode | LTMODE_BIT8;
+ fiscfg = *old_fiscfg | FISCFG_SINGLE_SYNC;
+ ltmode = *old_ltmode | LTMODE_BIT8;
if (want_ncq)
- new_haltcond &= ~EDMA_ERR_DEV;
+ haltcond &= ~EDMA_ERR_DEV;
else
- new_fiscfg |= FISCFG_WAIT_DEV_ERR;
+ fiscfg |= FISCFG_WAIT_DEV_ERR;
+ } else {
+ fiscfg = *old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
}
- if (new_fiscfg != old_fiscfg)
- writelfl(new_fiscfg, port_mmio + FISCFG_OFS);
- if (new_ltmode != old_ltmode)
- writelfl(new_ltmode, port_mmio + LTMODE_OFS);
- if (new_haltcond != old_haltcond)
- writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS);
+ port_mmio = mv_ap_base(ap);
+ mv_write_cached_reg(port_mmio + FISCFG_OFS, old_fiscfg, fiscfg);
+ mv_write_cached_reg(port_mmio + LTMODE_OFS, old_ltmode, ltmode);
+ mv_write_cached_reg(port_mmio + EDMA_HALTCOND_OFS, old_haltcond, haltcond);
}
static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq)
@@ -1194,7 +1388,86 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq)
writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS);
}
-static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
+/**
+ * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma
+ * @ap: Port being initialized
+ *
+ * There are two DMA modes on these chips: basic DMA, and EDMA.
+ *
+ * Bit-0 of the "EDMA RESERVED" register enables/disables use
+ * of basic DMA on the GEN_IIE versions of the chips.
+ *
+ * This bit survives EDMA resets, and must be set for basic DMA
+ * to function, and should be cleared when EDMA is active.
+ */
+static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma)
+{
+ struct mv_port_priv *pp = ap->private_data;
+ u32 new, *old = &pp->cached.unknown_rsvd;
+
+ if (enable_bmdma)
+ new = *old | 1;
+ else
+ new = *old & ~1;
+ mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new);
+}
+
+/*
+ * SOC chips have an issue whereby the HDD LEDs don't always blink
+ * during I/O when NCQ is enabled. Enabling a special "LED blink" mode
+ * of the SOC takes care of it, generating a steady blink rate when
+ * any drive on the chip is active.
+ *
+ * Unfortunately, the blink mode is a global hardware setting for the SOC,
+ * so we must use it whenever at least one port on the SOC has NCQ enabled.
+ *
+ * We turn "LED blink" off when NCQ is not in use anywhere, because the normal
+ * LED operation works then, and provides better (more accurate) feedback.
+ *
+ * Note that this code assumes that an SOC never has more than one HC onboard.
+ */
+static void mv_soc_led_blink_enable(struct ata_port *ap)
+{
+ struct ata_host *host = ap->host;
+ struct mv_host_priv *hpriv = host->private_data;
+ void __iomem *hc_mmio;
+ u32 led_ctrl;
+
+ if (hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN)
+ return;
+ hpriv->hp_flags |= MV_HP_QUIRK_LED_BLINK_EN;
+ hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no);
+ led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS);
+ writel(led_ctrl | SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS);
+}
+
+static void mv_soc_led_blink_disable(struct ata_port *ap)
+{
+ struct ata_host *host = ap->host;
+ struct mv_host_priv *hpriv = host->private_data;
+ void __iomem *hc_mmio;
+ u32 led_ctrl;
+ unsigned int port;
+
+ if (!(hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN))
+ return;
+
+ /* disable led-blink only if no ports are using NCQ */
+ for (port = 0; port < hpriv->n_ports; port++) {
+ struct ata_port *this_ap = host->ports[port];
+ struct mv_port_priv *pp = this_ap->private_data;
+
+ if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
+ return;
+ }
+
+ hpriv->hp_flags &= ~MV_HP_QUIRK_LED_BLINK_EN;
+ hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no);
+ led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS);
+ writel(led_ctrl & ~SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS);
+}
+
+static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma)
{
u32 cfg;
struct mv_port_priv *pp = ap->private_data;
@@ -1203,7 +1476,8 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
/* set up non-NCQ EDMA configuration */
cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */
- pp->pp_flags &= ~MV_PP_FLAG_FBS_EN;
+ pp->pp_flags &=
+ ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY);
if (IS_GEN_I(hpriv))
cfg |= (1 << 8); /* enab config burst size mask */
@@ -1224,7 +1498,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
*/
want_fbs &= want_ncq;
- mv_config_fbs(port_mmio, want_ncq, want_fbs);
+ mv_config_fbs(ap, want_ncq, want_fbs);
if (want_fbs) {
pp->pp_flags |= MV_PP_FLAG_FBS_EN;
@@ -1232,18 +1506,27 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
}
cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
- cfg |= (1 << 22); /* enab 4-entry host queue cache */
- if (!IS_SOC(hpriv))
- cfg |= (1 << 18); /* enab early completion */
+ if (want_edma) {
+ cfg |= (1 << 22); /* enab 4-entry host queue cache */
+ if (!IS_SOC(hpriv))
+ cfg |= (1 << 18); /* enab early completion */
+ }
if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
+ mv_bmdma_enable_iie(ap, !want_edma);
+
+ if (IS_SOC(hpriv)) {
+ if (want_ncq)
+ mv_soc_led_blink_enable(ap);
+ else
+ mv_soc_led_blink_disable(ap);
+ }
}
if (want_ncq) {
cfg |= EDMA_CFG_NCQ;
pp->pp_flags |= MV_PP_FLAG_NCQ_EN;
- } else
- pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
+ }
writelfl(cfg, port_mmio + EDMA_CFG_OFS);
}
@@ -1327,6 +1610,8 @@ static int mv_port_start(struct ata_port *ap)
pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
}
}
+ mv_save_cached_regs(ap);
+ mv_edma_cfg(ap, 0, 0);
return 0;
out_port_free_dma_mem:
@@ -1375,12 +1660,13 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
u32 offset = addr & 0xffff;
u32 len = sg_len;
- if ((offset + sg_len > 0x10000))
+ if (offset + len > 0x10000)
len = 0x10000 - offset;
mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
mv_sg->flags_size = cpu_to_le32(len & 0xffff);
+ mv_sg->reserved = 0;
sg_len -= len;
addr += len;
@@ -1392,6 +1678,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
if (likely(last_sg))
last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+ mb(); /* ensure data structure is visible to the chipset */
}
static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
@@ -1402,6 +1689,147 @@ static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
}
/**
+ * mv_sff_irq_clear - Clear hardware interrupt after DMA.
+ * @ap: Port associated with this ATA transaction.
+ *
+ * We need this only for ATAPI bmdma transactions,
+ * as otherwise we experience spurious interrupts
+ * after libata-sff handles the bmdma interrupts.
+ */
+static void mv_sff_irq_clear(struct ata_port *ap)
+{
+ mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), ERR_IRQ);
+}
+
+/**
+ * mv_check_atapi_dma - Filter ATAPI cmds which are unsuitable for DMA.
+ * @qc: queued command to check for chipset/DMA compatibility.
+ *
+ * The bmdma engines cannot handle speculative data sizes
+ * (bytecount under/over flow). So only allow DMA for
+ * data transfer commands with known data sizes.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+
+ if (scmd) {
+ switch (scmd->cmnd[0]) {
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case GPCMD_READ_CD:
+ case GPCMD_SEND_DVD_STRUCTURE:
+ case GPCMD_SEND_CUE_SHEET:
+ return 0; /* DMA is safe */
+ }
+ }
+ return -EOPNOTSUPP; /* use PIO instead */
+}
+
+/**
+ * mv_bmdma_setup - Set up BMDMA transaction
+ * @qc: queued command to prepare DMA for.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_bmdma_setup(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_port_priv *pp = ap->private_data;
+
+ mv_fill_sg(qc);
+
+ /* clear all DMA cmd bits */
+ writel(0, port_mmio + BMDMA_CMD_OFS);
+
+ /* load PRD table addr. */
+ writel((pp->sg_tbl_dma[qc->tag] >> 16) >> 16,
+ port_mmio + BMDMA_PRD_HIGH_OFS);
+ writelfl(pp->sg_tbl_dma[qc->tag],
+ port_mmio + BMDMA_PRD_LOW_OFS);
+
+ /* issue r/w command */
+ ap->ops->sff_exec_command(ap, &qc->tf);
+}
+
+/**
+ * mv_bmdma_start - Start a BMDMA transaction
+ * @qc: queued command to start DMA on.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_bmdma_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *port_mmio = mv_ap_base(ap);
+ unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+ u32 cmd = (rw ? 0 : ATA_DMA_WR) | ATA_DMA_START;
+
+ /* start host DMA transaction */
+ writelfl(cmd, port_mmio + BMDMA_CMD_OFS);
+}
+
+/**
+ * mv_bmdma_stop - Stop BMDMA transfer
+ * @qc: queued command to stop DMA on.
+ *
+ * Clears the ATA_DMA_START flag in the bmdma control register
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *port_mmio = mv_ap_base(ap);
+ u32 cmd;
+
+ /* clear start/stop bit */
+ cmd = readl(port_mmio + BMDMA_CMD_OFS);
+ cmd &= ~ATA_DMA_START;
+ writelfl(cmd, port_mmio + BMDMA_CMD_OFS);
+
+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+ ata_sff_dma_pause(ap);
+}
+
+/**
+ * mv_bmdma_status - Read BMDMA status
+ * @ap: port for which to retrieve DMA status.
+ *
+ * Read and return equivalent of the sff BMDMA status register.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static u8 mv_bmdma_status(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ u32 reg, status;
+
+ /*
+ * Other bits are valid only if ATA_DMA_ACTIVE==0,
+ * and the ATA_DMA_INTR bit doesn't exist.
+ */
+ reg = readl(port_mmio + BMDMA_STATUS_OFS);
+ if (reg & ATA_DMA_ACTIVE)
+ status = ATA_DMA_ACTIVE;
+ else
+ status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR;
+ return status;
+}
+
+/**
* mv_qc_prep - Host specific command preparation.
* @qc: queued command to prepare
*
@@ -1450,7 +1878,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
* only 11 bytes...so we must pick and choose required
* registers based on the command. So, we drop feature and
* hob_feature for [RW] DMA commands, but they are needed for
- * NCQ. NCQ will drop hob_nsect.
+ * NCQ. NCQ will drop hob_nsect, which is not needed there
+ * (nsect is used only for the tag; feat/hob_feat hold true nsect).
*/
switch (tf->command) {
case ATA_CMD_READ:
@@ -1562,6 +1991,132 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
}
/**
+ * mv_sff_check_status - fetch device status, if valid
+ * @ap: ATA port to fetch status from
+ *
+ * When using command issue via mv_qc_issue_fis(),
+ * the initial ATA_BUSY state does not show up in the
+ * ATA status (shadow) register. This can confuse libata!
+ *
+ * So we have a hook here to fake ATA_BUSY for that situation,
+ * until the first time a BUSY, DRQ, or ERR bit is seen.
+ *
+ * The rest of the time, it simply returns the ATA status register.
+ */
+static u8 mv_sff_check_status(struct ata_port *ap)
+{
+ u8 stat = ioread8(ap->ioaddr.status_addr);
+ struct mv_port_priv *pp = ap->private_data;
+
+ if (pp->pp_flags & MV_PP_FLAG_FAKE_ATA_BUSY) {
+ if (stat & (ATA_BUSY | ATA_DRQ | ATA_ERR))
+ pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY;
+ else
+ stat = ATA_BUSY;
+ }
+ return stat;
+}
+
+/**
+ * mv_send_fis - Send a FIS, using the "Vendor-Unique FIS" register
+ * @fis: fis to be sent
+ * @nwords: number of 32-bit words in the fis
+ */
+static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ u32 ifctl, old_ifctl, ifstat;
+ int i, timeout = 200, final_word = nwords - 1;
+
+ /* Initiate FIS transmission mode */
+ old_ifctl = readl(port_mmio + SATA_IFCTL_OFS);
+ ifctl = 0x100 | (old_ifctl & 0xf);
+ writelfl(ifctl, port_mmio + SATA_IFCTL_OFS);
+
+ /* Send all words of the FIS except for the final word */
+ for (i = 0; i < final_word; ++i)
+ writel(fis[i], port_mmio + VENDOR_UNIQUE_FIS_OFS);
+
+ /* Flag end-of-transmission, and then send the final word */
+ writelfl(ifctl | 0x200, port_mmio + SATA_IFCTL_OFS);
+ writelfl(fis[final_word], port_mmio + VENDOR_UNIQUE_FIS_OFS);
+
+ /*
+ * Wait for FIS transmission to complete.
+ * This typically takes just a single iteration.
+ */
+ do {
+ ifstat = readl(port_mmio + SATA_IFSTAT_OFS);
+ } while (!(ifstat & 0x1000) && --timeout);
+
+ /* Restore original port configuration */
+ writelfl(old_ifctl, port_mmio + SATA_IFCTL_OFS);
+
+ /* See if it worked */
+ if ((ifstat & 0x3000) != 0x1000) {
+ ata_port_printk(ap, KERN_WARNING,
+ "%s transmission error, ifstat=%08x\n",
+ __func__, ifstat);
+ return AC_ERR_OTHER;
+ }
+ return 0;
+}
+
+/**
+ * mv_qc_issue_fis - Issue a command directly as a FIS
+ * @qc: queued command to start
+ *
+ * Note that the ATA shadow registers are not updated
+ * after command issue, so the device will appear "READY"
+ * if polled, even while it is BUSY processing the command.
+ *
+ * So we use a status hook to fake ATA_BUSY until the drive changes state.
+ *
+ * Note: we don't get updated shadow regs on *completion*
+ * of non-data commands. So avoid sending them via this function,
+ * as they will appear to have completed immediately.
+ *
+ * GEN_IIE has special registers that we could get the result tf from,
+ * but earlier chipsets do not. For now, we ignore those registers.
+ */
+static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct mv_port_priv *pp = ap->private_data;
+ struct ata_link *link = qc->dev->link;
+ u32 fis[5];
+ int err = 0;
+
+ ata_tf_to_fis(&qc->tf, link->pmp, 1, (void *)fis);
+ err = mv_send_fis(ap, fis, sizeof(fis) / sizeof(fis[0]));
+ if (err)
+ return err;
+
+ switch (qc->tf.protocol) {
+ case ATAPI_PROT_PIO:
+ pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY;
+ /* fall through */
+ case ATAPI_PROT_NODATA:
+ ap->hsm_task_state = HSM_ST_FIRST;
+ break;
+ case ATA_PROT_PIO:
+ pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY;
+ if (qc->tf.flags & ATA_TFLAG_WRITE)
+ ap->hsm_task_state = HSM_ST_FIRST;
+ else
+ ap->hsm_task_state = HSM_ST;
+ break;
+ default:
+ ap->hsm_task_state = HSM_ST_LAST;
+ break;
+ }
+
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ ata_pio_queue_task(ap, qc, 0);
+ return 0;
+}
+
+/**
* mv_qc_issue - Initiate a command to the host
* @qc: queued command to start
*
@@ -1575,14 +2130,28 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
*/
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
{
+ static int limit_warnings = 10;
struct ata_port *ap = qc->ap;
void __iomem *port_mmio = mv_ap_base(ap);
struct mv_port_priv *pp = ap->private_data;
u32 in_index;
+ unsigned int port_irqs;
- if ((qc->tf.protocol != ATA_PROT_DMA) &&
- (qc->tf.protocol != ATA_PROT_NCQ)) {
- static int limit_warnings = 10;
+ pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; /* paranoia */
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ case ATA_PROT_NCQ:
+ mv_start_edma(ap, port_mmio, pp, qc->tf.protocol);
+ pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
+ in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+
+ /* Write the request in pointer to kick the EDMA to life */
+ writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+ port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ return 0;
+
+ case ATA_PROT_PIO:
/*
* Errata SATA#16, SATA#24: warn if multiple DRQs expected.
*
@@ -1600,27 +2169,46 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
": attempting PIO w/multiple DRQ: "
"this may fail due to h/w errata\n");
}
- /*
- * We're about to send a non-EDMA capable command to the
- * port. Turn off EDMA so there won't be problems accessing
- * shadow block, etc registers.
- */
- mv_stop_edma(ap);
- mv_enable_port_irqs(ap, ERR_IRQ);
- mv_pmp_select(ap, qc->dev->link->pmp);
- return ata_sff_qc_issue(qc);
+ /* drop through */
+ case ATA_PROT_NODATA:
+ case ATAPI_PROT_PIO:
+ case ATAPI_PROT_NODATA:
+ if (ap->flags & ATA_FLAG_PIO_POLLING)
+ qc->tf.flags |= ATA_TFLAG_POLLING;
+ break;
}
- mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
-
- pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
- in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ port_irqs = ERR_IRQ; /* mask device interrupt when polling */
+ else
+ port_irqs = ERR_IRQ | DONE_IRQ; /* unmask all interrupts */
- /* and write the request in pointer to kick the EDMA to life */
- writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
- port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ /*
+ * We're about to send a non-EDMA capable command to the
+ * port. Turn off EDMA so there won't be problems accessing
+ * shadow block, etc registers.
+ */
+ mv_stop_edma(ap);
+ mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs);
+ mv_pmp_select(ap, qc->dev->link->pmp);
- return 0;
+ if (qc->tf.command == ATA_CMD_READ_LOG_EXT) {
+ struct mv_host_priv *hpriv = ap->host->private_data;
+ /*
+ * Workaround for 88SX60x1 FEr SATA#25 (part 2).
+ *
+ * After any NCQ error, the READ_LOG_EXT command
+ * from libata-eh *must* use mv_qc_issue_fis().
+ * Otherwise it might fail, due to chip errata.
+ *
+ * Rather than special-case it, we'll just *always*
+ * use this method here for READ_LOG_EXT, making for
+ * easier testing.
+ */
+ if (IS_GEN_II(hpriv))
+ return mv_qc_issue_fis(qc);
+ }
+ return ata_sff_qc_issue(qc);
}
static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
@@ -1631,8 +2219,12 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
return NULL;
qc = ata_qc_from_tag(ap, ap->link.active_tag);
- if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
- qc = NULL;
+ if (qc) {
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ qc = NULL;
+ else if (!(qc->flags & ATA_QCFLAG_ACTIVE))
+ qc = NULL;
+ }
return qc;
}
@@ -2101,6 +2693,10 @@ static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
void __iomem *mmio = hpriv->base, *hc_mmio;
unsigned int handled = 0, port;
+ /* If asserted, clear the "all ports" IRQ coalescing bit */
+ if (main_irq_cause & ALL_PORTS_COAL_DONE)
+ writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE);
+
for (port = 0; port < hpriv->n_ports; port++) {
struct ata_port *ap = host->ports[port];
unsigned int p, shift, hardport, port_cause;
@@ -2133,6 +2729,8 @@ static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
* to ack (only) those ports via hc_irq_cause.
*/
ack_irqs = 0;
+ if (hc_cause & PORTS_0_3_COAL_DONE)
+ ack_irqs = HC_COAL_IRQ;
for (p = 0; p < MV_PORTS_PER_HC; ++p) {
if ((port + p) >= hpriv->n_ports)
break;
@@ -2214,9 +2812,15 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
struct ata_host *host = dev_instance;
struct mv_host_priv *hpriv = host->private_data;
unsigned int handled = 0;
+ int using_msi = hpriv->hp_flags & MV_HP_FLAG_MSI;
u32 main_irq_cause, pending_irqs;
spin_lock(&host->lock);
+
+ /* for MSI: block new interrupts while in here */
+ if (using_msi)
+ mv_write_main_irq_mask(0, hpriv);
+
main_irq_cause = readl(hpriv->main_irq_cause_addr);
pending_irqs = main_irq_cause & hpriv->main_irq_mask;
/*
@@ -2229,7 +2833,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
else
handled = mv_host_intr(host, pending_irqs);
}
+
+ /* for MSI: unmask; interrupt cause bits will retrigger now */
+ if (using_msi)
+ mv_write_main_irq_mask(hpriv->main_irq_mask, hpriv);
+
spin_unlock(&host->lock);
+
return IRQ_RETVAL(handled);
}
@@ -2779,6 +3389,8 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
mv_reset_channel(hpriv, mmio, ap->port_no);
pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ pp->pp_flags &=
+ ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY);
/* Workaround for errata FEr SATA#10 (part 2) */
do {
@@ -2798,6 +3410,8 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
extra = HZ; /* only extend it once, max */
}
} while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123);
+ mv_save_cached_regs(ap);
+ mv_edma_cfg(ap, 0, 0);
return rc;
}
@@ -2821,8 +3435,7 @@ static void mv_eh_thaw(struct ata_port *ap)
writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
/* clear pending irq events */
- hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
- hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
+ hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport);
writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
mv_enable_port_irqs(ap, ERR_IRQ);
@@ -3075,6 +3688,9 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
}
+ /* initialize shadow irq mask with register's value */
+ hpriv->main_irq_mask = readl(hpriv->main_irq_mask_addr);
+
/* global interrupt mask: 0 == mask everything */
mv_set_main_irq_mask(host, ~0, 0);
@@ -3118,19 +3734,19 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
}
- if (!IS_SOC(hpriv)) {
- /* Clear any currently outstanding host interrupt conditions */
- writelfl(0, mmio + hpriv->irq_cause_ofs);
+ /* Clear any currently outstanding host interrupt conditions */
+ writelfl(0, mmio + hpriv->irq_cause_ofs);
- /* and unmask interrupt generation for host regs */
- writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
+ /* and unmask interrupt generation for host regs */
+ writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
- /*
- * enable only global host interrupts for now.
- * The per-port interrupts get done later as ports are set up.
- */
- mv_set_main_irq_mask(host, 0, PCI_ERR);
- }
+ /*
+ * enable only global host interrupts for now.
+ * The per-port interrupts get done later as ports are set up.
+ */
+ mv_set_main_irq_mask(host, 0, PCI_ERR);
+ mv_set_irq_coalescing(host, irq_coalescing_io_count,
+ irq_coalescing_usecs);
done:
return rc;
}
@@ -3292,12 +3908,6 @@ static struct pci_driver mv_pci_driver = {
.remove = ata_pci_remove_one,
};
-/*
- * module options
- */
-static int msi; /* Use PCI msi; either zero (off, default) or non-zero */
-
-
/* move to PCI layer or libata core? */
static int pci_go_64(struct pci_dev *pdev)
{
@@ -3430,9 +4040,9 @@ static int mv_pci_init_one(struct pci_dev *pdev,
if (rc)
return rc;
- /* Enable interrupts */
- if (msi && pci_enable_msi(pdev))
- pci_intx(pdev, 1);
+ /* Enable message-switched interrupts, if requested */
+ if (msi && pci_enable_msi(pdev) == 0)
+ hpriv->hp_flags |= MV_HP_FLAG_MSI;
mv_dump_pci_cfg(pdev, 0x68);
mv_print_info(host);
@@ -3479,10 +4089,5 @@ MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_NAME);
-#ifdef CONFIG_PCI
-module_param(msi, int, 0444);
-MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
-#endif
-
module_init(mv_init);
module_exit(mv_exit);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 6f146061432..6cda12ba812 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -57,9 +57,9 @@ enum {
NV_MMIO_BAR = 5,
NV_PORTS = 2,
- NV_PIO_MASK = 0x1f,
- NV_MWDMA_MASK = 0x07,
- NV_UDMA_MASK = 0x7f,
+ NV_PIO_MASK = ATA_PIO4,
+ NV_MWDMA_MASK = ATA_MWDMA2,
+ NV_UDMA_MASK = ATA_UDMA6,
NV_PORT0_SCR_REG_OFFSET = 0x00,
NV_PORT1_SCR_REG_OFFSET = 0x40,
@@ -305,10 +305,10 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
+static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
-static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
static void nv_ck804_freeze(struct ata_port *ap);
static void nv_ck804_thaw(struct ata_port *ap);
static int nv_adma_slave_config(struct scsi_device *sdev);
@@ -352,6 +352,7 @@ enum nv_host_type
NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
CK804,
ADMA,
+ MCP5x,
SWNCQ,
};
@@ -363,10 +364,10 @@ static const struct pci_device_id nv_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), MCP5x },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), MCP5x },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), MCP5x },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), MCP5x },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
@@ -407,6 +408,7 @@ static struct scsi_host_template nv_swncq_sht = {
static struct ata_port_operations nv_common_ops = {
.inherits = &ata_bmdma_port_ops,
+ .lost_interrupt = ATA_OP_NULL,
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
};
@@ -420,26 +422,33 @@ static struct ata_port_operations nv_generic_ops = {
.hardreset = ATA_OP_NULL,
};
-/* OSDL bz3352 reports that nf2/3 controllers can't determine device
- * signature reliably. Also, the following thread reports detection
- * failure on cold boot with the standard debouncing timing.
+/* nf2 is ripe with hardreset related problems.
+ *
+ * kernel bz#3352 reports nf2/3 controllers can't determine device
+ * signature reliably. The following thread reports detection failure
+ * on cold boot with the standard debouncing timing.
*
* http://thread.gmane.org/gmane.linux.ide/34098
*
- * Debounce with hotplug timing and request follow-up SRST.
+ * And bz#12176 reports that hardreset simply doesn't work on nf2.
+ * Give up on it and just don't do hardreset.
*/
static struct ata_port_operations nv_nf2_ops = {
- .inherits = &nv_common_ops,
+ .inherits = &nv_generic_ops,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
- .hardreset = nv_nf2_hardreset,
};
-/* CK804 finally gets hardreset right */
+/* For initial probing after boot and hot plugging, hardreset mostly
+ * works fine on CK804 but curiously, reprobing on the initial port by
+ * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
+ * in somewhat undeterministic way. Use noclassify hardreset.
+ */
static struct ata_port_operations nv_ck804_ops = {
.inherits = &nv_common_ops,
.freeze = nv_ck804_freeze,
.thaw = nv_ck804_thaw,
+ .hardreset = nv_noclassify_hardreset,
.host_stop = nv_ck804_host_stop,
};
@@ -467,8 +476,19 @@ static struct ata_port_operations nv_adma_ops = {
.host_stop = nv_adma_host_stop,
};
+/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
+ * work, hardreset should be used and hardreset can't report proper
+ * signature, which suggests that mcp5x is closer to nf2 as long as
+ * reset quirkiness is concerned. Define separate ops for mcp5x with
+ * nv_noclassify_hardreset().
+ */
+static struct ata_port_operations nv_mcp5x_ops = {
+ .inherits = &nv_common_ops,
+ .hardreset = nv_noclassify_hardreset,
+};
+
static struct ata_port_operations nv_swncq_ops = {
- .inherits = &nv_generic_ops,
+ .inherits = &nv_mcp5x_ops,
.qc_defer = ata_std_qc_defer,
.qc_prep = nv_swncq_qc_prep,
@@ -531,6 +551,15 @@ static const struct ata_port_info nv_port_info[] = {
.port_ops = &nv_adma_ops,
.private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
},
+ /* MCP5x */
+ {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_mcp5x_ops,
+ .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
+ },
/* SWNCQ */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -1530,6 +1559,17 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
return 0;
}
+static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ bool online;
+ int rc;
+
+ rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
+ &online, NULL);
+ return online ? -EAGAIN : rc;
+}
+
static void nv_nf2_freeze(struct ata_port *ap)
{
void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
@@ -1554,17 +1594,6 @@ static void nv_nf2_thaw(struct ata_port *ap)
iowrite8(mask, scr_addr + NV_INT_ENABLE);
}
-static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
-{
- bool online;
- int rc;
-
- rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
- &online, NULL);
- return online ? -EAGAIN : rc;
-}
-
static void nv_ck804_freeze(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
@@ -2355,14 +2384,9 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (type == CK804 && adma_enabled) {
dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
type = ADMA;
- }
-
- if (type == SWNCQ) {
- if (swncq_enabled)
- dev_printk(KERN_NOTICE, &pdev->dev,
- "Using SWNCQ mode\n");
- else
- type = GENERIC;
+ } else if (type == MCP5x && swncq_enabled) {
+ dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
+ type = SWNCQ;
}
ppi[0] = &nv_port_info[type];
@@ -2500,7 +2524,7 @@ static void __exit nv_exit(void)
module_init(nv_init);
module_exit(nv_exit);
module_param_named(adma, adma_enabled, bool, 0444);
-MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
module_param_named(swncq, swncq_enabled, bool, 0444);
MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index ba9a2570a74..b1fd7d62071 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -176,7 +176,9 @@ static const struct ata_port_operations pdc_common_ops = {
.check_atapi_dma = pdc_check_atapi_dma,
.qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue,
+
.sff_irq_clear = pdc_irq_clear,
+ .lost_interrupt = ATA_OP_NULL,
.post_internal_cmd = pdc_post_internal_cmd,
.error_handler = pdc_error_handler,
@@ -213,8 +215,8 @@ static const struct ata_port_info pdc_port_info[] = {
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_SATA_PATA,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_old_sata_ops,
},
@@ -222,8 +224,8 @@ static const struct ata_port_info pdc_port_info[] = {
[board_2037x_pata] =
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -232,8 +234,8 @@ static const struct ata_port_info pdc_port_info[] = {
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_4_PORTS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_old_sata_ops,
},
@@ -242,8 +244,8 @@ static const struct ata_port_info pdc_port_info[] = {
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
PDC_FLAG_4_PORTS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -252,8 +254,8 @@ static const struct ata_port_info pdc_port_info[] = {
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_sata_ops,
},
@@ -262,8 +264,8 @@ static const struct ata_port_info pdc_port_info[] = {
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
PDC_FLAG_GEN_II,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -272,8 +274,8 @@ static const struct ata_port_info pdc_port_info[] = {
{
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_sata_ops,
},
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index a000c86ac85..c3936d35cda 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -147,6 +147,7 @@ static struct ata_port_operations qs_ata_ops = {
.softreset = ATA_OP_NULL,
.error_handler = qs_error_handler,
.post_internal_cmd = ATA_OP_NULL,
+ .lost_interrupt = ATA_OP_NULL,
.scr_read = qs_scr_read,
.scr_write = qs_scr_write,
@@ -160,7 +161,7 @@ static const struct ata_port_info qs_port_info[] = {
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
- .pio_mask = 0x10, /* pio4 */
+ .pio_mask = ATA_PIO4_ONLY,
.udma_mask = ATA_UDMA6,
.port_ops = &qs_ata_ops,
},
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 564c142b03b..e67ce8e5caa 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -44,6 +44,7 @@
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
+#include <linux/dmi.h>
#define DRV_NAME "sata_sil"
#define DRV_VERSION "2.4"
@@ -199,8 +200,8 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3112 */
{
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
@@ -208,24 +209,24 @@ static const struct ata_port_info sil_port_info[] = {
{
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
SIL_FLAG_NO_SATA_IRQ,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3512 */
{
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3114 */
{
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
@@ -323,7 +324,7 @@ static void sil_fill_sg(struct ata_queued_cmd *qc)
prd->addr = cpu_to_le32(addr);
prd->flags_len = cpu_to_le32(sg_len);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len);
last_prd = prd;
prd++;
@@ -695,11 +696,38 @@ static void sil_init_controller(struct ata_host *host)
}
}
+static bool sil_broken_system_poweroff(struct pci_dev *pdev)
+{
+ static const struct dmi_system_id broken_systems[] = {
+ {
+ .ident = "HP Compaq nx6325",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x12UL,
+ },
+
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+ if (dmi) {
+ unsigned long slot = (unsigned long)dmi->driver_data;
+ /* apply the quirk only to on-board controllers */
+ return slot == PCI_SLOT(pdev->devfn);
+ }
+
+ return false;
+}
+
static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
int board_id = ent->driver_data;
- const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL };
+ struct ata_port_info pi = sil_port_info[board_id];
+ const struct ata_port_info *ppi[] = { &pi, NULL };
struct ata_host *host;
void __iomem *mmio_base;
int n_ports, rc;
@@ -713,6 +741,13 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (board_id == sil_3114)
n_ports = 4;
+ if (sil_broken_system_poweroff(pdev)) {
+ pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN |
+ ATA_FLAG_NO_HIBERNATE_SPINDOWN;
+ dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
+ "on poweroff and hibernation\n");
+ }
+
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
if (!host)
return -ENOMEM;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 2590c2279fa..0d8990dcdfc 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -429,25 +429,25 @@ static const struct ata_port_info sil24_port_info[] = {
{
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
SIL24_FLAG_PCIX_IRQ_WOC,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil24_ops,
},
/* sil_3132 */
{
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil24_ops,
},
/* sil_3131/sil_3531 */
{
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil24_ops,
},
};
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 9c43b4e7c4a..8f983322861 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -97,8 +97,8 @@ static struct ata_port_operations sis_ops = {
static const struct ata_port_info sis_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x7,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &sis_ops,
};
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 609d147813a..7257f2d5c52 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -361,8 +361,8 @@ static const struct ata_port_info k2_port_info[] = {
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
@@ -371,8 +371,8 @@ static const struct ata_port_info k2_port_info[] = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
K2_FLAG_SATA_8_PORTS,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
@@ -380,8 +380,8 @@ static const struct ata_port_info k2_port_info[] = {
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
@@ -389,8 +389,8 @@ static const struct ata_port_info k2_port_info[] = {
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index ec04b8d3c79..dce3dccced3 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -265,8 +265,8 @@ static const struct ata_port_info pdc_port_info[] = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO |
ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &pdc_20621_ops,
},
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 019575bb3e0..e5bff47e8aa 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -89,7 +89,7 @@ static struct ata_port_operations uli_ops = {
static const struct ata_port_info uli_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_IGN_SIMPLEX,
- .pio_mask = 0x1f, /* pio0-4 */
+ .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &uli_ops,
};
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index c18935f0bda..98e8c50703b 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -92,6 +92,8 @@ static const struct pci_device_id svia_pci_tbl[] = {
{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
+ { PCI_VDEVICE(VIA, 0x9000), vt8251 },
+ { PCI_VDEVICE(VIA, 0x9040), vt8251 },
{ } /* terminate list */
};
@@ -144,24 +146,24 @@ static struct ata_port_operations vt8251_ops = {
static const struct ata_port_info vt6420_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &vt6420_sata_ops,
};
static struct ata_port_info vt6421_sport_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &vt6421_sata_ops,
};
static struct ata_port_info vt6421_pport_info = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f,
- .mwdma_mask = 0,
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA6,
.port_ops = &vt6421_pata_ops,
};
@@ -169,8 +171,8 @@ static struct ata_port_info vt6421_pport_info = {
static struct ata_port_info vt8251_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &vt8251_ops,
};
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index c57cdff9e6b..ed70bd28fa2 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -308,6 +308,9 @@ static struct scsi_host_template vsc_sata_sht = {
static struct ata_port_operations vsc_sata_ops = {
.inherits = &ata_bmdma_port_ops,
+ /* The IRQ handling is not quite standard SFF behaviour so we
+ cannot use the default lost interrupt handler */
+ .lost_interrupt = ATA_OP_NULL,
.sff_tf_load = vsc_sata_tf_load,
.sff_tf_read = vsc_sata_tf_read,
.freeze = vsc_freeze,
@@ -345,8 +348,8 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev,
static const struct ata_port_info pi = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO,
- .pio_mask = 0x1f,
- .mwdma_mask = 0x07,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &vsc_sata_ops,
};