linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover
@ 2008-11-03 10:01 Tejun Heo
  2008-11-03 10:01 ` [PATCH 1/8] Hibernation: Introduce system_entering_hibernation Tejun Heo
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide


Hello, Jeff.

This patchset contains eight patches that I collected for 2.6.28 while
you were away.  Unfortunately, the handover to you didn't work out too
well and these got forgotten.  This patchset contains the following
eight patches.

  0001-Hibernation-Introduce-system_entering_hibernation.patch
  0002-DMI-Introduce-dmi_first_match-to-make-the-interface.patch
  0003-SATA-Blacklisting-of-systems-that-spin-off-disks-du.patch
  0004-SATA-AHCI-Blacklist-system-that-spins-off-disks-dur.patch
  0005-SATA-Sil-Blacklist-system-that-spins-off-disks-duri.patch
  0006-SATA-PIIX-Blacklist-system-that-spins-off-disks-dur.patch
  0007-libata-Fix-a-potential-race-condition-in-ata_scsi_p.patch
  0008-libata-implement-ATA_HORKAGE_ATAPI_MOD16_DMA-and-ap.patch

0001-0006 are to fix the long-standing double spindown problems on
certain laptops.  0007 fixes a potential race condition and 0008
implements a workaround for a strange device.  These missed rc1 window
but they're all fixes or workarounds for weird hardware so I think
they qualify.

Thanks.

 drivers/ata/ahci.c          |   32 +++++++++++++++++++
 drivers/ata/ata_piix.c      |   34 ++++++++++++++++++++
 drivers/ata/libata-core.c   |    4 +-
 drivers/ata/libata-scsi.c   |   27 ++++++++++++----
 drivers/ata/sata_sil.c      |   36 ++++++++++++++++++++-
 drivers/firmware/dmi_scan.c |   74 ++++++++++++++++++++++++++++++++------------
 include/linux/dmi.h         |    1 
 include/linux/libata.h      |    4 ++
 include/linux/suspend.h     |    2 +
 kernel/power/disk.c         |   10 +++++
 10 files changed, 197 insertions(+), 27 deletions(-)

--
tejun

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/8] Hibernation: Introduce system_entering_hibernation
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-04  6:14   ` Jeff Garzik
  2008-11-03 10:01 ` [PATCH 2/8] DMI: Introduce dmi_first_match to make the interface more flexible Tejun Heo
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Rafael J. Wysocki, Tejun Heo

From: Rafael J. Wysocki <rjw@sisk.pl>

Introduce boolean function system_entering_hibernation() returning
'true' during the last phase of hibernation, in which devices are
being put into low power states and the sleep state (for example,
ACPI S4) is finally entered.

Some device drivers need such a function to check if the system is
in the final phase of hibernation.  In particular, some SATA drivers
are going to use it for blacklisting systems in which the disks
should not be spun down during the last phase of hibernation (the
BIOS will do that anyway).

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
 include/linux/suspend.h |    2 ++
 kernel/power/disk.c     |   10 ++++++++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 2ce8207..195200b 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -232,6 +232,7 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
 
 extern void hibernation_set_ops(struct platform_hibernation_ops *ops);
 extern int hibernate(void);
+extern bool system_entering_hibernation(void);
 #else /* CONFIG_HIBERNATION */
 static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
 static inline void swsusp_set_page_free(struct page *p) {}
@@ -239,6 +240,7 @@ static inline void swsusp_unset_page_free(struct page *p) {}
 
 static inline void hibernation_set_ops(struct platform_hibernation_ops *ops) {}
 static inline int hibernate(void) { return -ENOSYS; }
+static inline bool system_entering_hibernation(void) { return false; }
 #endif /* CONFIG_HIBERNATION */
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index c9d7408..248e243 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -72,6 +72,14 @@ void hibernation_set_ops(struct platform_hibernation_ops *ops)
 	mutex_unlock(&pm_mutex);
 }
 
+static bool entering_platform_hibernation;
+
+bool system_entering_hibernation(void)
+{
+	return entering_platform_hibernation;
+}
+EXPORT_SYMBOL_GPL(system_entering_hibernation);
+
 #ifdef CONFIG_PM_DEBUG
 static void hibernation_debug_sleep(void)
 {
@@ -416,6 +424,7 @@ int hibernation_platform_enter(void)
 	if (error)
 		goto Close;
 
+	entering_platform_hibernation = true;
 	suspend_console();
 	ftrace_save = __ftrace_enabled_save();
 	error = device_suspend(PMSG_HIBERNATE);
@@ -451,6 +460,7 @@ int hibernation_platform_enter(void)
  Finish:
 	hibernation_ops->finish();
  Resume_devices:
+	entering_platform_hibernation = false;
 	device_resume(PMSG_RESTORE);
 	__ftrace_enabled_restore(ftrace_save);
 	resume_console();
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/8] DMI: Introduce dmi_first_match to make the interface more flexible
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
  2008-11-03 10:01 ` [PATCH 1/8] Hibernation: Introduce system_entering_hibernation Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-03 10:01 ` [PATCH 3/8] SATA: Blacklisting of systems that spin off disks during ACPI power off (rev. 2) Tejun Heo
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Rafael J. Wysocki, Tejun Heo

From: Rafael J. Wysocki <rjw@sisk.pl>

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.  However, only the on-board controlles should
be blacklisted and their PCI slot numbers can be used for this
purpose.  Unfortunately the existing interface for checking DMI
information of the system is not very convenient for this purpose,
because to use it, we would have to define special callback functions
or create a separate struct dmi_system_id table for each blacklisted
system.

To overcome this difficulty introduce a new function
dmi_first_match() returning a pointer to the first entry in an array
of struct dmi_system_id elements that matches the system DMI
information.  Then, we can use this pointer to access the entry's
.driver_data field containing the additional information, such as
the PCI slot number, allowing us to do the desired blacklisting.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
 drivers/firmware/dmi_scan.c |   74 ++++++++++++++++++++++++++++++++-----------
 include/linux/dmi.h         |    1 +
 2 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 3e526b6..6e88b99 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -415,6 +415,27 @@ void __init dmi_scan_machine(void)
 }
 
 /**
+ *	dmi_match - check if dmi_system_id structure matches system DMI data
+ *	@dmi: pointer to the dmi_system_id structure to check
+ */
+static bool dmi_match(const struct dmi_system_id *dmi)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
+		int s = dmi->matches[i].slot;
+		if (s == DMI_NONE)
+			continue;
+		if (dmi_ident[s]
+		    && strstr(dmi_ident[s], dmi->matches[i].substr))
+			continue;
+		/* No match */
+		return false;
+	}
+	return true;
+}
+
+/**
  *	dmi_check_system - check system DMI data
  *	@list: array of dmi_system_id structures to match against
  *		All non-null elements of the list must match
@@ -429,32 +450,47 @@ void __init dmi_scan_machine(void)
  */
 int dmi_check_system(const struct dmi_system_id *list)
 {
-	int i, count = 0;
-	const struct dmi_system_id *d = list;
-
-	WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
-
-	while (d->ident) {
-		for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
-			int s = d->matches[i].slot;
-			if (s == DMI_NONE)
-				continue;
-			if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
-				continue;
-			/* No match */
-			goto fail;
+	int count = 0;
+	const struct dmi_system_id *d;
+
+	for (d = list; d->ident; d++)
+		if (dmi_match(d)) {
+			count++;
+			if (d->callback && d->callback(d))
+				break;
 		}
-		count++;
-		if (d->callback && d->callback(d))
-			break;
-fail:		d++;
-	}
 
 	return count;
 }
 EXPORT_SYMBOL(dmi_check_system);
 
 /**
+ *	dmi_first_match - find dmi_system_id structure matching system DMI data
+ *	@list: array of dmi_system_id structures to match against
+ *		All non-null elements of the list must match
+ *		their slot's (field index's) data (i.e., each
+ *		list string must be a substring of the specified
+ *		DMI slot's string data) to be considered a
+ *		successful match.
+ *
+ *	Walk the blacklist table until the first match is found.  Return the
+ *	pointer to the matching entry or NULL if there's no match.
+ */
+const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
+{
+	const struct dmi_system_id *d;
+
+	WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
+
+	for (d = list; d->ident; d++)
+		if (dmi_match(d))
+			return d;
+
+	return NULL;
+}
+EXPORT_SYMBOL(dmi_first_match);
+
+/**
  *	dmi_get_system_info - return DMI data value
  *	@field: data index (see enum dmi_field)
  *
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index e5084eb..6e20820 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -38,6 +38,7 @@ struct dmi_device {
 #ifdef CONFIG_DMI
 
 extern int dmi_check_system(const struct dmi_system_id *list);
+const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
 extern const char * dmi_get_system_info(int field);
 extern const struct dmi_device * dmi_find_device(int type, const char *name,
 	const struct dmi_device *from);
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/8] SATA: Blacklisting of systems that spin off disks during ACPI power off (rev. 2)
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
  2008-11-03 10:01 ` [PATCH 1/8] Hibernation: Introduce system_entering_hibernation Tejun Heo
  2008-11-03 10:01 ` [PATCH 2/8] DMI: Introduce dmi_first_match to make the interface more flexible Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-03 10:01 ` [PATCH 4/8] SATA AHCI: Blacklist system that spins off disks during ACPI power off Tejun Heo
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Rafael J. Wysocki, Tejun Heo

