diff options
Diffstat (limited to 'drivers/ata/sata_sil.c')
-rw-r--r-- | drivers/ata/sata_sil.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 564c142b03b0..9f029595f454 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/device.h> | 44 | #include <linux/device.h> |
45 | #include <scsi/scsi_host.h> | 45 | #include <scsi/scsi_host.h> |
46 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
47 | #include <linux/dmi.h> | ||
47 | 48 | ||
48 | #define DRV_NAME "sata_sil" | 49 | #define DRV_NAME "sata_sil" |
49 | #define DRV_VERSION "2.4" | 50 | #define DRV_VERSION "2.4" |
@@ -695,11 +696,38 @@ static void sil_init_controller(struct ata_host *host) | |||
695 | } | 696 | } |
696 | } | 697 | } |
697 | 698 | ||
699 | static bool sil_broken_system_poweroff(struct pci_dev *pdev) | ||
700 | { | ||
701 | static const struct dmi_system_id broken_systems[] = { | ||
702 | { | ||
703 | .ident = "HP Compaq nx6325", | ||
704 | .matches = { | ||
705 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
706 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), | ||
707 | }, | ||
708 | /* PCI slot number of the controller */ | ||
709 | .driver_data = (void *)0x12UL, | ||
710 | }, | ||
711 | |||
712 | { } /* terminate list */ | ||
713 | }; | ||
714 | const struct dmi_system_id *dmi = dmi_first_match(broken_systems); | ||
715 | |||
716 | if (dmi) { | ||
717 | unsigned long slot = (unsigned long)dmi->driver_data; | ||
718 | /* apply the quirk only to on-board controllers */ | ||
719 | return slot == PCI_SLOT(pdev->devfn); | ||
720 | } | ||
721 | |||
722 | return false; | ||
723 | } | ||
724 | |||
698 | static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 725 | static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
699 | { | 726 | { |
700 | static int printed_version; | 727 | static int printed_version; |
701 | int board_id = ent->driver_data; | 728 | int board_id = ent->driver_data; |
702 | const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL }; | 729 | struct ata_port_info pi = sil_port_info[board_id]; |
730 | const struct ata_port_info *ppi[] = { &pi, NULL }; | ||
703 | struct ata_host *host; | 731 | struct ata_host *host; |
704 | void __iomem *mmio_base; | 732 | void __iomem *mmio_base; |
705 | int n_ports, rc; | 733 | int n_ports, rc; |
@@ -713,6 +741,13 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
713 | if (board_id == sil_3114) | 741 | if (board_id == sil_3114) |
714 | n_ports = 4; | 742 | n_ports = 4; |
715 | 743 | ||
744 | if (sil_broken_system_poweroff(pdev)) { | ||
745 | pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN | | ||
746 | ATA_FLAG_NO_HIBERNATE_SPINDOWN; | ||
747 | dev_info(&pdev->dev, "quirky BIOS, skipping spindown " | ||
748 | "on poweroff and hibernation\n"); | ||
749 | } | ||
750 | |||
716 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); | 751 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); |
717 | if (!host) | 752 | if (!host) |
718 | return -ENOMEM; | 753 | return -ENOMEM; |