diff options
| -rw-r--r-- | drivers/ata/ahci.c | 72 | ||||
| -rw-r--r-- | drivers/ata/ata_piix.c | 9 | ||||
| -rw-r--r-- | drivers/ata/pata_efar.c | 17 | ||||
| -rw-r--r-- | drivers/ata/pata_legacy.c | 2 |
4 files changed, 91 insertions, 9 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 08186ecbaf8d..6b91c26a4635 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -220,6 +220,7 @@ enum { | |||
| 220 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ | 220 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ |
| 221 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ | 221 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ |
| 222 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ | 222 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ |
| 223 | AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ | ||
| 223 | 224 | ||
| 224 | /* ap->flags bits */ | 225 | /* ap->flags bits */ |
| 225 | 226 | ||
| @@ -2316,9 +2317,17 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) | |||
| 2316 | static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) | 2317 | static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) |
| 2317 | { | 2318 | { |
| 2318 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 2319 | struct ata_host *host = dev_get_drvdata(&pdev->dev); |
| 2320 | struct ahci_host_priv *hpriv = host->private_data; | ||
| 2319 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; | 2321 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; |
| 2320 | u32 ctl; | 2322 | u32 ctl; |
| 2321 | 2323 | ||
| 2324 | if (mesg.event & PM_EVENT_SUSPEND && | ||
| 2325 | hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { | ||
| 2326 | dev_printk(KERN_ERR, &pdev->dev, | ||
| 2327 | "BIOS update required for suspend/resume\n"); | ||
| 2328 | return -EIO; | ||
| 2329 | } | ||
| 2330 | |||
| 2322 | if (mesg.event & PM_EVENT_SLEEP) { | 2331 | if (mesg.event & PM_EVENT_SLEEP) { |
| 2323 | /* AHCI spec rev1.1 section 8.3.3: | 2332 | /* AHCI spec rev1.1 section 8.3.3: |
| 2324 | * Software must disable interrupts prior to requesting a | 2333 | * Software must disable interrupts prior to requesting a |
| @@ -2610,6 +2619,63 @@ static bool ahci_broken_system_poweroff(struct pci_dev *pdev) | |||
| 2610 | return false; | 2619 | return false; |
| 2611 | } | 2620 | } |
| 2612 | 2621 | ||
| 2622 | static bool ahci_broken_suspend(struct pci_dev *pdev) | ||
| 2623 | { | ||
| 2624 | static const struct dmi_system_id sysids[] = { | ||
| 2625 | /* | ||
| 2626 | * On HP dv[4-6] and HDX18 with earlier BIOSen, link | ||
| 2627 | * to the harddisk doesn't become online after | ||
| 2628 | * resuming from STR. Warn and fail suspend. | ||
| 2629 | */ | ||
| 2630 | { | ||
| 2631 | .ident = "dv4", | ||
| 2632 | .matches = { | ||
| 2633 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2634 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2635 | "HP Pavilion dv4 Notebook PC"), | ||
| 2636 | }, | ||
| 2637 | .driver_data = "F.30", /* cutoff BIOS version */ | ||
| 2638 | }, | ||
| 2639 | { | ||
| 2640 | .ident = "dv5", | ||
| 2641 | .matches = { | ||
| 2642 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2643 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2644 | "HP Pavilion dv5 Notebook PC"), | ||
| 2645 | }, | ||
| 2646 | .driver_data = "F.16", /* cutoff BIOS version */ | ||
| 2647 | }, | ||
| 2648 | { | ||
| 2649 | .ident = "dv6", | ||
| 2650 | .matches = { | ||
| 2651 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2652 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2653 | "HP Pavilion dv6 Notebook PC"), | ||
| 2654 | }, | ||
| 2655 | .driver_data = "F.21", /* cutoff BIOS version */ | ||
| 2656 | }, | ||
| 2657 | { | ||
| 2658 | .ident = "HDX18", | ||
| 2659 | .matches = { | ||
| 2660 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2661 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2662 | "HP HDX18 Notebook PC"), | ||
| 2663 | }, | ||
| 2664 | .driver_data = "F.23", /* cutoff BIOS version */ | ||
| 2665 | }, | ||
| 2666 | { } /* terminate list */ | ||
| 2667 | }; | ||
| 2668 | const struct dmi_system_id *dmi = dmi_first_match(sysids); | ||
| 2669 | const char *ver; | ||
| 2670 | |||
| 2671 | if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) | ||
| 2672 | return false; | ||
| 2673 | |||
| 2674 | ver = dmi_get_system_info(DMI_BIOS_VERSION); | ||
| 2675 | |||
| 2676 | return !ver || strcmp(ver, dmi->driver_data) < 0; | ||
| 2677 | } | ||
| 2678 | |||
| 2613 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2679 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 2614 | { | 2680 | { |
| 2615 | static int printed_version; | 2681 | static int printed_version; |
| @@ -2715,6 +2781,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2715 | "quirky BIOS, skipping spindown on poweroff\n"); | 2781 | "quirky BIOS, skipping spindown on poweroff\n"); |
| 2716 | } | 2782 | } |
| 2717 | 2783 | ||
| 2784 | if (ahci_broken_suspend(pdev)) { | ||
| 2785 | hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; | ||
| 2786 | dev_printk(KERN_WARNING, &pdev->dev, | ||
| 2787 | "BIOS update required for suspend/resume\n"); | ||
| 2788 | } | ||
| 2789 | |||
| 2718 | /* CAP.NP sometimes indicate the index of the last enabled | 2790 | /* CAP.NP sometimes indicate the index of the last enabled |
| 2719 | * port, at other times, that of the last possible port, so | 2791 | * port, at other times, that of the last possible port, so |
| 2720 | * determining the maximum port number requires looking at | 2792 | * determining the maximum port number requires looking at |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index d51a17c0f59b..1aeb7082b0c4 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
| @@ -1455,6 +1455,15 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev) | |||
| 1455 | /* PCI slot number of the controller */ | 1455 | /* PCI slot number of the controller */ |
| 1456 | .driver_data = (void *)0x1FUL, | 1456 | .driver_data = (void *)0x1FUL, |
| 1457 | }, | 1457 | }, |
| 1458 | { | ||
| 1459 | .ident = "HP Compaq nc6000", | ||
| 1460 | .matches = { | ||
| 1461 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 1462 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6000"), | ||
| 1463 | }, | ||
| 1464 | /* PCI slot number of the controller */ | ||
| 1465 | .driver_data = (void *)0x1FUL, | ||
| 1466 | }, | ||
| 1458 | 1467 | ||
| 1459 | { } /* terminate list */ | 1468 | { } /* terminate list */ |
| 1460 | }; | 1469 | }; |
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 2085e0a3a05a..2a6412f5d117 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/ata.h> | 22 | #include <linux/ata.h> |
| 23 | 23 | ||
| 24 | #define DRV_NAME "pata_efar" | 24 | #define DRV_NAME "pata_efar" |
| 25 | #define DRV_VERSION "0.4.4" | 25 | #define DRV_VERSION "0.4.5" |
| 26 | 26 | ||
| 27 | /** | 27 | /** |
| 28 | * efar_pre_reset - Enable bits | 28 | * efar_pre_reset - Enable bits |
| @@ -98,18 +98,17 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
| 98 | { 2, 1 }, | 98 | { 2, 1 }, |
| 99 | { 2, 3 }, }; | 99 | { 2, 3 }, }; |
| 100 | 100 | ||
| 101 | if (pio > 2) | 101 | if (pio > 1) |
| 102 | control |= 1; /* TIME1 enable */ | 102 | control |= 1; /* TIME */ |
| 103 | if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ | 103 | if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ |
| 104 | control |= 2; /* IE enable */ | 104 | control |= 2; /* IE */ |
| 105 | /* Intel specifies that the PPE functionality is for disk only */ | 105 | /* Intel specifies that the prefetch/posting is for disk only */ |
| 106 | if (adev->class == ATA_DEV_ATA) | 106 | if (adev->class == ATA_DEV_ATA) |
| 107 | control |= 4; /* PPE enable */ | 107 | control |= 4; /* PPE */ |
| 108 | 108 | ||
| 109 | pci_read_config_word(dev, idetm_port, &idetm_data); | 109 | pci_read_config_word(dev, idetm_port, &idetm_data); |
| 110 | 110 | ||
| 111 | /* Enable PPE, IE and TIME as appropriate */ | 111 | /* Set PPE, IE, and TIME as appropriate */ |
| 112 | |||
| 113 | if (adev->devno == 0) { | 112 | if (adev->devno == 0) { |
| 114 | idetm_data &= 0xCCF0; | 113 | idetm_data &= 0xCCF0; |
| 115 | idetm_data |= control; | 114 | idetm_data |= control; |
| @@ -129,7 +128,7 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
| 129 | pci_write_config_byte(dev, 0x44, slave_data); | 128 | pci_write_config_byte(dev, 0x44, slave_data); |
| 130 | } | 129 | } |
| 131 | 130 | ||
| 132 | idetm_data |= 0x4000; /* Ensure SITRE is enabled */ | 131 | idetm_data |= 0x4000; /* Ensure SITRE is set */ |
| 133 | pci_write_config_word(dev, idetm_port, idetm_data); | 132 | pci_write_config_word(dev, idetm_port, idetm_data); |
| 134 | } | 133 | } |
| 135 | 134 | ||
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index f72c6c5b820f..6932e56d179c 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | * | 48 | * |
| 49 | */ | 49 | */ |
| 50 | 50 | ||
| 51 | #include <linux/async.h> | ||
| 51 | #include <linux/kernel.h> | 52 | #include <linux/kernel.h> |
| 52 | #include <linux/module.h> | 53 | #include <linux/module.h> |
| 53 | #include <linux/pci.h> | 54 | #include <linux/pci.h> |
| @@ -1028,6 +1029,7 @@ static __init int legacy_init_one(struct legacy_probe *probe) | |||
| 1028 | &legacy_sht); | 1029 | &legacy_sht); |
| 1029 | if (ret) | 1030 | if (ret) |
| 1030 | goto fail; | 1031 | goto fail; |
| 1032 | async_synchronize_full(); | ||
| 1031 | ld->platform_dev = pdev; | 1033 | ld->platform_dev = pdev; |
| 1032 | 1034 | ||
| 1033 | /* Nothing found means we drop the port as its probably not there */ | 1035 | /* Nothing found means we drop the port as its probably not there */ |
