diff options
| -rw-r--r-- | drivers/ata/ahci.c | 66 |
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 | ||
| 3090 | static bool ahci_broken_online(struct pci_dev *pdev) | 3128 | static bool ahci_broken_online(struct pci_dev *pdev) |
