SATA Sil: Blacklist system that spins off disks during ACPI power off

Some notebooks from HP have the problem that their BIOSes attempt to
spin down hard drives before entering ACPI system states S4 and S5.
This leads to a yo-yo effect during system power-off shutdown and the
last phase of hibernation when the disk is first spun down by the
kernel and then almost immediately turned on and off by the BIOS.
This, in turn, may result in shortening the disk's life times.

To prevent this from happening we can blacklist the affected systems
using DMI information.

Blacklist HP nx6325 that uses the sata_sil driver.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

authored by Rafael J. Wysocki and committed by Jeff Garzik e57db7bd 1fd68434

+35 -1
+35 -1
drivers/ata/sata_sil.c
··· 695 } 696 } 697 698 static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 699 { 700 static int printed_version; 701 int board_id = ent->driver_data; 702 - const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL }; 703 struct ata_host *host; 704 void __iomem *mmio_base; 705 int n_ports, rc; ··· 739 n_ports = 2; 740 if (board_id == sil_3114) 741 n_ports = 4; 742 743 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 744 if (!host)
··· 695 } 696 } 697 698 + static bool sil_broken_system_poweroff(struct pci_dev *pdev) 699 + { 700 + static const struct dmi_system_id broken_systems[] = { 701 + { 702 + .ident = "HP Compaq nx6325", 703 + .matches = { 704 + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 705 + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), 706 + }, 707 + /* PCI slot number of the controller */ 708 + .driver_data = (void *)0x12UL, 709 + }, 710 + 711 + { } /* terminate list */ 712 + }; 713 + const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 714 + 715 + if (dmi) { 716 + unsigned long slot = (unsigned long)dmi->driver_data; 717 + /* apply the quirk only to on-board controllers */ 718 + return slot == PCI_SLOT(pdev->devfn); 719 + } 720 + 721 + return false; 722 + } 723 + 724 static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 725 { 726 static int printed_version; 727 int board_id = ent->driver_data; 728 + struct ata_port_info pi = sil_port_info[board_id]; 729 + const struct ata_port_info *ppi[] = { &pi, NULL }; 730 struct ata_host *host; 731 void __iomem *mmio_base; 732 int n_ports, rc; ··· 712 n_ports = 2; 713 if (board_id == sil_3114) 714 n_ports = 4; 715 + 716 + if (sil_broken_system_poweroff(pdev)) { 717 + pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN | 718 + ATA_FLAG_NO_HIBERNATE_SPINDOWN; 719 + dev_info(&pdev->dev, "quirky BIOS, skipping spindown " 720 + "on poweroff and hibernation\n"); 721 + } 722 723 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 724 if (!host)