aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 6bd930b93bcc..fdc9bcbe55a2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -641,6 +641,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
641 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */ 641 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */
642 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */ 642 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */
643 { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq }, /* Linux ID */ 643 { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq }, /* Linux ID */
644 { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_yesncq }, /* Linux ID */
645 { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_yesncq }, /* Linux ID */
646 { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_yesncq }, /* Linux ID */
647 { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_yesncq }, /* Linux ID */
648 { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_yesncq }, /* Linux ID */
649 { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_yesncq }, /* Linux ID */
650 { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_yesncq }, /* Linux ID */
651 { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_yesncq }, /* Linux ID */
652 { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_yesncq }, /* Linux ID */
653 { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_yesncq }, /* Linux ID */
654 { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_yesncq }, /* Linux ID */
655 { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_yesncq }, /* Linux ID */
656 { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_yesncq }, /* Linux ID */
657 { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_yesncq }, /* Linux ID */
658 { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_yesncq }, /* Linux ID */
644 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */ 659 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */
645 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */ 660 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */
646 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */ 661 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */
@@ -2263,7 +2278,7 @@ static void ahci_port_intr(struct ata_port *ap)
2263 struct ahci_port_priv *pp = ap->private_data; 2278 struct ahci_port_priv *pp = ap->private_data;
2264 struct ahci_host_priv *hpriv = ap->host->private_data; 2279 struct ahci_host_priv *hpriv = ap->host->private_data;
2265 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); 2280 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
2266 u32 status, qc_active; 2281 u32 status, qc_active = 0;
2267 int rc; 2282 int rc;
2268 2283
2269 status = readl(port_mmio + PORT_IRQ_STAT); 2284 status = readl(port_mmio + PORT_IRQ_STAT);
@@ -2321,11 +2336,22 @@ static void ahci_port_intr(struct ata_port *ap)
2321 } 2336 }
2322 } 2337 }
2323 2338
2324 /* pp->active_link is valid iff any command is in flight */ 2339 /* pp->active_link is not reliable once FBS is enabled, both
2325 if (ap->qc_active && pp->active_link->sactive) 2340 * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because
2326 qc_active = readl(port_mmio + PORT_SCR_ACT); 2341 * NCQ and non-NCQ commands may be in flight at the same time.
2327 else 2342 */
2328 qc_active = readl(port_mmio + PORT_CMD_ISSUE); 2343 if (pp->fbs_enabled) {
2344 if (ap->qc_active) {
2345 qc_active = readl(port_mmio + PORT_SCR_ACT);
2346 qc_active |= readl(port_mmio + PORT_CMD_ISSUE);
2347 }
2348 } else {
2349 /* pp->active_link is valid iff any command is in flight */
2350 if (ap->qc_active && pp->active_link->sactive)
2351 qc_active = readl(port_mmio + PORT_SCR_ACT);
2352 else
2353 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
2354 }
2329 2355
2330 rc = ata_qc_complete_multiple(ap, qc_active); 2356 rc = ata_qc_complete_multiple(ap, qc_active);
2331 2357
@@ -3022,6 +3048,14 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3022 * On HP dv[4-6] and HDX18 with earlier BIOSen, link 3048 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
3023 * to the harddisk doesn't become online after 3049 * to the harddisk doesn't become online after
3024 * resuming from STR. Warn and fail suspend. 3050 * resuming from STR. Warn and fail suspend.
3051 *
3052 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
3053 *
3054 * Use dates instead of versions to match as HP is
3055 * apparently recycling both product and version
3056 * strings.
3057 *
3058 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
3025 */ 3059 */
3026 { 3060 {
3027 .ident = "dv4", 3061 .ident = "dv4",
@@ -3030,7 +3064,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3030 DMI_MATCH(DMI_PRODUCT_NAME, 3064 DMI_MATCH(DMI_PRODUCT_NAME,
3031 "HP Pavilion dv4 Notebook PC"), 3065 "HP Pavilion dv4 Notebook PC"),
3032 }, 3066 },
3033 .driver_data = "F.30", /* cutoff BIOS version */ 3067 .driver_data = "20090105", /* F.30 */
3034 }, 3068 },
3035 { 3069 {
3036 .ident = "dv5", 3070 .ident = "dv5",
@@ -3039,7 +3073,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3039 DMI_MATCH(DMI_PRODUCT_NAME, 3073 DMI_MATCH(DMI_PRODUCT_NAME,
3040 "HP Pavilion dv5 Notebook PC"), 3074 "HP Pavilion dv5 Notebook PC"),
3041 }, 3075 },
3042 .driver_data = "F.16", /* cutoff BIOS version */ 3076 .driver_data = "20090506", /* F.16 */
3043 }, 3077 },
3044 { 3078 {
3045 .ident = "dv6", 3079 .ident = "dv6",
@@ -3048,7 +3082,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3048 DMI_MATCH(DMI_PRODUCT_NAME, 3082 DMI_MATCH(DMI_PRODUCT_NAME,
3049 "HP Pavilion dv6 Notebook PC"), 3083 "HP Pavilion dv6 Notebook PC"),
3050 }, 3084 },
3051 .driver_data = "F.21", /* cutoff BIOS version */ 3085 .driver_data = "20090423", /* F.21 */
3052 }, 3086 },
3053 { 3087 {
3054 .ident = "HDX18", 3088 .ident = "HDX18",
@@ -3057,7 +3091,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3057 DMI_MATCH(DMI_PRODUCT_NAME, 3091 DMI_MATCH(DMI_PRODUCT_NAME,
3058 "HP HDX18 Notebook PC"), 3092 "HP HDX18 Notebook PC"),
3059 }, 3093 },
3060 .driver_data = "F.23", /* cutoff BIOS version */ 3094 .driver_data = "20090430", /* F.23 */
3061 }, 3095 },
3062 /* 3096 /*
3063 * Acer eMachines G725 has the same problem. BIOS 3097 * Acer eMachines G725 has the same problem. BIOS
@@ -3065,6 +3099,8 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3065 * work. Inbetween, there are V1.06, V2.06 and V3.03 3099 * work. Inbetween, there are V1.06, V2.06 and V3.03
3066 * that we don't have much idea about. For now, 3100 * that we don't have much idea about. For now,
3067 * blacklist anything older than V3.04. 3101 * blacklist anything older than V3.04.
3102 *
3103 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
3068 */ 3104 */
3069 { 3105 {
3070 .ident = "G725", 3106 .ident = "G725",
@@ -3072,19 +3108,21 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
3072 DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 3108 DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
3073 DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 3109 DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
3074 }, 3110 },
3075 .driver_data = "V3.04", /* cutoff BIOS version */ 3111 .driver_data = "20091216", /* V3.04 */
3076 }, 3112 },
3077 { } /* terminate list */ 3113 { } /* terminate list */
3078 }; 3114 };
3079 const struct dmi_system_id *dmi = dmi_first_match(sysids); 3115 const struct dmi_system_id *dmi = dmi_first_match(sysids);
3080 const char *ver; 3116 int year, month, date;
3117 char buf[9];
3081 3118
3082 if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 3119 if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
3083 return false; 3120 return false;
3084 3121
3085 ver = dmi_get_system_info(DMI_BIOS_VERSION); 3122 dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
3123 snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
3086 3124
3087 return !ver || strcmp(ver, dmi->driver_data) < 0; 3125 return strcmp(buf, dmi->driver_data) < 0;
3088} 3126}
3089 3127
3090static bool ahci_broken_online(struct pci_dev *pdev) 3128static bool ahci_broken_online(struct pci_dev *pdev)