X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fata%2Flibata-eh.c;h=1abfdba8d99b480410706a6465c7800cb8cf8d24;hb=4ae72a1e469a3bcfd3c1f77dac62392c489bf9ca;hp=2aad7b79d6dd9cfb896bf6f76c37100c1e1083eb;hpb=a569a30d301e4dbc0ad67a211292edece2da1146;p=powerpc.git diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 2aad7b79d6..1abfdba8d9 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -332,7 +332,7 @@ void ata_scsi_error(struct Scsi_Host *host) if (ap->pflags & ATA_PFLAG_LOADING) ap->pflags &= ~ATA_PFLAG_LOADING; else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) - queue_work(ata_aux_wq, &ap->hotplug_task); + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, 0); if (ap->pflags & ATA_PFLAG_RECOVERED) ata_port_printk(ap, KERN_INFO, "EH complete\n"); @@ -1276,7 +1276,7 @@ static int ata_eh_speed_down(struct ata_device *dev, int is_io, return ATA_EH_HARDRESET; /* lower transfer mode */ - if (ata_down_xfermask_limit(dev, 0) == 0) + if (ata_down_xfermask_limit(dev, ATA_DNXFER_ANY) == 0) return ATA_EH_SOFTRESET; ata_dev_printk(dev, KERN_ERR, @@ -1443,15 +1443,10 @@ static void ata_eh_report(struct ata_port *ap) }; struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; - unsigned int nbytes; if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) continue; - nbytes = qc->nbytes; - if (!nbytes) - nbytes = qc->nsect << 9; - ata_dev_printk(qc->dev, KERN_ERR, "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " "tag %d cdb 0x%x data %u %s\n " @@ -1461,7 +1456,7 @@ static void ata_eh_report(struct ata_port *ap) cmd->lbal, cmd->lbam, cmd->lbah, cmd->hob_feature, cmd->hob_nsect, cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, - cmd->device, qc->tag, qc->cdb[0], nbytes, + cmd->device, qc->tag, qc->cdb[0], qc->nbytes, dma_str[qc->dma_dir], res->command, res->feature, res->nsect, res->lbal, res->lbam, res->lbah, @@ -1692,9 +1687,6 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, ata_class_enabled(ehc->classes[dev->devno])) { dev->class = ehc->classes[dev->devno]; - if (ap->flags & ATA_FLAG_DETECT_POLLING) - readid_flags |= ATA_READID_DETECT; - rc = ata_dev_read_id(dev, &dev->class, readid_flags, dev->id); if (rc == 0) { @@ -1799,7 +1791,7 @@ static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev) *r_failed_dev = dev; DPRINTK("EXIT\n"); - return 0; + return rc; } /** @@ -1972,7 +1964,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, { struct ata_eh_context *ehc = &ap->eh_context; struct ata_device *dev; - int down_xfermask, i, rc; + int i, rc; DPRINTK("ENTER\n"); @@ -1982,6 +1974,10 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + /* collect port action mask recorded in dev actions */ + ehc->i.action |= ehc->i.dev_action[i] & ~ATA_EH_PERDEV_MASK; + ehc->i.dev_action[i] &= ATA_EH_PERDEV_MASK; + /* process hotplug request */ if (dev->flags & ATA_DFLAG_DETACH) ata_eh_detach_dev(dev); @@ -1997,7 +1993,6 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, } retry: - down_xfermask = 0; rc = 0; /* if UNLOADING, finish immediately */ @@ -2042,10 +2037,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, /* configure transfer mode if necessary */ if (ehc->i.flags & ATA_EHI_SETMODE) { rc = ata_set_mode(ap, &dev); - if (rc) { - down_xfermask = 1; + if (rc) goto dev_fail; - } ehc->i.flags &= ~ATA_EHI_SETMODE; } @@ -2057,20 +2050,27 @@ 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, schedule probing */ - ehc->i.probe_mask |= (1 << dev->devno); case -EINVAL: + /* eeek, something went very wrong, give up */ ehc->tries[dev->devno] = 0; break; + + case -ENODEV: + /* device missing or wrong IDENTIFY data, schedule probing */ + ehc->i.probe_mask |= (1 << dev->devno); + /* give it just one more chance */ + ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: - sata_down_spd_limit(ap); - default: - ehc->tries[dev->devno]--; - if (down_xfermask && - ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1)) - ehc->tries[dev->devno] = 0; + 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]) {