From: Rafael J. Wysocki <rjw@sisk.pl>

Introduce new libata flags ATA_FLAG_NO_POWEROFF_SPINDOWN and
ATA_FLAG_NO_HIBERNATE_SPINDOWN that, if set, will prevent disks from
being spun off during system power off and hibernation, respectively
(to handle the hibernation case we need the new system state
SYSTEM_HIBERNATE_ENTER that can be checked against by libata, in
analogy with SYSTEM_POWER_OFF).

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
 drivers/ata/libata-scsi.c |   20 +++++++++++++++++---
 include/linux/libata.h    |    2 ++
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index bbb30d8..0a0aa95 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -46,6 +46,7 @@
 #include <linux/libata.h>
 #include <linux/hdreg.h>
 #include <linux/uaccess.h>
+#include <linux/suspend.h>
 
 #include "libata.h"
 
@@ -1307,6 +1308,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
 
 		tf->command = ATA_CMD_VERIFY;	/* READ VERIFY */
 	} else {
+		/* Some odd clown BIOSen issue spindown on power off (ACPI S4
+		 * or S5) causing some drives to spin up and down again.
+		 */
+		if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
+		    system_state == SYSTEM_POWER_OFF)
+			goto skip;
+
+		if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
+		     system_entering_hibernation())
+			goto skip;
+
 		/* XXX: This is for backward compatibility, will be
 		 * removed.  Read Documentation/feature-removal-schedule.txt
 		 * for more info.
@@ -1330,8 +1342,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
 				scmd->scsi_done = qc->scsidone;
 				qc->scsidone = ata_delayed_done;
 			}
-			scmd->result = SAM_STAT_GOOD;
-			return 1;
+			goto skip;
 		}
 
 		/* Issue ATA STANDBY IMMEDIATE command */
