From 4f1deba435ef75380c1d06fda860c7a15ea16fdf Mon Sep 17 00:00:00 2001 From: "JosephChan@via.com.tw" Date: Fri, 19 Mar 2010 14:08:11 +0800 Subject: pata_via: Add VIA VX900 support Signed-off-by: Joseph Chan Signed-off-by: Jeff Garzik --- drivers/ata/pata_via.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 3059ec017de3..95d39c36acea 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -677,6 +677,7 @@ static const struct pci_device_id via[] = { { PCI_VDEVICE(VIA, 0x3164), }, { PCI_VDEVICE(VIA, 0x5324), }, { PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE }, + { PCI_VDEVICE(VIA, 0x9001), VIA_IDFLAG_SINGLE }, { }, }; -- cgit v1.2.2 From 332ac7ff77cdc6a183d78ab129545d7b14a1d57c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 23 Mar 2010 12:24:08 +0900 Subject: libata-sff: fix spurious IRQ handling Commit 27943620cbd960f710a385ff4a538e14ed3f1922 introduced spurious IRQ handling but it has a race condition where valid completion can be lost while trying to clear spurious IRQ leading to occassional command timeouts. This patch improves SFF interrupt handler such that 1. Once BMDMA HSM is stopped, the condition is never considered spurious. As there's no way to resume stopped BMDMA HSM, if device status doesn't agree with BMDMA status, the only way out is aborting the command (otherwise, it will just end up timing out). 2. ap->ops->sff_check_status() can be safely called to clear spurious device IRQ as it atomically returns completion status but BMDMA IRQ status can't be cleared in safe way if command is in flight. After a spurious IRQ, call ap->ops->sff_irq_clear() only if the respective device is idle and retry completion if sff_check_status() indicates command completion. Please note that ata_piix uses bmdma_status for sff_irq_check() and #2 won't weaken spurious IRQ handling even with in-flight command because if bmdma_status indicates IRQ pending but device status is not on spurious check, the next IRQ handler invocation will abort the command due to #1. This fixes bko#15537. https://bugzilla.kernel.org/show_bug.cgi?id=15537 Signed-off-by: Tejun Heo Cc: Andrew Benton Cc: Petr Uzel Cc: Rafael J. Wysocki Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 561dec2481cb..277477251a86 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1667,6 +1667,7 @@ unsigned int ata_sff_host_intr(struct ata_port *ap, { struct ata_eh_info *ehi = &ap->link.eh_info; u8 status, host_stat = 0; + bool bmdma_stopped = false; VPRINTK("ata%u: protocol %d task_state %d\n", ap->print_id, qc->tf.protocol, ap->hsm_task_state); @@ -1699,6 +1700,7 @@ unsigned int ata_sff_host_intr(struct ata_port *ap, /* before we do anything else, clear DMA-Start bit */ ap->ops->bmdma_stop(qc); + bmdma_stopped = true; if (unlikely(host_stat & ATA_DMA_ERR)) { /* error when transfering data to/from memory */ @@ -1716,8 +1718,14 @@ unsigned int ata_sff_host_intr(struct ata_port *ap, /* check main status, clearing INTRQ if needed */ status = ata_sff_irq_status(ap); - if (status & ATA_BUSY) - goto idle_irq; + if (status & ATA_BUSY) { + if (bmdma_stopped) { + /* BMDMA engine is already stopped, we're screwed */ + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + } else + goto idle_irq; + } /* ack bmdma irq events */ ap->ops->sff_irq_clear(ap); @@ -1762,13 +1770,16 @@ EXPORT_SYMBOL_GPL(ata_sff_host_intr); irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; + bool retried = false; unsigned int i; - unsigned int handled = 0, polling = 0; + unsigned int handled, idle, polling; unsigned long flags; /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ spin_lock_irqsave(&host->lock, flags); +retry: + handled = idle = polling = 0; for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; struct ata_queued_cmd *qc; @@ -1782,7 +1793,8 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) handled |= ata_sff_host_intr(ap, qc); else polling |= 1 << i; - } + } else + idle |= 1 << i; } /* @@ -1790,7 +1802,9 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) * asserting IRQ line, nobody cared will ensue. Check IRQ * pending status if available and clear spurious IRQ. */ - if (!handled) { + if (!handled && !retried) { + bool retry = false; + for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; @@ -1805,8 +1819,23 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) ata_port_printk(ap, KERN_INFO, "clearing spurious IRQ\n"); - ap->ops->sff_check_status(ap); - ap->ops->sff_irq_clear(ap); + if (idle & (1 << i)) { + ap->ops->sff_check_status(ap); + ap->ops->sff_irq_clear(ap); + } else { + /* clear INTRQ and check if BUSY cleared */ + if (!(ap->ops->sff_check_status(ap) & ATA_BUSY)) + retry |= true; + /* + * With command in flight, we can't do + * sff_irq_clear() w/o racing with completion. + */ + } + } + + if (retry) { + retried = true; + goto retry; } } -- cgit v1.2.2 From bc8a67386fd462914269fa93446e1891955a8bb3 Mon Sep 17 00:00:00 2001 From: "JosephChan@via.com.tw" Date: Thu, 25 Mar 2010 20:51:47 +0800 Subject: pata_via: fix VT6410/6415/6330 detection issue When using VT6410/6415/6330 chips on some VIA's platforms, the HDD connection to VT6410/6415/6330 cannot be detected. It is because the driver detects wrong via_isa_bridge ID, and then causes this issue to happen. Signed-off-by: Joseph Chan Signed-off-by: Jeff Garzik --- drivers/ata/pata_via.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 95d39c36acea..c59b40710fbd 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -576,6 +576,10 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) u8 rev = isa->revision; pci_dev_put(isa); + if ((id->device == 0x0415 || id->device == 0x3164) && + (config->id != id->device)) + continue; + if (rev >= config->rev_min && rev <= config->rev_max) break; } -- cgit v1.2.2 From 5a0e3ad6af8660be21ca98a971cd00f331318c05 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Mar 2010 17:04:11 +0900 Subject: include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h percpu.h is included by sched.h and module.h and thus ends up being included when building most .c files. percpu.h includes slab.h which in turn includes gfp.h making everything defined by the two files universally available and complicating inclusion dependencies. percpu.h -> slab.h dependency is about to be removed. Prepare for this change by updating users of gfp and slab facilities include those headers directly instead of assuming availability. As this conversion needs to touch large number of source files, the following script is used as the basis of conversion. http://userweb.kernel.org/~tj/misc/slabh-sweep.py The script does the followings. * Scan files for gfp and slab usages and update includes such that only the necessary includes are there. ie. if only gfp is used, gfp.h, if slab is used, slab.h. * When the script inserts a new include, it looks at the include blocks and try to put the new include such that its order conforms to its surrounding. It's put in the include block which contains core kernel includes, in the same order that the rest are ordered - alphabetical, Christmas tree, rev-Xmas-tree or at the end if there doesn't seem to be any matching order. * If the script can't find a place to put a new include (mostly because the file doesn't have fitting include block), it prints out an error message indicating which .h file needs to be added to the file. The conversion was done in the following steps. 1. The initial automatic conversion of all .c files updated slightly over 4000 files, deleting around 700 includes and adding ~480 gfp.h and ~3000 slab.h inclusions. The script emitted errors for ~400 files. 2. Each error was manually checked. Some didn't need the inclusion, some needed manual addition while adding it to implementation .h or embedding .c file was more appropriate for others. This step added inclusions to around 150 files. 3. The script was run again and the output was compared to the edits from #2 to make sure no file was left behind. 4. Several build tests were done and a couple of problems were fixed. e.g. lib/decompress_*.c used malloc/free() wrappers around slab APIs requiring slab.h to be added manually. 5. The script was run on all .h files but without automatically editing them as sprinkling gfp.h and slab.h inclusions around .h files could easily lead to inclusion dependency hell. Most gfp.h inclusion directives were ignored as stuff from gfp.h was usually wildly available and often used in preprocessor macros. Each slab.h inclusion directive was examined and added manually as necessary. 6. percpu.h was updated not to include slab.h. 7. Build test were done on the following configurations and failures were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my distributed build env didn't work with gcov compiles) and a few more options had to be turned off depending on archs to make things build (like ipr on powerpc/64 which failed due to missing writeq). * x86 and x86_64 UP and SMP allmodconfig and a custom test config. * powerpc and powerpc64 SMP allmodconfig * sparc and sparc64 SMP allmodconfig * ia64 SMP allmodconfig * s390 SMP allmodconfig * alpha SMP allmodconfig * um on x86_64 SMP allmodconfig 8. percpu.h modifications were reverted so that it could be applied as a separate patch and serve as bisection point. Given the fact that I had only a couple of failures from tests on step 6, I'm fairly confident about the coverage of this conversion patch. If there is a breakage, it's likely to be something in one of the arch headers which should be easily discoverable easily on most builds of the specific arch. Signed-off-by: Tejun Heo Guess-its-ok-by: Christoph Lameter Cc: Ingo Molnar Cc: Lee Schermerhorn --- drivers/ata/ahci.c | 1 + drivers/ata/ata_piix.c | 1 + drivers/ata/libata-acpi.c | 1 + drivers/ata/libata-core.c | 1 + drivers/ata/libata-pmp.c | 1 + drivers/ata/libata-scsi.c | 1 + drivers/ata/libata-sff.c | 1 + drivers/ata/pata_acpi.c | 1 + drivers/ata/pata_at32.c | 1 + drivers/ata/pata_at91.c | 1 + drivers/ata/pata_atp867x.c | 1 + drivers/ata/pata_cmd640.c | 1 + drivers/ata/pata_icside.c | 1 + drivers/ata/pata_it821x.c | 1 + drivers/ata/pata_macio.c | 1 + drivers/ata/pata_mpc52xx.c | 2 +- drivers/ata/pata_octeon_cf.c | 1 + drivers/ata/pata_pcmcia.c | 1 + drivers/ata/pata_rb532_cf.c | 1 + drivers/ata/pata_rdc.c | 1 + drivers/ata/pata_via.c | 1 + drivers/ata/pdc_adma.c | 1 + drivers/ata/sata_fsl.c | 1 + drivers/ata/sata_inic162x.c | 1 + drivers/ata/sata_mv.c | 1 + drivers/ata/sata_nv.c | 1 + drivers/ata/sata_promise.c | 1 + drivers/ata/sata_qstor.c | 1 + drivers/ata/sata_sil24.c | 1 + drivers/ata/sata_sx4.c | 1 + drivers/ata/sata_uli.c | 1 + 31 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fdc9bcbe55a2..5326af28a410 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index c33806654e46..83bc49fac9bb 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -90,6 +90,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 292fdbc0431a..7b5eea7e01dc 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "libata.h" diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4a28420efff2..3f6771e63230 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 51f0ffb78cbd..00305f41ed86 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -9,6 +9,7 @@ #include #include +#include #include "libata.h" const struct ata_port_operations sata_pmp_port_ops = { diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index bea003a24d27..0088cdeb0b1e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -33,6 +33,7 @@ * */ +#include #include #include #include diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 277477251a86..6411e0c7b9fe 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -33,6 +33,7 @@ */ #include +#include #include #include #include diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 8e5e13210426..1ea2be0f4b94 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index 5c129f99a7e3..66ce6a526f27 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 376dd380b43c..c6a946aa252c 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 6fe7ded40c6a..bb6e0746e07d 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c index 6cd5d5dd9e3b..45896b3c6538 100644 --- a/drivers/ata/pata_cmd640.c +++ b/drivers/ata/pata_cmd640.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index b663b7ffae4b..fa812e206eeb 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 9bde1cb5f981..5cb286fd839e 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index 4cc7bbd10ec2..211b6438b3a0 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 2bc2dbe30e8f..9f5b053611dd 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 37ef416c1242..005a44483a7b 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 147de2fd66d2..3c3172d3c34e 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 45f1e10f917b..0ffd631000b7 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -19,6 +19,7 @@ * */ +#include #include #include #include diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c index 237a24d41a2d..37092cfd7bc6 100644 --- a/drivers/ata/pata_rdc.c +++ b/drivers/ata/pata_rdc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index c59b40710fbd..741e7cb69d8c 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index 6c65b0776a2c..5904cfdb8dbe 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index ce4136eea08f..a69192b38b43 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 4406902b4293..27dc6c86a4cd 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -39,6 +39,7 @@ * happy to assist. */ +#include #include #include #include diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index df8ee325d3ca..71cc0d42f9e1 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 684fe04dbbb7..2a98b09ab735 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -38,6 +38,7 @@ #include #include +#include #include #include #include diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 63306285c843..5356ec00d2b4 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 326c0cfc29b3..92ba45e6689b 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 1370df6c420c..433b6b89c795 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index bbcf970068ad..232468f2ea90 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index e5bff47e8aa1..011e098590d1 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include -- cgit v1.2.2 From c710f785329aa751e6cf3b901c1cef167ea0648d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 Mar 2010 16:41:18 +0900 Subject: libata: don't whine on spurious IRQ On configurations where IRQ line is shared with a different controller, spurious IRQs may happen continuously. The message was put there primarily for debugging anyway. Kill it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 6411e0c7b9fe..e3877b6843c9 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1816,10 +1816,6 @@ retry: !ap->ops->sff_irq_check(ap)) continue; - if (printk_ratelimit()) - ata_port_printk(ap, KERN_INFO, - "clearing spurious IRQ\n"); - if (idle & (1 << i)) { ap->ops->sff_check_status(ap); ap->ops->sff_irq_clear(ap); -- cgit v1.2.2 From 68b0ddb289220b6d4d865be128939663be34959d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 5 Apr 2010 10:51:26 +0900 Subject: libata: disable NCQ on Crucial C300 SSD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Crucial said, Thank you for contacting us. We know that with our M225 line of SSDs you sometimes need to disable NCQ (native command queuing) to avoid just the type of errors you're seeing. Our recommendation for the M225 is to add libata.force=noncq to your Linux kernel boot options, under the kernel ATA library option. I have sent your feedback to the engineers working on the C300, and asked them to please pass it on to the firmware team. I have been notified that they are in the process of testing and finalizing a new firmware version, that you can expect to see released around the end of April. We’ll keep you posted as to when it will be available for download. So, turn off NCQ on the drive w/ the current firmware revision. Reported in the following bug. https://bugzilla.kernel.org/show_bug.cgi?id=15573 Signed-off-by: Tejun Heo Reported-by: lethalwp@scarlet.be Reported-by: Luke Macken Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3f6771e63230..2ab34dc97f6f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4354,6 +4354,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, + /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */ + { "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, }, + /* devices which puke on READ_NATIVE_MAX */ { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA }, -- cgit v1.2.2 From 445d211b0da4e9a6e6d576edff85085c2aaf53df Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 5 Apr 2010 10:33:13 +0900 Subject: libata: unlock HPA if device shrunk Some BIOSes don't configure HPA during boot but do so while resuming. This causes harddrives to shrink during resume making libata detach and reattach them. This can be worked around by unlocking HPA if old size equals native size. Add ATA_DFLAG_UNLOCK_HPA so that HPA unlocking can be controlled per-device and update ata_dev_revalidate() such that it sets ATA_DFLAG_UNLOCK_HPA and fails with -EIO when the above condition is detected. This patch fixes the following bug. https://bugzilla.kernel.org/show_bug.cgi?id=15396 Signed-off-by: Tejun Heo Reported-by: Oleksandr Yermolenko Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 74 ++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 29 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2ab34dc97f6f..49cffb6094a3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1494,6 +1494,7 @@ static int ata_hpa_resize(struct ata_device *dev) { struct ata_eh_context *ehc = &dev->link->eh_context; int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; + bool unlock_hpa = ata_ignore_hpa || dev->flags & ATA_DFLAG_UNLOCK_HPA; u64 sectors = ata_id_n_sectors(dev->id); u64 native_sectors; int rc; @@ -1510,7 +1511,7 @@ static int ata_hpa_resize(struct ata_device *dev) /* If device aborted the command or HPA isn't going to * be unlocked, skip HPA resizing. */ - if (rc == -EACCES || !ata_ignore_hpa) { + if (rc == -EACCES || !unlock_hpa) { ata_dev_printk(dev, KERN_WARNING, "HPA support seems " "broken, skipping HPA handling\n"); dev->horkage |= ATA_HORKAGE_BROKEN_HPA; @@ -1525,7 +1526,7 @@ static int ata_hpa_resize(struct ata_device *dev) dev->n_native_sectors = native_sectors; /* nothing to do? */ - if (native_sectors <= sectors || !ata_ignore_hpa) { + if (native_sectors <= sectors || !unlock_hpa) { if (!print_info || native_sectors == sectors) return 0; @@ -4186,36 +4187,51 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, goto fail; /* verify n_sectors hasn't changed */ - if (dev->class == ATA_DEV_ATA && n_sectors && - dev->n_sectors != n_sectors) { - ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch " - "%llu != %llu\n", - (unsigned long long)n_sectors, - (unsigned long long)dev->n_sectors); - /* - * Something could have caused HPA to be unlocked - * involuntarily. If n_native_sectors hasn't changed - * and the new size matches it, keep the device. - */ - if (dev->n_native_sectors == n_native_sectors && - dev->n_sectors > n_sectors && - dev->n_sectors == n_native_sectors) { - ata_dev_printk(dev, KERN_WARNING, - "new n_sectors matches native, probably " - "late HPA unlock, continuing\n"); - /* keep using the old n_sectors */ - dev->n_sectors = n_sectors; - } else { - /* restore original n_[native]_sectors and fail */ - dev->n_native_sectors = n_native_sectors; - dev->n_sectors = n_sectors; - rc = -ENODEV; - goto fail; - } + if (dev->class != ATA_DEV_ATA || !n_sectors || + dev->n_sectors == n_sectors) + return 0; + + /* n_sectors has changed */ + ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n", + (unsigned long long)n_sectors, + (unsigned long long)dev->n_sectors); + + /* + * Something could have caused HPA to be unlocked + * involuntarily. If n_native_sectors hasn't changed and the + * new size matches it, keep the device. + */ + if (dev->n_native_sectors == n_native_sectors && + dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) { + ata_dev_printk(dev, KERN_WARNING, + "new n_sectors matches native, probably " + "late HPA unlock, continuing\n"); + /* keep using the old n_sectors */ + dev->n_sectors = n_sectors; + return 0; } - return 0; + /* + * Some BIOSes boot w/o HPA but resume w/ HPA locked. Try + * unlocking HPA in those cases. + * + * https://bugzilla.kernel.org/show_bug.cgi?id=15396 + */ + if (dev->n_native_sectors == n_native_sectors && + dev->n_sectors < n_sectors && n_sectors == n_native_sectors && + !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) { + ata_dev_printk(dev, KERN_WARNING, + "old n_sectors matches native, probably " + "late HPA lock, will try to unlock HPA\n"); + /* try unlocking HPA */ + dev->flags |= ATA_DFLAG_UNLOCK_HPA; + rc = -EIO; + } else + rc = -ENODEV; + /* restore original n_[native_]sectors and fail */ + dev->n_native_sectors = n_native_sectors; + dev->n_sectors = n_sectors; fail: ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); return rc; -- cgit v1.2.2