summaryrefslogtreecommitdiff
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 13:38:50 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 13:38:50 -0700
commit57399ec9077a4b962b81037aaa279fab52f5e989 (patch)
tree847dfb9304001ab9ffc5eef5f20ae514cd01bb90 /drivers/ata/libata-eh.c
parente1bd2ac5a6b7a8b625e40c9e9f8b6dea4cf22f85 (diff)
parentc6e54a578133fb353a50fb44d650768b3b9eb18e (diff)
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (21 commits) libata: remove irq_on from ata_bus_reset() and ata_std_postreset() ata_piix: kill incorrect invalid map value warning libata: add another Maxtor drive with broken NCQ to the list [libata] sata_mv: Fix and clean up per-chip-generation tests [libata] sata_mv: Convert to new exception handling (EH) infrastructure [libata] sata_mv: minor bug fixes, enhancements, and cleanups (prep for new EH) [libata] sata_mv: Minor cleanups and renaming, preparing for new EH & NCQ libata-link: add PMP related ATA constants libata-link: separate out ata_eh_handle_dev_fail() pata_hpt3x3: fix DMA Kconfig option to actually have a hope of working Add Hitachi HDS7250SASUN500G 0621KTAWSD to NCQ blacklist pata_scc.c: Workaround for errata A308 libata: add FUJITSU MHV2080BH to NCQ blacklist pata_hpt3x3: major reworking and testing libata: clean up horkage handling libata: quirk IOMEGA ZIP 250 ATAPI FLOPPY libata: simplify PCI legacy SFF host handling pata_mpc52xx: suspend/resume support sata_promise: SATA hotplug support, take 2 pata_sis: FIFO whack ...
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c96
1 files changed, 52 insertions, 44 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 9ee0a8c08d96..9aa62a0754f6 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1897,6 +1897,57 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
return 1;
}
+static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+{
+ struct ata_port *ap = dev->ap;
+ struct ata_eh_context *ehc = &ap->eh_context;
+
+ ehc->tries[dev->devno]--;
+
+ switch (err) {
+ case -ENODEV:
+ /* device missing or wrong IDENTIFY data, schedule probing */
+ ehc->i.probe_mask |= (1 << dev->devno);
+ case -EINVAL:
+ /* give it just one more chance */
+ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
+ case -EIO:
+ if (ehc->tries[dev->devno] == 1) {
+ /* This is the last chance, better to slow
+ * down than lose it.
+ */
+ sata_down_spd_limit(ap);
+ ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+ }
+ }
+
+ if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+ /* disable device if it has used up all its chances */
+ ata_dev_disable(dev);
+
+ /* detach if offline */
+ if (ata_port_offline(ap))
+ ata_eh_detach_dev(dev);
+
+ /* probe if requested */
+ if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+ !(ehc->did_probe_mask & (1 << dev->devno))) {
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+
+ ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+ ehc->did_probe_mask |= (1 << dev->devno);
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
+ } else {
+ /* soft didn't work? be haaaaard */
+ if (ehc->i.flags & ATA_EHI_DID_RESET)
+ ehc->i.action |= ATA_EH_HARDRESET;
+ else
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
+}
+
/**
* ata_eh_recover - recover host port after error
* @ap: host port to recover
@@ -1997,50 +2048,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
goto out;
dev_fail:
- ehc->tries[dev->devno]--;
-
- switch (rc) {
- case -ENODEV:
- /* device missing or wrong IDENTIFY data, schedule probing */
- ehc->i.probe_mask |= (1 << dev->devno);
- case -EINVAL:
- /* give it just one more chance */
- ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
- case -EIO:
- if (ehc->tries[dev->devno] == 1) {
- /* This is the last chance, better to slow
- * down than lose it.
- */
- sata_down_spd_limit(ap);
- ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
- }
- }
-
- if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
- /* disable device if it has used up all its chances */
- ata_dev_disable(dev);
-
- /* detach if offline */
- if (ata_port_offline(ap))
- ata_eh_detach_dev(dev);
-
- /* probe if requested */
- if ((ehc->i.probe_mask & (1 << dev->devno)) &&
- !(ehc->did_probe_mask & (1 << dev->devno))) {
- ata_eh_detach_dev(dev);
- ata_dev_init(dev);
-
- ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
- ehc->did_probe_mask |= (1 << dev->devno);
- ehc->i.action |= ATA_EH_SOFTRESET;
- }
- } else {
- /* soft didn't work? be haaaaard */
- if (ehc->i.flags & ATA_EHI_DID_RESET)
- ehc->i.action |= ATA_EH_HARDRESET;
- else
- ehc->i.action |= ATA_EH_SOFTRESET;
- }
+ ata_eh_handle_dev_fail(dev, rc);
if (ata_port_nr_enabled(ap)) {
ata_port_printk(ap, KERN_WARNING, "failed to recover some "