3.2.93-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Sui Chen <suichen6@xxxxxxxxx> commit 8bfd174312629866efa535193d9e563768ff4307 upstream. (Correction in this resend: fixed function name acer_sa5_271_workaround; fixed the always-true condition in the function; fixed description.) On the Acer Switch Alpha 12 (model number: SA5-271), the internal SSD may not get detected because the port_map and CAP.nr_ports combination causes the driver to skip the port that is actually connected to the SSD. More specifically, either all SATA ports are identified as DUMMY, or all ports get ``link down'' and never get up again. This problem occurs occasionally. When this problem occurs, CAP may hold a value of 0xC734FF00 or 0xC734FF01 and port_map may hold a value of 0x00 or 0x01. When this problem does not occur, CAP holds a value of 0xC734FF02 and port_map may hold a value of 0x07. Overriding the CAP value to 0xC734FF02 and port_map to 0x7 significantly reduces the occurrence of this problem. Link: https://bugzilla.kernel.org/attachment.cgi?id=253091 Signed-off-by: Sui Chen <suichen6@xxxxxxxxx> Tested-by: Damian Ivanov <damianatorrpm@xxxxxxxxx> Signed-off-by: Tejun Heo <tj@xxxxxxxxxx> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/ata/ahci.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1268,6 +1268,40 @@ static inline void ahci_gtf_filter_worka {} #endif +/* + * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected + * as DUMMY, or detected but eventually get a "link down" and never get up + * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the + * port_map may hold a value of 0x00. + * + * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports + * and can significantly reduce the occurrence of the problem. + * + * https://bugzilla.kernel.org/show_bug.cgi?id=189471 + */ +static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, + struct pci_dev *pdev) +{ + static const struct dmi_system_id sysids[] = { + { + .ident = "Acer Switch Alpha 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") + }, + }, + { } + }; + + if (dmi_check_system(sysids)) { + dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); + if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { + hpriv->port_map = 0x7; + hpriv->cap = 0xC734FF02; + } + } +} + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned int board_id = ent->driver_data; @@ -1407,6 +1441,10 @@ static int ahci_init_one(struct pci_dev "online status unreliable, applying workaround\n"); } + + /* Acer SA5-271 workaround modifies private_data */ + acer_sa5_271_workaround(hpriv, pdev); + /* 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