@@ -1347,10 +1358,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
 
 	return 0;
 
-invalid_fld:
+ invalid_fld:
 	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
 	/* "Invalid field in cbd" */
 	return 1;
+ skip:
+	scmd->result = SAM_STAT_GOOD;
+	return 1;
 }
 
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f5441ed..cc0ceaf 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -187,6 +187,8 @@ enum {
 	ATA_FLAG_PIO_POLLING	= (1 << 9), /* use polling PIO if LLD
 					     * doesn't handle PIO interrupts */
 	ATA_FLAG_NCQ		= (1 << 10), /* host supports NCQ */
+	ATA_FLAG_NO_POWEROFF_SPINDOWN = (1 << 11), /* don't spindown before poweroff */
+	ATA_FLAG_NO_HIBERNATE_SPINDOWN = (1 << 12), /* don't spindown before hibernation */
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
 	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
 	ATA_FLAG_NO_IORDY	= (1 << 16), /* controller lacks iordy */
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/8] SATA AHCI: Blacklist system that spins off disks during ACPI power off
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
                   ` (2 preceding siblings ...)
  2008-11-03 10:01 ` [PATCH 3/8] SATA: Blacklisting of systems that spin off disks during ACPI power off (rev. 2) Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-03 10:01 ` [PATCH 5/8] SATA Sil: " Tejun Heo
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Rafael J. Wysocki, Tejun Heo

From: Rafael J. Wysocki <rjw@sisk.pl>

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 nx6310 that uses the AHCI driver.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
 drivers/ata/ahci.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index a67b8e7..8e8790b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -2546,6 +2546,32 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
 	}
 }
 
+static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
+{
+	static const struct dmi_system_id broken_systems[] = {
+		{
+			.ident = "HP Compaq nx6310",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
+			},
+			/* PCI slot number of the controller */
+			.driver_data = (void *)0x1FUL,
+		},
+
+		{ }	/* terminate list */
+	};
+	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+	if (dmi) {
+		unsigned long slot = (unsigned long)dmi->driver_data;
+		/* apply the quirk only to on-board controllers */
+		return slot == PCI_SLOT(pdev->devfn);
+	}
+
+	return false;
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
@@ -2641,6 +2667,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		}
 	}
 
+	if (ahci_broken_system_poweroff(pdev)) {
+		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
+		dev_info(&pdev->dev,
+			"quirky BIOS, skipping spindown on poweroff\n");
+	}
+
 	/* CAP.NP sometimes indicate the index of the last enabled
 	 * port, at other times, that of the last possible port, so
 	 * determining the maximum port number requires looking at
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/8] SATA Sil: Blacklist system that spins off disks during ACPI power off
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
                   ` (3 preceding siblings ...)
  2008-11-03 10:01 ` [PATCH 4/8] SATA AHCI: Blacklist system that spins off disks during ACPI power off Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-03 10:01 ` [PATCH 6/8] SATA PIIX: " Tejun Heo
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Rafael J. Wysocki, Tejun Heo

