|
@@ -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)
|