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
From: Rafael J. Wysocki <redacted>
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 <redacted>
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(-)
@@ -415,6 +415,27 @@ void __init dmi_scan_machine(void)}/**+*dmi_match-checkifdmi_system_idstructurematchessystemDMIdata+*@dmi:pointertothedmi_system_idstructuretocheck+*/+staticbooldmi_match(conststructdmi_system_id*dmi)+{+inti;++for(i=0;i<ARRAY_SIZE(dmi->matches);i++){+ints=dmi->matches[i].slot;+if(s==DMI_NONE)+continue;+if(dmi_ident[s]+&&strstr(dmi_ident[s],dmi->matches[i].substr))+continue;+/* No match */+returnfalse;+}+returntrue;+}++/***dmi_check_system-checksystemDMIdata*@list:arrayofdmi_system_idstructurestomatchagainst*Allnon-nullelementsofthelistmustmatch
@@ -429,32 +450,47 @@ void __init dmi_scan_machine(void)*/intdmi_check_system(conststructdmi_system_id*list){-inti,count=0;-conststructdmi_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++){-ints=d->matches[i].slot;-if(s==DMI_NONE)-continue;-if(dmi_ident[s]&&strstr(dmi_ident[s],d->matches[i].substr))-continue;-/* No match */-gotofail;+intcount=0;+conststructdmi_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++;-}returncount;}EXPORT_SYMBOL(dmi_check_system);/**+*dmi_first_match-finddmi_system_idstructurematchingsystemDMIdata+*@list:arrayofdmi_system_idstructurestomatchagainst+*Allnon-nullelementsofthelistmustmatch+*theirslot's(fieldindex's)data(i.e.,each+*liststringmustbeasubstringofthespecified+*DMIslot'sstringdata)tobeconsidereda+*successfulmatch.+*+*Walktheblacklisttableuntilthefirstmatchisfound.Returnthe+*pointertothematchingentryorNULLifthere'snomatch.+*/+conststructdmi_system_id*dmi_first_match(conststructdmi_system_id*list)+{+conststructdmi_system_id*d;++WARN(!dmi_initialized,KERN_ERR"dmi check: not initialized yet.\n");++for(d=list;d->ident;d++)+if(dmi_match(d))+returnd;++returnNULL;+}+EXPORT_SYMBOL(dmi_first_match);++/***dmi_get_system_info-returnDMIdatavalue*@field:dataindex(seeenumdmi_field)*
From: Rafael J. Wysocki <redacted>
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 <redacted>
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(-)
From: Rafael J. Wysocki <redacted>
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 <redacted>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
drivers/ata/ahci.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
@@ -2546,6 +2546,32 @@ static void ahci_p5wdh_workaround(struct ata_host *host)}}+staticboolahci_broken_system_poweroff(structpci_dev*pdev)+{+staticconststructdmi_system_idbroken_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 */+};+conststructdmi_system_id*dmi=dmi_first_match(broken_systems);++if(dmi){+unsignedlongslot=(unsignedlong)dmi->driver_data;+/* apply the quirk only to on-board controllers */+returnslot==PCI_SLOT(pdev->devfn);+}++returnfalse;+}+staticintahci_init_one(structpci_dev*pdev,conststructpci_device_id*ent){staticintprinted_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,atothertimes,thatofthelastpossibleport,so*determiningthemaximumportnumberrequireslookingat
From: Rafael J. Wysocki <redacted>
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 <redacted>
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(-)
@@ -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+*orS5)causingsomedrivestospinupanddownagain.+*/+if((qc->ap->flags&ATA_FLAG_NO_POWEROFF_SPINDOWN)&&+system_state==SYSTEM_POWER_OFF)+gotoskip;++if((qc->ap->flags&ATA_FLAG_NO_HIBERNATE_SPINDOWN)&&+system_entering_hibernation())+gotoskip;+/* XXX: This is for backward compatibility, will be*removed.ReadDocumentation/feature-removal-schedule.txt*formoreinfo.
@@ -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;-return1;+gotoskip;}/* Issue ATA STANDBY IMMEDIATE command */
@@ -1347,10 +1358,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)return0;-invalid_fld:+invalid_fld:ata_scsi_set_sense(scmd,ILLEGAL_REQUEST,0x24,0x0);/* "Invalid field in cbd" */return1;+skip:+scmd->result=SAM_STAT_GOOD;+return1;}
From: Rafael J. Wysocki <redacted>
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 <redacted>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
drivers/ata/ata_piix.c | 34 ++++++++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
@@ -1370,6 +1370,32 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)}}+staticboolpiix_broken_system_poweroff(structpci_dev*pdev)+{+staticconststructdmi_system_idbroken_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 */+};+conststructdmi_system_id*dmi=dmi_first_match(broken_systems);++if(dmi){+unsignedlongslot=(unsignedlong)dmi->driver_data;+/* apply the quirk only to on-board controllers */+returnslot==PCI_SLOT(pdev->devfn);+}++returnfalse;+}+/***piix_init_one-RegisterPIIXATAPCIdevicewithkernelservices*@pdev:PCIdevicetoregister
@@ -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];
From: Rafael J. Wysocki <redacted>
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 <redacted>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
drivers/ata/sata_sil.c | 36 +++++++++++++++++++++++++++++++++++-
1 files changed, 35 insertions(+), 1 deletions(-)
@@ -603,11 +603,38 @@ static void sil_init_controller(struct ata_host *host)}}+staticboolsil_broken_system_poweroff(structpci_dev*pdev)+{+staticconststructdmi_system_idbroken_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 */+};+conststructdmi_system_id*dmi=dmi_first_match(broken_systems);++if(dmi){+unsignedlongslot=(unsignedlong)dmi->driver_data;+/* apply the quirk only to on-board controllers */+returnslot==PCI_SLOT(pdev->devfn);+}++returnfalse;+}+staticintsil_init_one(structpci_dev*pdev,conststructpci_device_id*ent){staticintprinted_version;intboard_id=ent->driver_data;-conststructata_port_info*ppi[]={&sil_port_info[board_id],NULL};+structata_port_infopi=sil_port_info[board_id];+conststructata_port_info*ppi[]={&pi,NULL};structata_host*host;void__iomem*mmio_base;intn_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;
From: Elias Oltmanns <redacted>
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 <redacted>
Signed-off-by: Tejun Heo <tj.kernel.org>
---
drivers/ata/libata-scsi.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
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 <redacted>
---
drivers/ata/libata-core.c | 4 +++-
include/linux/libata.h | 2 ++
2 files changed, 5 insertions(+), 1 deletions(-)
@@ -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*fewATAPIdeviceschokeonsuchDMArequests.*/-if(unlikely(qc->nbytes&15))+if(!(qc->dev->horkage&ATA_HORKAGE_ATAPI_MOD16_DMA)&&+unlikely(qc->nbytes&15))return1;if(ap->ops->check_atapi_dma)
@@ -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+notmultipleof16bytes*//* DMA mask for user DMA control: User visible values; DO NOTrenumber*/
From: Jeff Garzik <hidden> Date: 2008-11-04 06:10:58
Tejun Heo wrote:
From: Elias Oltmanns <redacted>
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 <redacted>
Signed-off-by: Tejun Heo <tj.kernel.org>
---
drivers/ata/libata-scsi.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
From: Jeff Garzik <hidden> Date: 2008-11-04 06:11:07
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 <redacted>
---
drivers/ata/libata-core.c | 4 +++-
include/linux/libata.h | 2 ++
2 files changed, 5 insertions(+), 1 deletions(-)
From: Jeff Garzik <hidden> Date: 2008-11-04 06:14:08
Tejun Heo wrote:
From: Rafael J. Wysocki <redacted>
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 <redacted>
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(-)