From: Rafael J. Wysocki <rjw@sisk.pl>

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: Tejun Heo <tj@kernel.org>
---
 drivers/ata/sata_sil.c |   36 +++++++++++++++++++++++++++++++++++-
 1 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 031d7b7..f1dd478 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -603,11 +603,38 @@ static void sil_init_controller(struct ata_host *host)
 	}
 }
 
+static bool sil_broken_system_poweroff(struct pci_dev *pdev)
+{
+	static const struct dmi_system_id broken_systems[] = {
+		{
+			.ident = "HP Compaq nx6325",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
+			},
+			/* PCI slot number of the controller */
+			.driver_data = (void *)0x12UL,
+		},
+
+		{ }	/* terminate list */
+	};
+	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+	if (dmi) {
+		unsigned long slot = (unsigned long)dmi->driver_data;
+		/* apply the quirk only to on-board controllers */
+		return slot == PCI_SLOT(pdev->devfn);
+	}
+
+	return false;
+}
+
 static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
 	int board_id = ent->driver_data;
-	const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL };
+	struct ata_port_info pi = sil_port_info[board_id];
+	const struct ata_port_info *ppi[] = { &pi, NULL };
 	struct ata_host *host;
 	void __iomem *mmio_base;
 	int n_ports, rc;
@@ -621,6 +648,13 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (board_id == sil_3114)
 		n_ports = 4;
 
