Izik Weksler wrote: > Tejun, > > If you're sending the patch please send it to this address. Okay, please test the attached patch and please cc linux-ide@xxxxxxxxxxxxxxx when replying. Thanks. -- tejun
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 06f212f..d838bdd 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -44,6 +44,7 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> #include <linux/libata.h> +#include <linux/dmi.h> #define DRV_NAME "ahci" #define DRV_VERSION "2.3" @@ -1631,6 +1632,31 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) } #endif +static void ahci_port_mark_nosrst(struct ata_port *ap) +{ + static struct dmi_system_id sysids[] = { + { + .ident = "P5W DH Deluxe", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTEK COMPUTER INC"), + DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), + }, + }, + { } + }; + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + + /* The second port of the PCI device 00:1f.2 is connected to a + * SIMG PMP which pukes on SRST. + */ + if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && + ap->port_no == 1 && dmi_check_system(sysids)) { + dev_printk(KERN_INFO, &pdev->dev, + "enabling ASUS on-board PMP workaround\n"); + ap->flags |= ATA_FLAG_NO_SRST; + } +} + static int ahci_port_start(struct ata_port *ap) { struct device *dev = ap->host->dev; @@ -1639,6 +1665,8 @@ static int ahci_port_start(struct ata_port *ap) dma_addr_t mem_dma; int rc; + ahci_port_mark_nosrst(ap); + pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ac6ceed..c51fa7f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1759,9 +1759,12 @@ static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, return 0; } -static int ata_eh_followup_srst_needed(int rc, int classify, +static int ata_eh_followup_srst_needed(struct ata_port *ap, + int rc, int classify, const unsigned int *classes) { + if (ap->flags & ATA_FLAG_NO_SRST) + return 0; if (rc == -EAGAIN) return 1; if (rc != 0) @@ -1792,7 +1795,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify, */ action = ehc->i.action; ehc->i.action &= ~ATA_EH_RESET_MASK; - if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && + if (softreset && (!hardreset || (!(ap->flags & ATA_FLAG_NO_SRST) && + !sata_set_spd_needed(ap) && !(action & ATA_EH_HARDRESET)))) ehc->i.action |= ATA_EH_SOFTRESET; else @@ -1855,7 +1859,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, rc = ata_do_reset(ap, reset, classes, deadline); if (reset == hardreset && - ata_eh_followup_srst_needed(rc, classify, classes)) { + ata_eh_followup_srst_needed(ap, rc, classify, classes)) { /* okay, let's do follow-up softreset */ reset = softreset; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h diff --git a/include/linux/libata.h b/include/linux/libata.h index 41978a5..8f98689 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -177,6 +177,7 @@ enum { ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ + ATA_FLAG_NO_SRST = (1 << 18), /* avoid softreset */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be