aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-27 10:50:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-27 10:50:41 -0500
commit490a8d70cdd77d6262c3d5815bc0b1c54a3a63f8 (patch)
treecf8feb25b7ce349b375a6bdfab8d4d83b3fc9715 /drivers/ata
parent8c022fdd5fc1b9949bad21d26e0cb115d045c7f9 (diff)
parent5f451fe1ab5d73b987051f0d23c85216c552e163 (diff)
Merge branch 'hibern_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'hibern_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: SATA PIIX: Blacklist system that spins off disks during ACPI power off SATA Sil: Blacklist system that spins off disks during ACPI power off SATA AHCI: Blacklist system that spins off disks during ACPI power off SATA: Blacklisting of systems that spin off disks during ACPI power off DMI: Introduce dmi_first_match to make the interface more flexible Hibernation: Introduce system_entering_hibernation
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c32
-rw-r--r--drivers/ata/ata_piix.c34
-rw-r--r--drivers/ata/libata-scsi.c20
-rw-r--r--drivers/ata/sata_sil.c36
4 files changed, 118 insertions, 4 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 96039671e3b9..77bba4c083cb 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -2548,6 +2548,32 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
2548 } 2548 }
2549} 2549}
2550 2550
2551static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
2552{
2553 static const struct dmi_system_id broken_systems[] = {
2554 {
2555 .ident = "HP Compaq nx6310",
2556 .matches = {
2557 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2558 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
2559 },
2560 /* PCI slot number of the controller */
2561 .driver_data = (void *)0x1FUL,
2562 },
2563
2564 { } /* terminate list */
2565 };
2566 const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
2567
2568 if (dmi) {
2569 unsigned long slot = (unsigned long)dmi->driver_data;
2570 /* apply the quirk only to on-board controllers */
2571 return slot == PCI_SLOT(pdev->devfn);
2572 }
2573
2574 return false;
2575}
2576
2551static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 2577static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2552{ 2578{
2553 static int printed_version; 2579 static int printed_version;
@@ -2647,6 +2673,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2647 } 2673 }
2648 } 2674 }
2649 2675
2676 if (ahci_broken_system_poweroff(pdev)) {
2677 pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
2678 dev_info(&pdev->dev,
2679 "quirky BIOS, skipping spindown on poweroff\n");
2680 }
2681
2650 /* CAP.NP sometimes indicate the index of the last enabled 2682 /* CAP.NP sometimes indicate the index of the last enabled
2651 * port, at other times, that of the last possible port, so 2683 * port, at other times, that of the last possible port, so
2652 * determining the maximum port number requires looking at 2684 * determining the maximum port number requires looking at
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 887d8f46a287..54961c0b2c73 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1387,6 +1387,32 @@ static void piix_iocfg_bit18_quirk(struct ata_host *host)
1387 } 1387 }
1388} 1388}
1389 1389
1390static bool piix_broken_system_poweroff(struct pci_dev *pdev)
1391{
1392 static const struct dmi_system_id broken_systems[] = {
1393 {
1394 .ident = "HP Compaq 2510p",
1395 .matches = {
1396 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1397 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"),
1398 },
1399 /* PCI slot number of the controller */
1400 .driver_data = (void *)0x1FUL,
1401 },
1402
1403 { } /* terminate list */
1404 };
1405 const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
1406
1407 if (dmi) {
1408 unsigned long slot = (unsigned long)dmi->driver_data;
1409 /* apply the quirk only to on-board controllers */
1410 return slot == PCI_SLOT(pdev->devfn);
1411 }
1412
1413 return false;
1414}
1415
1390/** 1416/**
1391 * piix_init_one - Register PIIX ATA PCI device with kernel services 1417 * piix_init_one - Register PIIX ATA PCI device with kernel services
1392 * @pdev: PCI device to register 1418 * @pdev: PCI device to register
@@ -1422,6 +1448,14 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
1422 if (!in_module_init) 1448 if (!in_module_init)
1423 return -ENODEV; 1449 return -ENODEV;
1424 1450
1451 if (piix_broken_system_poweroff(pdev)) {
1452 piix_port_info[ent->driver_data].flags |=
1453 ATA_FLAG_NO_POWEROFF_SPINDOWN |
1454 ATA_FLAG_NO_HIBERNATE_SPINDOWN;
1455 dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
1456 "on poweroff and hibernation\n");
1457 }
1458
1425 port_info[0] = piix_port_info[ent->driver_data]; 1459 port_info[0] = piix_port_info[ent->driver_data];
1426 port_info[1] = piix_port_info[ent->driver_data]; 1460 port_info[1] = piix_port_info[ent->driver_data];
1427 1461
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a1a6e6298c33..3c4c5ae277ba 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -46,6 +46,7 @@
46#include <linux/libata.h> 46#include <linux/libata.h>
47#include <linux/hdreg.h> 47#include <linux/hdreg.h>
48#include <linux/uaccess.h> 48#include <linux/uaccess.h>
49#include <linux/suspend.h>
49 50
50#include "libata.h" 51#include "libata.h"
51 52
@@ -1303,6 +1304,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
1303 1304
1304 tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ 1305 tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
1305 } else { 1306 } else {
1307 /* Some odd clown BIOSen issue spindown on power off (ACPI S4
1308 * or S5) causing some drives to spin up and down again.
1309 */
1310 if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
1311 system_state == SYSTEM_POWER_OFF)
1312 goto skip;
1313
1314 if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
1315 system_entering_hibernation())
1316 goto skip;
1317
1306 /* XXX: This is for backward compatibility, will be 1318 /* XXX: This is for backward compatibility, will be
1307 * removed. Read Documentation/feature-removal-schedule.txt 1319 * removed. Read Documentation/feature-removal-schedule.txt
1308 * for more info. 1320 * for more info.
@@ -1326,8 +1338,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
1326 scmd->scsi_done = qc->scsidone; 1338 scmd->scsi_done = qc->scsidone;
1327 qc->scsidone = ata_delayed_done; 1339 qc->scsidone = ata_delayed_done;
1328 } 1340 }
1329 scmd->result = SAM_STAT_GOOD; 1341 goto skip;
1330 return 1;
1331 } 1342 }
1332 1343
1333 /* Issue ATA STANDBY IMMEDIATE command */ 1344 /* Issue ATA STANDBY IMMEDIATE command */
@@ -1343,10 +1354,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
1343 1354
1344 return 0; 1355 return 0;
1345 1356
1346invalid_fld: 1357 invalid_fld:
1347 ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); 1358 ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
1348 /* "Invalid field in cbd" */ 1359 /* "Invalid field in cbd" */
1349 return 1; 1360 return 1;
1361 skip:
1362 scmd->result = SAM_STAT_GOOD;
1363 return 1;
1350} 1364}
1351 1365
1352 1366
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 564c142b03b0..bfd55b085ae6 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -695,11 +695,38 @@ static void sil_init_controller(struct ata_host *host)
695 } 695 }
696} 696}
697 697
698static 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
698static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 724static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
699{ 725{
700 static int printed_version; 726 static int printed_version;
701 int board_id = ent->driver_data; 727 int board_id = ent->driver_data;
702 const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL }; 728 struct ata_port_info pi = sil_port_info[board_id];
729 const struct ata_port_info *ppi[] = { &pi, NULL };
703 struct ata_host *host; 730 struct ata_host *host;
704 void __iomem *mmio_base; 731 void __iomem *mmio_base;
705 int n_ports, rc; 732 int n_ports, rc;
@@ -713,6 +740,13 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
713 if (board_id == sil_3114) 740 if (board_id == sil_3114)
714 n_ports = 4; 741 n_ports = 4;
715 742
743 if (sil_broken_system_poweroff(pdev)) {
744 pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN |
745 ATA_FLAG_NO_HIBERNATE_SPINDOWN;
746 dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
747 "on poweroff and hibernation\n");
748 }
749
716 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 750 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
717 if (!host) 751 if (!host)
718 return -ENOMEM; 752 return -ENOMEM;