+	if (sil_broken_system_poweroff(pdev)) {
+		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN |
+					ATA_FLAG_NO_HIBERNATE_SPINDOWN;
+		dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
+				"on poweroff and hibernation\n");
+	}
+
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
 	if (!host)
 		return -ENOMEM;
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/8] SATA PIIX: Blacklist system that spins off disks during ACPI power off
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
                   ` (4 preceding siblings ...)
  2008-11-03 10:01 ` [PATCH 5/8] SATA Sil: " Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-03 10:01 ` [PATCH 7/8] libata: Fix a potential race condition in ata_scsi_park_show() Tejun Heo
  2008-11-03 10:01 ` [PATCH 8/8] libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it Tejun Heo
  7 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Rafael J. Wysocki, Tejun Heo

From: Rafael J. Wysocki <rjw@sisk.pl>

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 2510p that uses the ata_piix driver.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
 drivers/ata/ata_piix.c |   34 ++++++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 8e37be1..f5fff92 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1370,6 +1370,32 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
 	}
 }
 
+static bool piix_broken_system_poweroff(struct pci_dev *pdev)
+{
+	static const struct dmi_system_id broken_systems[] = {
+		{
+			.ident = "HP Compaq 2510p",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"),
+			},
+			/* PCI slot number of the controller */
+			.driver_data = (void *)0x1FUL,
+		},
+
+		{ }	/* terminate list */
+	};
+	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+	if (dmi) {
+		unsigned long slot = (unsigned long)dmi->driver_data;
+		/* apply the quirk only to on-board controllers */
+		return slot == PCI_SLOT(pdev->devfn);
+	}
+
+	return false;
+}
+
 /**
  *	piix_init_one - Register PIIX ATA PCI device with kernel services
  *	@pdev: PCI device to register
@@ -1405,6 +1431,14 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
 	if (!in_module_init)
 		return -ENODEV;
 
+	if (piix_broken_system_poweroff(pdev)) {
+		piix_port_info[ent->driver_data].flags |=
+				ATA_FLAG_NO_POWEROFF_SPINDOWN |
+					ATA_FLAG_NO_HIBERNATE_SPINDOWN;
+		dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
+				"on poweroff and hibernation\n");
+	}
+
 	port_info[0] = piix_port_info[ent->driver_data];
 	port_info[1] = piix_port_info[ent->driver_data];
 
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/8] libata: Fix a potential race condition in ata_scsi_park_show()
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
                   ` (5 preceding siblings ...)
  2008-11-03 10:01 ` [PATCH 6/8] SATA PIIX: " Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-04  6:10   ` Jeff Garzik
  2008-11-03 10:01 ` [PATCH 8/8] libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it Tejun Heo
  7 siblings, 1 reply; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Elias Oltmanns

From: Elias Oltmanns <eo@nebensachen.de>

Peter Moulder has pointed out that there is a slight chance that a
negative value might be passed to jiffies_to_msecs() in
ata_scsi_park_show(). This is fixed by saving the value of jiffies in a
local variable, thus also reducing code since the volatile variable
jiffies is accessed only once.

Signed-off-by: Elias Oltmanns <eo@nebensachen.de>
Signed-off-by: Tejun Heo <tj.kernel.org>
---
 drivers/ata/libata-scsi.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 0a0aa95..d12f84f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -191,7 +191,7 @@ static ssize_t ata_scsi_park_show(struct device *device,
 	struct ata_port *ap;
 	struct ata_link *link;
 	struct ata_device *dev;
-	unsigned long flags;
+	unsigned long flags, now;
 	unsigned int uninitialized_var(msecs);
 	int rc = 0;
 
@@ -209,10 +209,11 @@ static ssize_t ata_scsi_park_show(struct device *device,
 	}
 
 	link = dev->link;
+	now = jiffies;
 	if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS &&
 	    link->eh_context.unloaded_mask & (1 << dev->devno) &&
-	    time_after(dev->unpark_deadline, jiffies))
-		msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies);
+	    time_after(dev->unpark_deadline, now))
+		msecs = jiffies_to_msecs(dev->unpark_deadline - now);
 	else
 		msecs = 0;
 
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 8/8] libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it
  2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
                   ` (6 preceding siblings ...)
  2008-11-03 10:01 ` [PATCH 7/8] libata: Fix a potential race condition in ata_scsi_park_show() Tejun Heo
@ 2008-11-03 10:01 ` Tejun Heo
  2008-11-04  6:11   ` Jeff Garzik
  7 siblings, 1 reply; 12+ messages in thread
From: Tejun Heo @ 2008-11-03 10:01 UTC (permalink / raw)
  To: jeff, linux-ide; +Cc: Tejun Heo, John Clark

libata always uses PIO for ATAPI commands when the number of bytes to
transfer isn't multiple of 16 but quantum DAT72 chokes on odd bytes
PIO transfers.  Implement a horkage to skip the mod16 check and apply
it to the quantum device.

This is reported by John Clark in the following thread.

  http://thread.gmane.org/gmane.linux.ide/34748

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: John Clark <clarkjc@runbox.com>
---
 drivers/ata/libata-core.c |    4 +++-
 include/linux/libata.h    |    2 ++
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 82af701..91b478f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4024,6 +4024,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
 	/* Weird ATAPI devices */
 	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
+	{ "QUANTUM DAT    DAT72-000", NULL,	ATA_HORKAGE_ATAPI_MOD16_DMA },
 
 	/* Devices we expect to fail diagnostics */
 
@@ -4444,7 +4445,8 @@ int atapi_check_dma(struct ata_queued_cmd *qc)
 	/* Don't allow DMA if it isn't multiple of 16 bytes.  Quite a
 	 * few ATAPI devices choke on such DMA requests.
 	 */
-	if (unlikely(qc->nbytes & 15))
+	if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) &&
+	    unlikely(qc->nbytes & 15))
 		return 1;
 
 	if (ap->ops->check_atapi_dma)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index cc0ceaf..a2eb8f2 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -375,6 +375,8 @@ enum {
 	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */
 	ATA_HORKAGE_STUCK_ERR	= (1 << 9),	/* stuck ERR on next PACKET */
 	ATA_HORKAGE_BRIDGE_OK	= (1 << 10),	/* no bridge limits */
+	ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands
+						    not multiple of 16 bytes */
 
 	 /* DMA mask for user DMA control: User visible values; DO NOT
 	    renumber */
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 7/8] libata: Fix a potential race condition in ata_scsi_park_show()
  2008-11-03 10:01 ` [PATCH 7/8] libata: Fix a potential race condition in ata_scsi_park_show() Tejun Heo
