From 2fcad9d27168b287e3db61f6694254e0afa32f8c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 3 Oct 2009 18:27:29 +0900 Subject: ahci: disable 64bit DMA by default on SB600s Till now only one board, ASUS M2A-VM, can do 64bit dma with recent BIOSen. Enabling 64bit DMA by default already broke three boards. Enabling 64bit DMA isn't worth these regressions. Disable 64bit DMA by default and enable it only on boards which are known to work. Signed-off-by: Tejun Heo Reported-by: Gabriele Balducci Reported-by: maierp@informatik.tu-muenchen.de Cc: Shane Huang Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 60 ++++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 40 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index acd1162712b..c95015986c9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -447,7 +447,8 @@ static const struct ata_port_info ahci_port_info[] = { [board_ahci_sb600] = { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | - AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), + AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | + AHCI_HFLAG_32BIT_ONLY), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, @@ -2650,17 +2651,15 @@ static void ahci_p5wdh_workaround(struct ata_host *host) } } -/* - * SB600 ahci controller on certain boards can't do 64bit DMA with - * older BIOS. - */ -static bool ahci_sb600_32bit_only(struct pci_dev *pdev) +/* only some SB600 ahci controllers can do 64bit DMA */ +static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) { static const struct dmi_system_id sysids[] = { /* * The oldest version known to be broken is 0901 and * working is 1501 which was released on 2007-10-26. - * Force 32bit DMA on anything older than 1501. + * Enable 64bit DMA on 1501 and anything newer. + * * Please read bko#9412 for more info. */ { @@ -2672,48 +2671,29 @@ static bool ahci_sb600_32bit_only(struct pci_dev *pdev) }, .driver_data = "20071026", /* yyyymmdd */ }, - /* - * It's yet unknown whether more recent BIOS fixes the - * problem. Blacklist the whole board for the time - * being. Please read the following thread for more - * info. - * - * http://thread.gmane.org/gmane.linux.ide/42326 - */ - { - .ident = "Gigabyte GA-MA69VM-S2", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, - "Gigabyte Technology Co., Ltd."), - DMI_MATCH(DMI_BOARD_NAME, "GA-MA69VM-S2"), - }, - }, { } }; const struct dmi_system_id *match; + int year, month, date; + char buf[9]; match = dmi_first_match(sysids); if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || !match) return false; - if (match->driver_data) { - int year, month, date; - char buf[9]; - - dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); - snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); - - if (strcmp(buf, match->driver_data) >= 0) - return false; + dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); + snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); + if (strcmp(buf, match->driver_data) >= 0) { + dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n", + match->ident); + return true; + } else { dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " "forcing 32bit DMA, update BIOS\n", match->ident); - } else - dev_printk(KERN_WARNING, &pdev->dev, "%s: this board can't " - "do 64bit DMA, forcing 32bit\n", match->ident); - - return true; + return false; + } } static bool ahci_broken_system_poweroff(struct pci_dev *pdev) @@ -2926,9 +2906,9 @@ 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; - /* apply sb600 32bit only quirk */ - if (ahci_sb600_32bit_only(pdev)) - hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; + /* only some SB600s can do 64bit DMA */ + if (ahci_sb600_enable_64bit(pdev)) + hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) pci_intx(pdev, 1); -- cgit v1.2.3 From c21c8066be5a2870b3e047616e03e9e56a4701a4 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 28 Sep 2009 21:56:07 -0400 Subject: pata_ali: trivial fix of a very frequent spelling mistake something-bility is spelled as something-blity so a grep for 'blit' would find these lines I broke this one out from the rest as it actually changes the output of a kernel message - so it could in theory change the behavior of tools that parse that ouput Signed-off-by: Dirk Hohndel Signed-off-by: Jeff Garzik --- drivers/ata/pata_ali.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index fc9c5d6d7d8..1432dc9d0ab 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -290,7 +290,7 @@ static void ali_warn_atapi_dma(struct ata_device *adev) if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) { ata_dev_printk(adev, KERN_WARNING, - "WARNING: ATAPI DMA disabled for reliablity issues. It can be enabled\n"); + "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n"); ata_dev_printk(adev, KERN_WARNING, "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n"); } -- cgit v1.2.3 From 4c521c8ef0e802f88f1d80352dd1b3d6a6aa1cc8 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Sun, 20 Sep 2009 17:02:31 -0600 Subject: ahci: display all AHCI 1.3 HBA capability flags (v2) Update the AHCI driver to display all of the HBA capabilities defined in the AHCI 1.3 specification. Some of these are in a new CAP2 (HBA Capabilities Extended) register which is only defined on AHCI 1.2 or later. The spec says that undefined registers should always return 0 on read, but to be safe we assume a value of 0 unless the controller reports AHCI version 1.2 or later. The value can also be retrieved through sysfs as with the existing capability field. For example, on an Intel Ibex Peak (PCH) controller: ahci 0000:00:1f.2: flags: 64bit ncq sntf stag pm led clo pmp pio slum part ems sxs apst We don't do anything special with the new flags yet. Also, change the code that displays the flags to use the same bit enumerations that are used to control actual operation. Signed-off-by: Robert Hancock Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 86 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 20 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index c95015986c9..a47d309df2f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -122,6 +122,7 @@ enum { HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ HOST_EM_LOC = 0x1c, /* Enclosure Management location */ HOST_EM_CTL = 0x20, /* Enclosure Management Control */ + HOST_CAP2 = 0x24, /* host capabilities, extended */ /* HOST_CTL bits */ HOST_RESET = (1 << 0), /* reset controller; self-clear */ @@ -129,16 +130,29 @@ enum { HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ /* HOST_CAP bits */ + HOST_CAP_SXS = (1 << 5), /* Supports External SATA */ HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */ - HOST_CAP_SSC = (1 << 14), /* Slumber capable */ + HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */ + HOST_CAP_PART = (1 << 13), /* Partial state capable */ + HOST_CAP_SSC = (1 << 14), /* Slumber state capable */ + HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */ + HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */ HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ + HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_LED = (1 << 25), /* Supports activity LED */ HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ + HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */ HOST_CAP_SNTF = (1 << 29), /* SNotification register */ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ + /* HOST_CAP2 bits */ + HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */ + HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */ + HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */ + /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */ PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */ @@ -267,8 +281,10 @@ struct ahci_em_priv { struct ahci_host_priv { unsigned int flags; /* AHCI_HFLAG_* */ u32 cap; /* cap to use */ + u32 cap2; /* cap2 to use */ u32 port_map; /* port map to use */ u32 saved_cap; /* saved initial cap */ + u32 saved_cap2; /* saved initial cap2 */ u32 saved_port_map; /* saved initial port_map */ u32 em_loc; /* enclosure management location */ }; @@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link); static ssize_t ahci_show_host_caps(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t ahci_show_host_cap2(struct device *dev, + struct device_attribute *attr, char *buf); static ssize_t ahci_show_host_version(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t ahci_show_port_cmd(struct device *dev, struct device_attribute *attr, char *buf); DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); +DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); @@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = { &dev_attr_em_message_type, &dev_attr_em_message, &dev_attr_ahci_host_caps, + &dev_attr_ahci_host_cap2, &dev_attr_ahci_host_version, &dev_attr_ahci_port_cmd, NULL @@ -733,6 +753,16 @@ static ssize_t ahci_show_host_caps(struct device *dev, return sprintf(buf, "%x\n", hpriv->cap); } +static ssize_t ahci_show_host_cap2(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct ata_port *ap = ata_shost_to_port(shost); + struct ahci_host_priv *hpriv = ap->host->private_data; + + return sprintf(buf, "%x\n", hpriv->cap2); +} + static ssize_t ahci_show_host_version(struct device *dev, struct device_attribute *attr, char *buf) { @@ -772,7 +802,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, struct ahci_host_priv *hpriv) { void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; - u32 cap, port_map; + u32 cap, cap2, vers, port_map; int i; int mv; @@ -785,6 +815,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev, hpriv->saved_cap = cap = readl(mmio + HOST_CAP); hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); + /* CAP2 register is only defined for AHCI 1.2 and later */ + vers = readl(mmio + HOST_VERSION); + if ((vers >> 16) > 1 || + ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200)) + hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2); + else + hpriv->saved_cap2 = cap2 = 0; + /* some chips have errata preventing 64bit use */ if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) { dev_printk(KERN_INFO, &pdev->dev, @@ -870,6 +908,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, /* record values to use during operation */ hpriv->cap = cap; + hpriv->cap2 = cap2; hpriv->port_map = port_map; } @@ -888,6 +927,8 @@ static void ahci_restore_initial_config(struct ata_host *host) void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; writel(hpriv->saved_cap, mmio + HOST_CAP); + if (hpriv->saved_cap2) + writel(hpriv->saved_cap2, mmio + HOST_CAP2); writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ } @@ -2535,13 +2576,14 @@ static void ahci_print_info(struct ata_host *host) struct ahci_host_priv *hpriv = host->private_data; struct pci_dev *pdev = to_pci_dev(host->dev); void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; - u32 vers, cap, impl, speed; + u32 vers, cap, cap2, impl, speed; const char *speed_s; u16 cc; const char *scc_s; vers = readl(mmio + HOST_VERSION); cap = hpriv->cap; + cap2 = hpriv->cap2; impl = hpriv->port_map; speed = (cap >> 20) & 0xf; @@ -2584,25 +2626,29 @@ static void ahci_print_info(struct ata_host *host) "flags: " "%s%s%s%s%s%s%s" "%s%s%s%s%s%s%s" - "%s\n" + "%s%s%s%s%s%s\n" , - cap & (1 << 31) ? "64bit " : "", - cap & (1 << 30) ? "ncq " : "", - cap & (1 << 29) ? "sntf " : "", - cap & (1 << 28) ? "ilck " : "", - cap & (1 << 27) ? "stag " : "", - cap & (1 << 26) ? "pm " : "", - cap & (1 << 25) ? "led " : "", - - cap & (1 << 24) ? "clo " : "", - cap & (1 << 19) ? "nz " : "", - cap & (1 << 18) ? "only " : "", - cap & (1 << 17) ? "pmp " : "", - cap & (1 << 15) ? "pio " : "", - cap & (1 << 14) ? "slum " : "", - cap & (1 << 13) ? "part " : "", - cap & (1 << 6) ? "ems ": "" + cap & HOST_CAP_64 ? "64bit " : "", + cap & HOST_CAP_NCQ ? "ncq " : "", + cap & HOST_CAP_SNTF ? "sntf " : "", + cap & HOST_CAP_MPS ? "ilck " : "", + cap & HOST_CAP_SSS ? "stag " : "", + cap & HOST_CAP_ALPM ? "pm " : "", + cap & HOST_CAP_LED ? "led " : "", + cap & HOST_CAP_CLO ? "clo " : "", + cap & HOST_CAP_ONLY ? "only " : "", + cap & HOST_CAP_PMP ? "pmp " : "", + cap & HOST_CAP_FBS ? "fbs " : "", + cap & HOST_CAP_PIO_MULTI ? "pio " : "", + cap & HOST_CAP_SSC ? "slum " : "", + cap & HOST_CAP_PART ? "part " : "", + cap & HOST_CAP_CCC ? "ccc " : "", + cap & HOST_CAP_EMS ? "ems " : "", + cap & HOST_CAP_SXS ? "sxs " : "", + cap2 & HOST_CAP2_APST ? "apst " : "", + cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "", + cap2 & HOST_CAP2_BOH ? "boh " : "" ); } -- cgit v1.2.3 From f1bce7f80e3b400cf29787b0afa9c3042b959017 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 16 Sep 2009 04:16:04 +0900 Subject: libata: cosmetic updates We're about to add more SATA_* and ATA_ACPI_FILTER_* constants. Reformat them in preparation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-acpi.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 01964b6e6f6..719e7d237dc 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -20,16 +20,6 @@ #include -enum { - ATA_ACPI_FILTER_SETXFER = 1 << 0, - ATA_ACPI_FILTER_LOCK = 1 << 1, - ATA_ACPI_FILTER_DIPM = 1 << 2, - - ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER | - ATA_ACPI_FILTER_LOCK | - ATA_ACPI_FILTER_DIPM, -}; - static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM)"); -- cgit v1.2.3 From fa5b561c4ea170caf9759109acc2e961a7e83bea Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 16 Sep 2009 04:17:02 +0900 Subject: libata: implement more acpi filtering options Currently libata-acpi can only filter DIPM among SATA feature enables via _GTF. This patch adds the capability to filter out FPDMA non-zero offset, in-order guarantee and auto-activation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-acpi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 719e7d237dc..960c6a7caa8 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -22,7 +22,7 @@ static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); -MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM)"); +MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)"); #define NO_PORT_MULT 0xffff #define SATA_ADR(root, pmp) (((root) << 16) | (pmp)) @@ -637,12 +637,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, return 1; } - if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM) { + if (tf->command == ATA_CMD_SET_FEATURES && + tf->feature == SETFEATURES_SATA_ENABLE) { /* inhibit enabling DIPM */ - if (tf->command == ATA_CMD_SET_FEATURES && - tf->feature == SETFEATURES_SATA_ENABLE && + if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM && tf->nsect == SATA_DIPM) return 1; + + /* inhibit FPDMA non-zero offset */ + if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_FPDMA_OFFSET && + (tf->nsect == SATA_FPDMA_OFFSET || + tf->nsect == SATA_FPDMA_IN_ORDER)) + return 1; + + /* inhibit FPDMA auto activation */ + if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_FPDMA_AA && + tf->nsect == SATA_FPDMA_AA) + return 1; } return 0; -- cgit v1.2.3 From 110f66d25c33c2259b1125255fa7063ab07b8340 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 16 Sep 2009 04:17:28 +0900 Subject: libata: make gtf_filter per-dev Add ->gtf_filter to ata_device and set it to ata_acpi_gtf_filter when initializing ata_link. This is to allow quirks which apply different gtf filters. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-acpi.c | 17 +++++++++-------- drivers/ata/libata-core.c | 3 +++ drivers/ata/libata.h | 2 ++ 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 960c6a7caa8..b0882cddfd4 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -20,7 +20,7 @@ #include -static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; +unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)"); @@ -603,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev, tf->command = gtf->tf[6]; /* 0x1f7 */ } -static int ata_acpi_filter_tf(const struct ata_taskfile *tf, +static int ata_acpi_filter_tf(struct ata_device *dev, + const struct ata_taskfile *tf, const struct ata_taskfile *ptf) { - if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_SETXFER) { + if (dev->gtf_filter & ATA_ACPI_FILTER_SETXFER) { /* libata doesn't use ACPI to configure transfer mode. * It will only confuse device configuration. Skip. */ @@ -615,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, return 1; } - if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_LOCK) { + if (dev->gtf_filter & ATA_ACPI_FILTER_LOCK) { /* BIOS writers, sorry but we don't wanna lock * features unless the user explicitly said so. */ @@ -640,18 +641,18 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, if (tf->command == ATA_CMD_SET_FEATURES && tf->feature == SETFEATURES_SATA_ENABLE) { /* inhibit enabling DIPM */ - if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM && + if (dev->gtf_filter & ATA_ACPI_FILTER_DIPM && tf->nsect == SATA_DIPM) return 1; /* inhibit FPDMA non-zero offset */ - if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_FPDMA_OFFSET && + if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_OFFSET && (tf->nsect == SATA_FPDMA_OFFSET || tf->nsect == SATA_FPDMA_IN_ORDER)) return 1; /* inhibit FPDMA auto activation */ - if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_FPDMA_AA && + if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_AA && tf->nsect == SATA_FPDMA_AA) return 1; } @@ -705,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, pptf = &ptf; } - if (!ata_acpi_filter_tf(&tf, pptf)) { + if (!ata_acpi_filter_tf(dev, &tf, pptf)) { rtf = tf; err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0ddaf43d68c..b525a098134 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5591,6 +5591,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) dev->link = link; dev->devno = dev - link->device; +#ifdef CONFIG_ATA_ACPI + dev->gtf_filter = ata_acpi_gtf_filter; +#endif ata_dev_init(dev); } } diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index be8e2628f82..823e6309636 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI +extern unsigned int ata_acpi_gtf_filter; + extern void ata_acpi_associate_sata_port(struct ata_port *ap); extern void ata_acpi_associate(struct ata_host *host); extern void ata_acpi_dissociate(struct ata_host *host); -- cgit v1.2.3 From f80ae7e45a0e03da188494c6e947a5c8b0cdfb4a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 16 Sep 2009 04:18:03 +0900 Subject: ahci: filter FPDMA non-zero offset enable for Aspire 3810T Curiously, Aspire 3810T issues many SATA feature enable commands via _GTF, of which one is invalid and another is not supported by the drive. In the process, it also enables FPDMA non-zero offset. However, the feature also needs to be supported and enabled from the controller and it's wrong to enable it from _GTF unless the controller can do it by default. Currently, this ends up enabling FPDMA non-zero offset only on the drive side leading to NCQ command failures and eventual disabling of NCQ. This patch makes libata filter out FPDMA non-zero offset enable for the machine. This was reported by Marcus Meissner in bnc#522790. https://bugzilla.novell.com/show_bug.cgi?id=522790 Reported-by: Marcus Meissner Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a47d309df2f..4edca6eb73a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2884,6 +2884,50 @@ static bool ahci_broken_online(struct pci_dev *pdev) return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); } +static void ahci_gtf_filter_workaround(struct ata_host *host) +{ + static const struct dmi_system_id sysids[] = { + /* + * Aspire 3810T issues a bunch of SATA enable commands + * via _GTF including an invalid one and one which is + * rejected by the device. Among the successful ones + * is FPDMA non-zero offset enable which when enabled + * only on the drive side leads to NCQ command + * failures. Filter it out. + */ + { + .ident = "Aspire 3810T", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), + }, + .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, + }, + { } + }; + const struct dmi_system_id *dmi = dmi_first_match(sysids); + unsigned int filter; + int i; + + if (!dmi) + return; + + filter = (unsigned long)dmi->driver_data; + dev_printk(KERN_INFO, host->dev, + "applying extra ACPI _GTF filter 0x%x for %s\n", + filter, dmi->ident); + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + struct ata_link *link; + struct ata_device *dev; + + ata_for_each_link(link, ap, EDGE) + ata_for_each_dev(dev, link, ALL) + dev->gtf_filter |= filter; + } +} + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; @@ -3049,6 +3093,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* apply workaround for ASUS P5W DH Deluxe mainboard */ ahci_p5wdh_workaround(host); + /* apply gtf filter quirk */ + ahci_gtf_filter_workaround(host); + /* initialize adapter */ rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); if (rc) -- cgit v1.2.3 From 3b761d3d437cffcaf160a5d37eb6b3b186e491d5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 6 Oct 2009 17:08:40 +0900 Subject: libata: fix incorrect link online check during probe While trying to work around spurious detection retries for non-existent devices on slave links, commit 816ab89782ac139a8b65147cca990822bb7e8675 incorrectly added link offline check logic before ata_eh_thaw() was called. This means that if an occupied link goes down briefly at the time that offline check was performed, device class will be cleared to ATA_DEV_NONE and libata wouldn't retry thus failing detection of the device. The offline check should be done after the port is thawed together with online check so that such link glitches can be detected by the interrupt handler and handled properly. Signed-off-by: Tejun Heo Reported-by: Tim Blechmann Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 50 +++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index a04488f0de8..0a97822da21 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify, dev->pio_mode = XFER_PIO_0; dev->flags &= ~ATA_DFLAG_SLEEPING; - if (!ata_phys_link_offline(ata_dev_phys_link(dev))) { - /* apply class override */ - if (lflags & ATA_LFLAG_ASSUME_ATA) - classes[dev->devno] = ATA_DEV_ATA; - else if (lflags & ATA_LFLAG_ASSUME_SEMB) - classes[dev->devno] = ATA_DEV_SEMB_UNSUP; - } else - classes[dev->devno] = ATA_DEV_NONE; + if (ata_phys_link_offline(ata_dev_phys_link(dev))) + continue; + + /* apply class override */ + if (lflags & ATA_LFLAG_ASSUME_ATA) + classes[dev->devno] = ATA_DEV_ATA; + else if (lflags & ATA_LFLAG_ASSUME_SEMB) + classes[dev->devno] = ATA_DEV_SEMB_UNSUP; } /* record current link speed */ @@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify, ap->pflags &= ~ATA_PFLAG_EH_PENDING; spin_unlock_irqrestore(link->ap->lock, flags); - /* Make sure onlineness and classification result correspond. + /* + * Make sure onlineness and classification result correspond. * Hotplug could have happened during reset and some * controllers fail to wait while a drive is spinning up after * being hotplugged causing misdetection. By cross checking - * link onlineness and classification result, those conditions - * can be reliably detected and retried. + * link on/offlineness and classification result, those + * conditions can be reliably detected and retried. */ nr_unknown = 0; ata_for_each_dev(dev, link, ALL) { - /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ - if (classes[dev->devno] == ATA_DEV_UNKNOWN) { - classes[dev->devno] = ATA_DEV_NONE; - if (ata_phys_link_online(ata_dev_phys_link(dev))) + if (ata_phys_link_online(ata_dev_phys_link(dev))) { + if (classes[dev->devno] == ATA_DEV_UNKNOWN) { + ata_dev_printk(dev, KERN_DEBUG, "link online " + "but device misclassifed\n"); + classes[dev->devno] = ATA_DEV_NONE; nr_unknown++; + } + } else if (ata_phys_link_offline(ata_dev_phys_link(dev))) { + if (ata_class_enabled(classes[dev->devno])) + ata_dev_printk(dev, KERN_DEBUG, "link offline, " + "clearing class %d to NONE\n", + classes[dev->devno]); + classes[dev->devno] = ATA_DEV_NONE; + } else if (classes[dev->devno] == ATA_DEV_UNKNOWN) { + ata_dev_printk(dev, KERN_DEBUG, "link status unknown, " + "clearing UNKNOWN to NONE\n"); + classes[dev->devno] = ATA_DEV_NONE; } } if (classify && nr_unknown) { if (try < max_tries) { ata_link_printk(link, KERN_WARNING, "link online but " - "device misclassified, retrying\n"); + "%d devices misclassified, retrying\n", + nr_unknown); failed_link = link; rc = -EAGAIN; goto fail; } ata_link_printk(link, KERN_WARNING, - "link online but device misclassified, " - "device detection might fail\n"); + "link online but %d devices misclassified, " + "device detection might fail\n", nr_unknown); } /* reset successful, schedule revalidation */ -- cgit v1.2.3 From 566b54c8a491654b145b6ae246039e5b4a56e587 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 7 Oct 2009 00:26:57 +0200 Subject: pata_atp867x: fix it to not claim MWDMA support MWDMA modes are not supported by this driver currently. Acked-by: Jung-Ik (John) Lee Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_atp867x.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 7990de925d2..ebfc8ff8651 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -118,20 +118,13 @@ struct atp867x_priv { int pci66mhz; }; -static inline u8 atp867x_speed_to_mode(u8 speed) -{ - return speed - XFER_UDMA_0 + 1; -} - static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct atp867x_priv *dp = ap->private_data; u8 speed = adev->dma_mode; u8 b; - u8 mode; - - mode = atp867x_speed_to_mode(speed); + u8 mode = speed - XFER_UDMA_0 + 1; /* * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed @@ -471,7 +464,6 @@ static int atp867x_init_one(struct pci_dev *pdev, static const struct ata_port_info info_867x = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &atp867x_ops, }; -- cgit v1.2.3 From 64207f59137fd300a869e35b14c15f775c64c6fc Mon Sep 17 00:00:00 2001 From: "John(Jung-Ik) Lee" Date: Wed, 7 Oct 2009 00:27:03 +0200 Subject: pata_atp867x: clarifications in timings calculations and cable detection Signed-off-by: John(Jung-Ik) Lee Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_atp867x.c | 52 +++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 14 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index ebfc8ff8651..27d3148b3d8 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -149,8 +149,10 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) iowrite8(b, dp->dma_mode); } -static int atp867x_get_active_clocks_shifted(unsigned int clk) +static int atp867x_get_active_clocks_shifted(struct ata_port *ap, + unsigned int clk) { + struct atp867x_priv *dp = ap->private_data; unsigned char clocks = clk; switch (clocks) { @@ -159,15 +161,25 @@ static int atp867x_get_active_clocks_shifted(unsigned int clk) break; case 1 ... 7: break; - case 8 ... 12: + case 9 ... 12: clocks = 7; break; default: printk(KERN_WARNING "ATP867X: active %dclk is invalid. " "Using default 8clk.\n", clk); - clocks = 0; /* 8 clk */ - break; + case 8: /* default 8 clk */ + clocks = 0; + goto active_clock_shift_done; } + + /* + * Doc 6.6.9: increase the clock value by 1 for safer PIO speed + * on 66MHz bus + */ + if (dp->pci66mhz && clocks < 7) + clocks++; + +active_clock_shift_done: return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT; } @@ -181,20 +193,19 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk) break; case 1 ... 11: break; - case 12: - clocks = 0; - break; case 13: case 14: - --clocks; + --clocks; /* by the spec */ break; case 15: break; default: printk(KERN_WARNING "ATP867X: recover %dclk is invalid. " - "Using default 15clk.\n", clk); - clocks = 0; /* 12 clk */ + "Using default 12clk.\n", clk); + case 12: /* default 12 clk */ + clocks = 0; break; } + return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT; } @@ -223,10 +234,8 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev) b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK); iowrite8(b, dp->dma_mode); - b = atp867x_get_active_clocks_shifted(t.active) | + b = atp867x_get_active_clocks_shifted(ap, t.active) | atp867x_get_recover_clocks_shifted(t.recover); - if (dp->pci66mhz) - b += 0x10; if (adev->devno & 1) iowrite8(b, dp->slave_piospd); @@ -239,9 +248,24 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev) iowrite8(b, dp->eightb_piospd); } +static int atp867x_cable_override(struct pci_dev *pdev) +{ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_ARTOP && + (pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867A || + pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867B)) { + return 1; + } + return 0; +} + static int atp867x_cable_detect(struct ata_port *ap) { - return ATA_CBL_PATA40_SHORT; + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + + if (atp867x_cable_override(pdev)) + return ATA_CBL_PATA40_SHORT; + + return ATA_CBL_PATA_UNK; } static struct scsi_host_template atp867x_sht = { -- cgit v1.2.3 From c59bcc37cb56e00ae0582339bea948853d600436 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 7 Oct 2009 00:27:19 +0200 Subject: pata_atp867x: PIO support fixes * use 8 clk setting for active clocks == 7 (was 12 clk) * use 12 clk setting for active clocks > 12 (was 8 clk) * do 66MHz bus fixup before mapping active clocks * fix setup of PIO command timings Acked-by: Jung-Ik (John) Lee Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_atp867x.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 27d3148b3d8..4a2cd9a7bad 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -155,30 +155,31 @@ static int atp867x_get_active_clocks_shifted(struct ata_port *ap, struct atp867x_priv *dp = ap->private_data; unsigned char clocks = clk; + /* + * Doc 6.6.9: increase the clock value by 1 for safer PIO speed + * on 66MHz bus + */ + if (dp->pci66mhz) + clocks++; + switch (clocks) { case 0: clocks = 1; break; - case 1 ... 7: - break; - case 9 ... 12: - clocks = 7; + case 1 ... 6: break; default: printk(KERN_WARNING "ATP867X: active %dclk is invalid. " - "Using default 8clk.\n", clk); + "Using 12clk.\n", clk); + case 9 ... 12: + clocks = 7; /* 12 clk */ + break; + case 7: case 8: /* default 8 clk */ clocks = 0; goto active_clock_shift_done; } - /* - * Doc 6.6.9: increase the clock value by 1 for safer PIO speed - * on 66MHz bus - */ - if (dp->pci66mhz && clocks < 7) - clocks++; - active_clock_shift_done: return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT; } @@ -193,7 +194,8 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk) break; case 1 ... 11: break; - case 13: case 14: + case 13: + case 14: --clocks; /* by the spec */ break; case 15: @@ -235,16 +237,16 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev) iowrite8(b, dp->dma_mode); b = atp867x_get_active_clocks_shifted(ap, t.active) | - atp867x_get_recover_clocks_shifted(t.recover); + atp867x_get_recover_clocks_shifted(t.recover); if (adev->devno & 1) iowrite8(b, dp->slave_piospd); else iowrite8(b, dp->mstr_piospd); - /* - * use the same value for comand timing as for PIO timimg - */ + b = atp867x_get_active_clocks_shifted(ap, t.act8b) | + atp867x_get_recover_clocks_shifted(t.rec8b); + iowrite8(b, dp->eightb_piospd); } -- cgit v1.2.3 From 7affb32a32eabbbe42d6746923ec1d0bf7327234 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 7 Oct 2009 00:27:25 +0200 Subject: pata_atp867x: add Power Management support Cc: Jung-Ik (John) Lee Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_atp867x.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 4a2cd9a7bad..6fe7ded40c6 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -533,6 +533,23 @@ err_out: return rc; } +#ifdef CONFIG_PM +static int atp867x_reinit_one(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + int rc; + + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; + + atp867x_fixup(host); + + ata_host_resume(host); + return 0; +} +#endif + static struct pci_device_id atp867x_pci_tbl[] = { { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 }, { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 }, @@ -544,6 +561,10 @@ static struct pci_driver atp867x_driver = { .id_table = atp867x_pci_tbl, .probe = atp867x_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM + .suspend = ata_pci_device_suspend, + .resume = atp867x_reinit_one, +#endif }; static int __init atp867x_init(void) -- cgit v1.2.3 From 8e5132175bebaa26f8ea5036a1e942686c11cab4 Mon Sep 17 00:00:00 2001 From: Markus Trippelsdorf Date: Fri, 9 Oct 2009 05:41:47 +0200 Subject: ahci: Add ifdef wrapper to ahci_gtf_filter_workaround Commit f80ae7e45a0e03da188494c6e947a5c8b0cdfb4a ahci: filter FPDMA non-zero offset enable for Aspire 3810T breaks the current git build for configurations that don't define CONFIG_ATA_ACPI. This adds an ifdef wrapper to ahci_gtf_filter_workaround. Signed-off-by: Markus Trippelsdorf Acked-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 4edca6eb73a..b1a257746a1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2884,6 +2884,7 @@ static bool ahci_broken_online(struct pci_dev *pdev) return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); } +#ifdef CONFIG_ATA_ACPI static void ahci_gtf_filter_workaround(struct ata_host *host) { static const struct dmi_system_id sysids[] = { @@ -2927,6 +2928,10 @@ static void ahci_gtf_filter_workaround(struct ata_host *host) dev->gtf_filter |= filter; } } +#else +static inline void ahci_gtf_filter_workaround(struct ata_host *host) +{} +#endif static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { -- cgit v1.2.3 From 7d948b1114c7eded14e5a31f440af751d70ecde0 Mon Sep 17 00:00:00 2001 From: "JosephChan@via.com.tw" Date: Fri, 16 Oct 2009 15:45:23 +0800 Subject: pata_via: extend the rev_max for VT6330 Fix the VT6330 issue, it's because the rev_max of VT6330 exceeds 0x2f. The VT6415 and VT6330 share the same device ID. Signed-off-by: Joseph Chan Signed-off-by: Jeff Garzik --- drivers/ata/pata_via.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 45657cacec4..88984b803d6 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -111,7 +111,7 @@ static const struct via_isa_bridge { { "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 }, - { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES }, + { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0xff, 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 }, -- cgit v1.2.3 From 726206f84c67303cc004aacfd45d37f9277a29f6 Mon Sep 17 00:00:00 2001 From: peer chen Date: Thu, 15 Oct 2009 16:34:56 +0800 Subject: ahci: Add the AHCI controller Linux Device ID for NVIDIA chipsets. Add the generic device ID for NVIDIA AHCI controller. Signed-off-by: Peer Chen Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index b1a257746a1..8c5c0dd4f6f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -605,6 +605,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq }, /* Linux ID */ { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */ { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */ { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */ -- cgit v1.2.3 From 5deab536654f95345ea11e8ec6ed5c778df348b5 Mon Sep 17 00:00:00 2001 From: Shane Huang Date: Tue, 13 Oct 2009 11:14:00 +0800 Subject: ahci / atiixp / pci quirks: rename AMD SB900 into Hudson-2 This patch renames the code name SB900 into Hudson-2 Signed-off-by: Shane Huang Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 +- drivers/ata/pata_atiixp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 8c5c0dd4f6f..a06f5d6375a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -575,7 +575,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ /* AMD */ - { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD SB900 */ + { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ /* AMD is using RAID class only for ahci controllers */ { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index aa4b3f6ae77..ae4454d4e95 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -246,7 +246,7 @@ static const struct pci_device_id atiixp[] = { { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_SB900_IDE), }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), }, { }, }; -- cgit v1.2.3 From 6489e3262e6b188a1a009b65e8a94b7aa17645b7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 14 Oct 2009 11:18:28 +0900 Subject: sata_nv: make sure link is brough up online when skipping hardreset prereset doesn't bring link online if hardreset is about to happen and nv_hardreset() may skip if conditions are not right so softreset may be entered with non-working link status if the system firmware didn't bring it up before entering OS code which can happen during resume. This patch makes nv_hardreset() to bring up the link if it's skipping reset. This bug was reported by frodone@gmail.com in the following bug entry. http://bugzilla.kernel.org/show_bug.cgi?id=14329 Signed-off-by: Tejun Heo Reported-by: frodone@gmail.com Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 86a40582999..1eb4e020eb5 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1594,9 +1594,21 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class, !ata_dev_enabled(link->device)) sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, NULL, NULL); - else if (!(ehc->i.flags & ATA_EHI_QUIET)) - ata_link_printk(link, KERN_INFO, - "nv: skipping hardreset on occupied port\n"); + else { + const unsigned long *timing = sata_ehc_deb_timing(ehc); + int rc; + + if (!(ehc->i.flags & ATA_EHI_QUIET)) + ata_link_printk(link, KERN_INFO, "nv: skipping " + "hardreset on occupied port\n"); + + /* make sure the link is online */ + rc = sata_link_resume(link, timing, deadline); + /* whine about phy resume failure but proceed */ + if (rc && rc != -EOPNOTSUPP) + ata_link_printk(link, KERN_WARNING, "failed to resume " + "link (errno=%d)\n", rc); + } /* device signature acquisition is unreliable */ return -EAGAIN; -- cgit v1.2.3 From 4f7c2874995ac48a4622755b8bd159eb2fb6d8f4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 15 Oct 2009 23:37:32 +0900 Subject: libata: fix PMP initialization Commit 842faa6c1a1d6faddf3377948e5cf214812c6c90 fixed error handling during attach by not committing detected device class to dev->class while attaching a new device. However, this change missed the PMP class check in the configuration loop causing a new PMP device to go through ata_dev_configure() as if it were an ATA or ATAPI device. As PMP device doesn't have a regular IDENTIFY data, this makes ata_dev_configure() tries to configure a PMP device using an invalid data. For the most part, it wasn't too harmful and went unnoticed but this ends up clearing dev->flags which may have ATA_DFLAG_AN set by sata_pmp_attach(). This means that SATA_PMP_FEAT_NOTIFY ends up being disabled on PMPs and on PMPs which honor the flag breaks hotplug support. This problem was discovered and reported by Ethan Hsiao. Signed-off-by: Tejun Heo Reported-by: Ethan Hsiao Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 0a97822da21..bba2ae5df1c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2981,12 +2981,14 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, * device detection messages backwards. */ ata_for_each_dev(dev, link, ALL) { - if (!(new_mask & (1 << dev->devno)) || - dev->class == ATA_DEV_PMP) + if (!(new_mask & (1 << dev->devno))) continue; dev->class = ehc->classes[dev->devno]; + if (dev->class == ATA_DEV_PMP) + continue; + ehc->i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ehc->i.flags &= ~ATA_EHI_PRINTINFO; -- cgit v1.2.3 From f4b31db92d163df8a639f5a8c8633bdeb6e8432d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 16 Oct 2009 13:00:51 +0900 Subject: libata: fix internal command failure handling When an internal command fails, it should be failed directly without invoking EH. In the original implemetation, this was accomplished by letting internal command bypass failure handling in ata_qc_complete(). However, later changes added post-successful-completion handling to that code path and the success path is no longer adequate as internal command failure path. One of the visible problems is that internal command failure due to timeout or other freeze conditions would spuriously trigger WARN_ON_ONCE() in the success path. This patch updates failure path such that internal command failure handling is contained there. Signed-off-by: Tejun Heo Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b525a098134..d7f0f1b1ae3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5028,12 +5028,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_FAILED; if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { - if (!ata_tag_internal(qc->tag)) { - /* always fill result TF for failed qc */ - fill_result_tf(qc); + /* always fill result TF for failed qc */ + fill_result_tf(qc); + + if (!ata_tag_internal(qc->tag)) ata_qc_schedule_eh(qc); - return; - } + else + __ata_qc_complete(qc); + return; } WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN); -- cgit v1.2.3 From 6d4f950e9ea15816c6a4f266ce6b9e438346771e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 6 Oct 2009 16:07:51 +0100 Subject: pata_sc1200: Fix crash on boot The SC1200 needs a NULL terminator or it may cause a crash on boot. Bug #14227 Also correct a bogus comment as the driver had serializing added so can run dual port. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_sc1200.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index f49814d6fd2..3bbed8322ec 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -235,8 +235,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) .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, }; + const struct ata_port_info *ppi[] = { &info, NULL }; return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL); } -- cgit v1.2.3 From 159a7ff7a13f9a02c75006f40c0561a3a81aefcd Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 12 Oct 2009 15:44:00 -0700 Subject: sata_mv: Prevent PIO commands to be defered too long if traffic in progress. Use excl_link when non NCQ commands are defered, to be sure they are processed as soon as outstanding commands are completed. It prevents some commands to be defered indifinitely when using a port multiplier. Signed-off-by: Gwendal Grignou Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 17f9ff9067a..6f5093b7c8c 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1382,6 +1382,25 @@ static int mv_qc_defer(struct ata_queued_cmd *qc) */ if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH) return ATA_DEFER_PORT; + + /* PIO commands need exclusive link: no other commands [DMA or PIO] + * can run concurrently. + * set excl_link when we want to send a PIO command in DMA mode + * or a non-NCQ command in NCQ mode. + * When we receive a command from that link, and there are no + * outstanding commands, mark a flag to clear excl_link and let + * the command go through. + */ + if (unlikely(ap->excl_link)) { + if (link == ap->excl_link) { + if (ap->nr_active_links) + return ATA_DEFER_PORT; + qc->flags |= ATA_QCFLAG_CLEAR_EXCL; + return 0; + } else + return ATA_DEFER_PORT; + } + /* * If the port is completely idle, then allow the new qc. */ @@ -1395,8 +1414,14 @@ static int mv_qc_defer(struct ata_queued_cmd *qc) * doesn't allow it. */ if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) && - (pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol)) - return 0; + (pp->pp_flags & MV_PP_FLAG_NCQ_EN)) { + if (ata_is_ncq(qc->tf.protocol)) + return 0; + else { + ap->excl_link = link; + return ATA_DEFER_PORT; + } + } return ATA_DEFER_PORT; } -- cgit v1.2.3