@ 2008-11-04  6:10   ` Jeff Garzik
  0 siblings, 0 replies; 12+ messages in thread
From: Jeff Garzik @ 2008-11-04  6:10 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, Elias Oltmanns

Tejun Heo wrote:
> From: Elias Oltmanns <eo@nebensachen.de>
> 
> Peter Moulder has pointed out that there is a slight chance that a
> negative value might be passed to jiffies_to_msecs() in
> ata_scsi_park_show(). This is fixed by saving the value of jiffies in a
> local variable, thus also reducing code since the volatile variable
> jiffies is accessed only once.
> 
> Signed-off-by: Elias Oltmanns <eo@nebensachen.de>
> Signed-off-by: Tejun Heo <tj.kernel.org>
> ---
>  drivers/ata/libata-scsi.c |    7 ++++---
>  1 files changed, 4 insertions(+), 3 deletions(-)

applied



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 8/8] libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it
  2008-11-03 10:01 ` [PATCH 8/8] libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it Tejun Heo
@ 2008-11-04  6:11   ` Jeff Garzik
  0 siblings, 0 replies; 12+ messages in thread
From: Jeff Garzik @ 2008-11-04  6:11 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, John Clark

Tejun Heo wrote:
> libata always uses PIO for ATAPI commands when the number of bytes to
> transfer isn't multiple of 16 but quantum DAT72 chokes on odd bytes
> PIO transfers.  Implement a horkage to skip the mod16 check and apply
> it to the quantum device.
> 
> This is reported by John Clark in the following thread.
> 
>   http://thread.gmane.org/gmane.linux.ide/34748
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: John Clark <clarkjc@runbox.com>
> ---
>  drivers/ata/libata-core.c |    4 +++-
>  include/linux/libata.h    |    2 ++
>  2 files changed, 5 insertions(+), 1 deletions(-)

applied



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/8] Hibernation: Introduce system_entering_hibernation
  2008-11-03 10:01 ` [PATCH 1/8] Hibernation: Introduce system_entering_hibernation Tejun Heo
@ 2008-11-04  6:14   ` Jeff Garzik
  0 siblings, 0 replies; 12+ messages in thread
From: Jeff Garzik @ 2008-11-04  6:14 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, Rafael J. Wysocki

Tejun Heo wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Introduce boolean function system_entering_hibernation() returning
> 'true' during the last phase of hibernation, in which devices are
> being put into low power states and the sleep state (for example,
> ACPI S4) is finally entered.
> 
> Some device drivers need such a function to check if the system is
> in the final phase of hibernation.  In particular, some SATA drivers
> are going to use it for blacklisting systems in which the disks
> should not be spun down during the last phase of hibernation (the
> BIOS will do that anyway).
> 
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> Signed-off-by: Tejun Heo <tj@kernel.org>
> ---
>  include/linux/suspend.h |    2 ++
>  kernel/power/disk.c     |   10 ++++++++++
>  2 files changed, 12 insertions(+), 0 deletions(-)

applied 1-6



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-11-04  6:14 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-03 10:01 [PATCHSET #upstream-fixes] patches which fell off the crack during maintainership handover Tejun Heo
2008-11-03 10:01 ` [PATCH 1/8] Hibernation: Introduce system_entering_hibernation Tejun Heo
2008-11-04  6:14   ` Jeff Garzik
2008-11-03 10:01 ` [PATCH 2/8] DMI: Introduce dmi_first_match to make the interface more flexible Tejun Heo
2008-11-03 10:01 ` [PATCH 3/8] SATA: Blacklisting of systems that spin off disks during ACPI power off (rev. 2) Tejun Heo
2008-11-03 10:01 ` [PATCH 4/8] SATA AHCI: Blacklist system that spins off disks during ACPI power off Tejun Heo
2008-11-03 10:01 ` [PATCH 5/8] SATA Sil: " Tejun Heo
2008-11-03 10:01 ` [PATCH 6/8] SATA PIIX: " Tejun Heo
2008-11-03 10:01 ` [PATCH 7/8] libata: Fix a potential race condition in ata_scsi_park_show() Tejun Heo
2008-11-04  6:10   ` Jeff Garzik
2008-11-03 10:01 ` [PATCH 8/8] libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it Tejun Heo
2008-11-04  6:11   ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).