From 002c8054fa8d0f1afce2b0c728be32d338b9293a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH 01/22] [PATCH] libata: implement ata_dev_absent() For the time being we cannot use ata_dev_present() as it was renamed to ata_dev_enabled() but we still need presence test. Implement negation of the test. Conveniently, the negated result is needed in more places. This is suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/libata.h b/include/linux/libata.h index c6883ba8cba..0f8e3720edd 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -682,6 +682,11 @@ static inline unsigned int ata_class_disabled(unsigned int class) return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP; } +static inline unsigned int ata_class_absent(unsigned int class) +{ + return !ata_class_enabled(class) && !ata_class_disabled(class); +} + static inline unsigned int ata_dev_enabled(const struct ata_device *dev) { return ata_class_enabled(dev->class); @@ -692,6 +697,11 @@ static inline unsigned int ata_dev_disabled(const struct ata_device *dev) return ata_class_disabled(dev->class); } +static inline unsigned int ata_dev_absent(const struct ata_device *dev) +{ + return ata_class_absent(dev->class); +} + static inline u8 ata_chk_status(struct ata_port *ap) { return ap->ops->check_status(ap); From 1c3fae4d7eb121933341443c37d3bbee43c0fb68 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 20:53:28 +0900 Subject: [PATCH 02/22] [PATCH] libata: implement ap->sata_spd_limit and helpers ap->sata_spd_limit contrains SATA PHY speed of the port. It is initialized to the configured value prior to probing thus preserving BIOS configured value. hardreset is responsible for applying SPD limit and sata_std_hardreset() is updated to do that. SATA SPD limit will be used to enhance failure handling during probing and later by EH. This patch also normalizes some comments around affected code. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 143 +++++++++++++++++++++++++++++++++++-- include/linux/libata.h | 1 + 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3acf56200d8..63488673765 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,6 +65,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); +static int ata_down_sata_spd_limit(struct ata_port *ap); static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); @@ -1596,6 +1597,120 @@ void ata_port_disable(struct ata_port *ap) ap->flags |= ATA_FLAG_PORT_DISABLED; } +/** + * ata_down_sata_spd_limit - adjust SATA spd limit downward + * @ap: Port to adjust SATA spd limit for + * + * Adjust SATA spd limit of @ap downward. Note that this + * function only adjusts the limit. The change must be applied + * using ata_set_sata_spd(). + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +static int ata_down_sata_spd_limit(struct ata_port *ap) +{ + u32 spd, mask; + int highbit; + + if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + return -EOPNOTSUPP; + + mask = ap->sata_spd_limit; + if (mask <= 1) + return -EINVAL; + highbit = fls(mask) - 1; + mask &= ~(1 << highbit); + + spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf; + if (spd <= 1) + return -EINVAL; + spd--; + mask &= (1 << spd) - 1; + if (!mask) + return -EINVAL; + + ap->sata_spd_limit = mask; + + printk(KERN_WARNING "ata%u: limiting SATA link speed to %s\n", + ap->id, sata_spd_string(fls(mask))); + + return 0; +} + +static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) +{ + u32 spd, limit; + + if (ap->sata_spd_limit == UINT_MAX) + limit = 0; + else + limit = fls(ap->sata_spd_limit); + + spd = (*scontrol >> 4) & 0xf; + *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4); + + return spd != limit; +} + +/** + * ata_set_sata_spd_needed - is SATA spd configuration needed + * @ap: Port in question + * + * Test whether the spd limit in SControl matches + * @ap->sata_spd_limit. This function is used to determine + * whether hardreset is necessary to apply SATA spd + * configuration. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 1 if SATA spd configuration is needed, 0 otherwise. + */ +static int ata_set_sata_spd_needed(struct ata_port *ap) +{ + u32 scontrol; + + if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + return 0; + + scontrol = scr_read(ap, SCR_CONTROL); + + return __ata_set_sata_spd_needed(ap, &scontrol); +} + +/** + * ata_set_sata_spd - set SATA spd according to spd limit + * @ap: Port to set SATA spd for + * + * Set SATA spd of @ap according to sata_spd_limit. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 if spd doesn't need to be changed, 1 if spd has been + * changed. -EOPNOTSUPP if SCR registers are inaccessible. + */ +static int ata_set_sata_spd(struct ata_port *ap) +{ + u32 scontrol; + + if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) + return -EOPNOTSUPP; + + scontrol = scr_read(ap, SCR_CONTROL); + if (!__ata_set_sata_spd_needed(ap, &scontrol)) + return 0; + + scr_write(ap, SCR_CONTROL, scontrol); + return 1; +} + /* * This mode timing computation functionality is ported over from * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik @@ -2165,7 +2280,14 @@ static int sata_phy_resume(struct ata_port *ap) void ata_std_probeinit(struct ata_port *ap) { if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { + u32 spd; + sata_phy_resume(ap); + + spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; + if (spd) + ap->sata_spd_limit &= (1 << spd) - 1; + if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } @@ -2253,18 +2375,30 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) DPRINTK("ENTER\n"); - /* Issue phy wake/reset */ + if (ata_set_sata_spd_needed(ap)) { + /* SATA spec says nothing about how to reconfigure + * spd. To be on the safe side, turn off phy during + * reconfiguration. This works for at least ICH7 AHCI + * and Sil3124. + */ + scontrol = scr_read(ap, SCR_CONTROL); + scontrol = (scontrol & 0x0f0) | 0x302; + scr_write_flush(ap, SCR_CONTROL, scontrol); + + ata_set_sata_spd(ap); + } + + /* issue phy wake/reset */ scontrol = scr_read(ap, SCR_CONTROL); scontrol = (scontrol & 0x0f0) | 0x301; scr_write_flush(ap, SCR_CONTROL, scontrol); - /* - * Couldn't find anything in SATA I/II specs, but AHCI-1.1 + /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 * 10.4.2 says at least 1 ms. */ msleep(1); - /* Bring phy back */ + /* bring phy back */ sata_phy_resume(ap); /* TODO: phy layer with polling, timeouts, etc. */ @@ -4454,6 +4588,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->flags |= ent->host_flags; ap->ops = ent->port_ops; ap->cbl = ATA_CBL_NONE; + ap->sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; diff --git a/include/linux/libata.h b/include/linux/libata.h index 0f8e3720edd..a5207e66ca5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -397,6 +397,7 @@ struct ata_port { unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ + unsigned int sata_spd_limit; /* SATA PHY speed limit */ struct ata_device device[ATA_MAX_DEVICES]; From 90dac02c08dabd471927f151b8393eb51e3e020e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH 03/22] [PATCH] libata: use SATA speed down in ata_drive_probe_reset() Make ata_drive_probe_reset() use SATA SPD configuration. Hardreset will be force if speed renegotiation is necessary. Also, if a hardreset fails, PHY speed is stepped down and hardreset is retried until the lowest speed is reached. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 63488673765..4fd24075afd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2578,7 +2578,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (probeinit) probeinit(ap); - if (softreset) { + if (softreset && !ata_set_sata_spd_needed(ap)) { rc = ata_do_reset(ap, softreset, postreset, 0, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2587,9 +2587,17 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (!hardreset) goto done; - rc = ata_do_reset(ap, hardreset, postreset, 0, classes); - if (rc || classes[0] != ATA_DEV_UNKNOWN) - goto done; + while (1) { + rc = ata_do_reset(ap, hardreset, postreset, 0, classes); + if (rc == 0) { + if (classes[0] != ATA_DEV_UNKNOWN) + goto done; + break; + } + + if (ata_down_sata_spd_limit(ap)) + goto done; + } if (softreset) rc = ata_do_reset(ap, softreset, postreset, 0, classes); From edbabd8679a39faef67def4438c9cbccb5c05c5d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 20:55:02 +0900 Subject: [PATCH 04/22] [PATCH] libata: add 5s sleep between resets Some devices react badly if resets are performed back-to-back. Give devices some time to breath and tell user that we're taking a nap. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4fd24075afd..3ddfbe1b86c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2582,6 +2582,9 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, rc = ata_do_reset(ap, softreset, postreset, 0, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; + printk(KERN_INFO "ata%u: softreset failed, will try " + "hardreset in 5 secs\n", ap->id); + ssleep(5); } if (!hardreset) @@ -2597,10 +2600,20 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, if (ata_down_sata_spd_limit(ap)) goto done; + + printk(KERN_INFO "ata%u: hardreset failed, will retry " + "in 5 secs\n", ap->id); + ssleep(5); } - if (softreset) + if (softreset) { + printk(KERN_INFO "ata%u: hardreset succeeded without " + "classification, will retry softreset in 5 secs\n", + ap->id); + ssleep(5); + rc = ata_do_reset(ap, softreset, postreset, 0, classes); + } done: if (rc == 0 && classes[0] == ATA_DEV_UNKNOWN) From cf176e1aa92eb2a3faea8409e841396a66413937 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH 05/22] [PATCH] libata: implement ata_down_xfermask_limit() Implement ata_down_xfermask_limit(). This function manipulates @dev->pio/mwdma/udma_mask such that the next lower transfer mode is selected. This will be used to improve ata_bus_probe() failure handling and later by EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3ddfbe1b86c..68fa64d2472 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,6 +65,8 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); +static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0); static int ata_down_sata_spd_limit(struct ata_port *ap); static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, @@ -1859,6 +1861,56 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, return 0; } +/** + * ata_down_xfermask_limit - adjust dev xfer masks downward + * @ap: Port associated with device @dev + * @dev: Device to adjust xfer masks + * @force_pio0: Force PIO0 + * + * Adjust xfer masks of @dev downward. Note that this function + * does not apply the change. Invoking ata_set_mode() afterwards + * will apply the limit. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0) +{ + unsigned long xfer_mask; + int highbit; + + xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask, + dev->udma_mask); + + if (!xfer_mask) + goto fail; + /* don't gear down to MWDMA from UDMA, go directly to PIO */ + if (xfer_mask & ATA_MASK_UDMA) + xfer_mask &= ~ATA_MASK_MWDMA; + + highbit = fls(xfer_mask) - 1; + xfer_mask &= ~(1 << highbit); + if (force_pio0) + xfer_mask &= 1 << ATA_SHIFT_PIO; + if (!xfer_mask) + goto fail; + + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, + &dev->udma_mask); + + printk(KERN_WARNING "ata%u: dev %u limiting speed to %s\n", + ap->id, dev->devno, ata_mode_string(xfer_mask)); + + return 0; + + fail: + return -EINVAL; +} + static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { unsigned int err_mask; From 14d2bac1877ed4e2cc940d1680db1a4f29225811 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:46 +0900 Subject: [PATCH 06/22] [PATCH] libata: improve ata_bus_probe() Improve ata_bus_probe() such that configuration failures are handled better. Each device is given ATA_PROBE_MAX_TRIES chances, but any non-transient error (revalidation failure with -ENODEV, configuration failure with -EINVAL...) disables the device directly. Any IO error results in SATA PHY speed down and ata_set_mode() failure lowers transfer mode. The last try always puts a device into PIO-0. After each failure, the whole port is reset to make sure that the controller and all the devices are in a known and stable state. The reset also applies SATA SPD configuration if necessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 65 ++++++++++++++++++++++++++++---------- include/linux/libata.h | 3 ++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 68fa64d2472..33b5bff58cc 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1370,11 +1370,18 @@ err_out_nosup: static int ata_bus_probe(struct ata_port *ap) { unsigned int classes[ATA_MAX_DEVICES]; - int i, rc, found = 0; + int tries[ATA_MAX_DEVICES]; + int i, rc, down_xfermask; struct ata_device *dev; ata_port_probe(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) + tries[i] = ATA_PROBE_MAX_TRIES; + + retry: + down_xfermask = 0; + /* reset and determine device classes */ for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ATA_DEV_UNKNOWN; @@ -1404,21 +1411,23 @@ static int ata_bus_probe(struct ata_port *ap) dev = &ap->device[i]; dev->class = classes[i]; + if (!tries[i]) { + ata_down_xfermask_limit(ap, dev, 1); + ata_dev_disable(ap, dev); + } + if (!ata_dev_enabled(dev)) continue; - WARN_ON(dev->id != NULL); - if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) { - dev->class = ATA_DEV_NONE; - continue; - } + kfree(dev->id); + dev->id = NULL; + rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); + if (rc) + goto fail; - if (ata_dev_configure(ap, dev, 1)) { - ata_dev_disable(ap, dev); - continue; - } - - found = 1; + rc = ata_dev_configure(ap, dev, 1); + if (rc) + goto fail; } /* configure transfer mode */ @@ -1427,12 +1436,18 @@ static int ata_bus_probe(struct ata_port *ap) * return error code and failing device on failure as * ata_set_mode() does. */ - if (found) - ap->ops->set_mode(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) { + ap->ops->set_mode(ap); + break; + } rc = 0; } else { - while (ata_set_mode(ap, &dev)) - ata_dev_disable(ap, dev); + rc = ata_set_mode(ap, &dev); + if (rc) { + down_xfermask = 1; + goto fail; + } } for (i = 0; i < ATA_MAX_DEVICES; i++) @@ -1443,6 +1458,24 @@ static int ata_bus_probe(struct ata_port *ap) ata_port_disable(ap); ap->ops->port_disable(ap); return -ENODEV; + + fail: + switch (rc) { + case -EINVAL: + case -ENODEV: + tries[dev->devno] = 0; + break; + case -EIO: + ata_down_sata_spd_limit(ap); + /* fall through */ + default: + tries[dev->devno]--; + if (down_xfermask && + ata_down_xfermask_limit(ap, dev, tries[dev->devno] == 1)) + tries[dev->devno] = 0; + } + + goto retry; } /** diff --git a/include/linux/libata.h b/include/linux/libata.h index a5207e66ca5..a4a1e6304e7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -211,6 +211,9 @@ enum { /* Masks for port functions */ ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), + + /* how hard are we gonna try to probe/recover devices */ + ATA_PROBE_MAX_TRIES = 3, }; enum hsm_task_states { From 565083e1f14e7771aa6bac2d3d4aae0b08d48d78 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 17:54:47 +0900 Subject: [PATCH 07/22] [PATCH] libata: consider disabled devices in ata_dev_xfermask() ata_bus_probe() now marks failed devices properly and leaves meaningful transfer mode masks. This patch makes ata_dev_xfermask() consider disable devices when determining PIO mode to avoid violating device selection timing. While at it, move port-wide resttriction out of device iteration loop and try to make the function look a bit prettier. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 33b5bff58cc..00018705582 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2913,23 +2913,34 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) unsigned long xfer_mask; int i; - xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, - ap->udma_mask); + xfer_mask = ata_pack_xfermask(ap->pio_mask, + ap->mwdma_mask, ap->udma_mask); + + /* Apply cable rule here. Don't apply it early because when + * we handle hot plug the cable type can itself change. + */ + if (ap->cbl == ATA_CBL_PATA40) + xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); /* FIXME: Use port-wide xfermask for now */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *d = &ap->device[i]; - if (!ata_dev_enabled(d)) + + if (ata_dev_absent(d)) continue; - xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask, - d->udma_mask); + + if (ata_dev_disabled(d)) { + /* to avoid violating device selection timing */ + xfer_mask &= ata_pack_xfermask(d->pio_mask, + UINT_MAX, UINT_MAX); + continue; + } + + xfer_mask &= ata_pack_xfermask(d->pio_mask, + d->mwdma_mask, d->udma_mask); xfer_mask &= ata_id_xfermask(d->id); if (ata_dma_blacklisted(d)) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - /* Apply cable rule here. Don't apply it early because when - we handle hot plug the cable type can itself change */ - if (ap->cbl == ATA_CBL_PATA40) - xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); } if (ata_dma_blacklisted(dev)) @@ -2940,11 +2951,12 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) if (hs->simplex_claimed) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); } + if (ap->ops->mode_filter) xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask); - ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, - &dev->udma_mask); + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, + &dev->mwdma_mask, &dev->udma_mask); } /** From d63cb4a6365aa161341fc365df1edc87cd00c9c0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH 08/22] [PATCH] libata: report device number when PIO fails Report device number on PIO failure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 00018705582..15d6c24c8e5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3909,7 +3909,8 @@ static void ata_pio_error(struct ata_port *ap) WARN_ON(qc == NULL); if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_WARNING "ata%u: PIO error\n", ap->id); + printk(KERN_WARNING "ata%u: dev %u PIO error\n", + ap->id, qc->dev->devno); /* make sure qc->err_mask is available to * know what's wrong and recover From 5eb45c02a9944e813a0b82457607557a1f2c64b5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH 09/22] [PATCH] libata: ata_dev_revalidate() printk update Make sure ata_dev_revalidate() complains on failures and kill revalidation failure message printed from ata_dev_set_mode(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 15d6c24c8e5..f39352a3ac1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1961,12 +1961,8 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) } rc = ata_dev_revalidate(ap, dev, 0); - if (rc) { - printk(KERN_ERR - "ata%u: failed to revalidate after set xfermode\n", - ap->id); + if (rc) return rc; - } DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", dev->xfer_shift, (int)dev->xfer_mode); @@ -2786,15 +2782,14 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, int post_reset) { - unsigned int class; - u16 *id; + unsigned int class = dev->class; + u16 *id = NULL; int rc; - if (!ata_dev_enabled(dev)) - return -ENODEV; - - class = dev->class; - id = NULL; + if (!ata_dev_enabled(dev)) { + rc = -ENODEV; + goto fail; + } /* allocate & read ID data */ rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); @@ -2811,7 +2806,9 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, dev->id = id; /* configure device according to the new ID */ - return ata_dev_configure(ap, dev, 0); + rc = ata_dev_configure(ap, dev, 0); + if (rc == 0) + return 0; fail: printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", From c43c555c3a6db7f0b55fd9b66d7ecff16e827d4e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH 10/22] [PATCH] libata: ATA_FLAG_IN_EH is not used, kill it Kill unused flag ATA_FLAG_IN_EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 19 +++++-------------- include/linux/libata.h | 1 - 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index c1a4b29a9ae..bcbf71e9895 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -779,31 +779,22 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) int ata_scsi_error(struct Scsi_Host *host) { - struct ata_port *ap; - unsigned long flags; + struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; DPRINTK("ENTER\n"); - ap = (struct ata_port *) &host->hostdata[0]; - - spin_lock_irqsave(&ap->host_set->lock, flags); - WARN_ON(ap->flags & ATA_FLAG_IN_EH); - ap->flags |= ATA_FLAG_IN_EH; - WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - + /* synchronize with IRQ handler and port task */ + spin_unlock_wait(&ap->host_set->lock); ata_port_flush_task(ap); + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + ap->ops->eng_timeout(ap); WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); scsi_eh_flush_done_q(&ap->eh_done_q); - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_IN_EH; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - DPRINTK("EXIT\n"); return 0; } diff --git a/include/linux/libata.h b/include/linux/libata.h index a4a1e6304e7..e20b0bfbd5f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -152,7 +152,6 @@ enum { ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */ - ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ From 949b38af40a0b88b7267908b1554a45b97b5b737 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH 11/22] [PATCH] libata: clean up constants * Reorder ATA_DFLAG_* such that feature flags determined by ata_dev_configure() are on lower bits. Reserve lower eight bits for this purpose and allocate dynamic flags from bit 8. * Reorder ATA_FLAG_* such that feature flags determined during driver initiailization are on bits 0:15, dynamic flags on 16:23 and LLDD specific flags on 24:31. * Kill trailing white space and lower-case an one line comment for consistency. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 53 ++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index e20b0bfbd5f..b7488a31e32 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -120,9 +120,10 @@ enum { ATA_SHT_USE_CLUSTERING = 1, /* struct ata_device stuff */ - ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ - ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ - ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */ + ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ + ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ + + ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -132,32 +133,34 @@ enum { ATA_DEV_NONE = 5, /* no device */ /* struct ata_port flags */ - ATA_FLAG_SLAVE_POSS = (1 << 1), /* host supports slave dev */ + ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ /* (doesn't imply presence) */ - ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */ - ATA_FLAG_SATA = (1 << 3), - ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */ - ATA_FLAG_SRST = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */ - ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ - ATA_FLAG_SATA_RESET = (1 << 7), /* (obsolete) use COMRESET */ - ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ - ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once - * proper HSM is in place. */ - ATA_FLAG_DEBUGMSG = (1 << 10), - ATA_FLAG_NO_ATAPI = (1 << 11), /* No ATAPI support */ + ATA_FLAG_SATA = (1 << 1), + ATA_FLAG_NO_LEGACY = (1 << 2), /* no legacy mode check */ + ATA_FLAG_MMIO = (1 << 3), /* use MMIO, not PIO */ + ATA_FLAG_SRST = (1 << 4), /* (obsolete) use ATA SRST, not E.D.D. */ + ATA_FLAG_SATA_RESET = (1 << 5), /* (obsolete) use COMRESET */ + ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ + ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ + ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ + ATA_FLAG_IRQ_MASK = (1 << 9), /* Mask IRQ in PIO xfers */ - ATA_FLAG_SUSPENDED = (1 << 12), /* port is suspended */ + ATA_FLAG_NOINTR = (1 << 16), /* FIXME: Remove this once + * proper HSM is in place. */ + ATA_FLAG_DEBUGMSG = (1 << 17), + ATA_FLAG_FLUSH_PORT_TASK = (1 << 18), /* flush port task */ - ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ - ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ + ATA_FLAG_PORT_DISABLED = (1 << 19), /* port is disabled, ignore it */ + ATA_FLAG_SUSPENDED = (1 << 20), /* port is suspended */ - ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */ + /* bits 24:31 of ap->flags are reserved for LLDD specific flags */ - ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ - ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ - ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ + /* struct ata_queued_cmd flags */ + ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ + ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */ + ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, - ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ + ATA_QCFLAG_EH_SCHEDULED = (1 << 3), /* EH scheduled */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ @@ -206,8 +209,8 @@ enum { /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, - - /* Masks for port functions */ + + /* masks for port functions */ ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), From 198e0fed9e59461fc1890dd8b75ec72d14638873 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:52 +0900 Subject: [PATCH 12/22] [PATCH] libata: rename ATA_FLAG_PORT_DISABLED to ATA_FLAG_DISABLED Rename ATA_FLAG_PORT_DISABLED to ATA_FLAG_DISABLED for consistency. (ATA_FLAG_* are always about ports). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 18 +++++++++--------- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/pdc_adma.c | 4 ++-- drivers/scsi/sata_mv.c | 2 +- drivers/scsi/sata_nv.c | 2 +- drivers/scsi/sata_promise.c | 2 +- drivers/scsi/sata_qstor.c | 4 ++-- drivers/scsi/sata_sil24.c | 2 +- drivers/scsi/sata_sx4.c | 2 +- drivers/scsi/sata_vsc.c | 2 +- include/linux/libata.h | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f39352a3ac1..53226b16355 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1045,7 +1045,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, * * Kill the following code as soon as those drivers are fixed. */ - if (ap->flags & ATA_FLAG_PORT_DISABLED) { + if (ap->flags & ATA_FLAG_DISABLED) { err_mask |= AC_ERR_SYSTEM; ata_port_probe(ap); } @@ -1395,7 +1395,7 @@ static int ata_bus_probe(struct ata_port *ap) } else { ap->ops->phy_reset(ap); - if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) + if (!(ap->flags & ATA_FLAG_DISABLED)) for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ap->device[i].class; @@ -1491,7 +1491,7 @@ static int ata_bus_probe(struct ata_port *ap) void ata_port_probe(struct ata_port *ap) { - ap->flags &= ~ATA_FLAG_PORT_DISABLED; + ap->flags &= ~ATA_FLAG_DISABLED; } /** @@ -1565,7 +1565,7 @@ void __sata_phy_reset(struct ata_port *ap) else ata_port_disable(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { @@ -1590,7 +1590,7 @@ void __sata_phy_reset(struct ata_port *ap) void sata_phy_reset(struct ata_port *ap) { __sata_phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; ata_bus_reset(ap); } @@ -1629,7 +1629,7 @@ void ata_port_disable(struct ata_port *ap) { ap->device[0].class = ATA_DEV_NONE; ap->device[1].class = ATA_DEV_NONE; - ap->flags |= ATA_FLAG_PORT_DISABLED; + ap->flags |= ATA_FLAG_DISABLED; } /** @@ -2251,7 +2251,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * Obtains host_set lock. * * SIDE EFFECTS: - * Sets ATA_FLAG_PORT_DISABLED if bus reset fails. + * Sets ATA_FLAG_DISABLED if bus reset fails. */ void ata_bus_reset(struct ata_port *ap) @@ -4468,7 +4468,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); @@ -4689,7 +4689,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, host->unique_id = ata_unique_id++; host->max_cmd_len = 12; - ap->flags = ATA_FLAG_PORT_DISABLED; + ap->flags = ATA_FLAG_DISABLED; ap->id = host->unique_id; ap->host = host; ap->ctl = ATA_DEVCTL_OBS; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index bcbf71e9895..096bdffbde1 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2728,7 +2728,7 @@ void ata_scsi_scan_host(struct ata_port *ap) struct ata_device *dev; unsigned int i; - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; for (i = 0; i < ATA_MAX_DEVICES; i++) { diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 3c85c4b66e1..d64073dd028 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -456,7 +456,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) continue; handled = 1; adma_enter_reg_mode(ap); - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR)) continue; pp = ap->private_data; if (!pp || pp->state != adma_state_pkt) @@ -481,7 +481,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set) for (port_no = 0; port_no < host_set->n_ports; ++port_no) { struct ata_port *ap; ap = host_set->ports[port_no]; - if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) { + if (ap && (!(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR)))) { struct ata_queued_cmd *qc; struct adma_port_priv *pp = ap->private_data; if (!pp || pp->state != adma_state_mmio) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 0f7d334aadc..e9152f85000 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1397,7 +1397,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, } } - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR)) continue; err_mask = ac_err_mask(ata_status); diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index f77bf183dfa..72721ac482d 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -280,7 +280,7 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index cc928c68a47..9557c7aa45e 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -534,7 +534,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ap = host_set->ports[i]; tmp = mask & (1 << (i + 1)); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 9ffe1ef0d20..8ef042a0944 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -396,7 +396,7 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) sff1, sff0, port_no, sHST, sDST); handled = 1; if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + (ATA_FLAG_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_pkt) @@ -429,7 +429,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) struct ata_port *ap; ap = host_set->ports[port_no]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_mmio) diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 068c98a4111..c34f6dabf41 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -770,7 +770,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * for (i = 0; i < host_set->n_ports; i++) if (status & (1 << i)) { struct ata_port *ap = host_set->ports[i]; - if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { sil24_host_intr(host_set->ports[i]); handled++; } else diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index ae70f60c7c0..3af28ef76fd 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -834,7 +834,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re tmp = mask & (1 << i); VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 836bbbb26ff..cecc1f76256 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -222,7 +222,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + (ATA_FLAG_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); diff --git a/include/linux/libata.h b/include/linux/libata.h index b7488a31e32..890262f44d0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -150,7 +150,7 @@ enum { ATA_FLAG_DEBUGMSG = (1 << 17), ATA_FLAG_FLUSH_PORT_TASK = (1 << 18), /* flush port task */ - ATA_FLAG_PORT_DISABLED = (1 << 19), /* port is disabled, ignore it */ + ATA_FLAG_DISABLED = (1 << 19), /* port is disabled, ignore it */ ATA_FLAG_SUSPENDED = (1 << 20), /* port is suspended */ /* bits 24:31 of ap->flags are reserved for LLDD specific flags */ From ea1dd4e13010eb9dd5ffb4bfabbb472bc238bebb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 13/22] [PATCH] libata: clear only affected flags during ata_dev_configure() ata_dev_configure() should not clear dynamic device flags determined elsewhere. Lower eight bits are reserved for feature flags, define ATA_DFLAG_CFG_MASK and clear only those bits before configuring device. Without this patch, ATA_DFLAG_PIO gets turned off during revalidation making PIO mode unuseable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- include/linux/libata.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 53226b16355..985283cbcbd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1241,7 +1241,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, id[84], id[85], id[86], id[87], id[88]); /* initialize to-be-configured parameters */ - dev->flags = 0; + dev->flags &= ~ATA_DFLAG_CFG_MASK; dev->max_sectors = 0; dev->cdb_len = 0; dev->n_sectors = 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index 890262f44d0..cbbc821fe22 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -122,6 +122,7 @@ enum { /* struct ata_device stuff */ ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ + ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ From e8384607d4f395985e3cc5f82d75fc73efc2ecf0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 14/22] [PATCH] libata: clear ATA_DFLAG_PIO before setting it ata_dev_set_mode() is now responsible for managing ATA_DFLAG_PIO. Clear it before setting it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 985283cbcbd..007d1888804 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1949,6 +1949,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) unsigned int err_mask; int rc; + dev->flags &= ~ATA_DFLAG_PIO; if (dev->xfer_shift == ATA_SHIFT_PIO) dev->flags |= ATA_DFLAG_PIO; From 2719736779da2c7fbb17d3de16c817b429bfeb9c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 15/22] [PATCH] libata: add ATA_QCFLAG_IO Add a new qc flag ATA_QCFLAG_IO. This flag gets set for normal IO commands originating from SCSI midlayer. This information will be used by EH to determine transfer speed reconfiguration. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 1 + include/linux/libata.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 096bdffbde1..234e1cadb07 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1188,6 +1188,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm u64 block; u32 n_block; + qc->flags |= ATA_QCFLAG_IO; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || diff --git a/include/linux/libata.h b/include/linux/libata.h index cbbc821fe22..a6d829cb056 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -161,7 +161,8 @@ enum { ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, - ATA_QCFLAG_EH_SCHEDULED = (1 << 3), /* EH scheduled */ + ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ + ATA_QCFLAG_EH_SCHEDULED = (1 << 4), /* EH scheduled */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ From c91af2c87e4048cdefcfc9f16fed8d728243c92d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 16/22] [PATCH] libata: pass qc around intead of ap during PIO The current code passes pointer to ap around and repeatedly performs ata_qc_from_tag() to access the ongoing qc. This is unnatural and makes EH synchronization cumbersome. Make PIO codes deal with qc instead of ap. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 71 ++++++++++++++------------------------ 1 file changed, 26 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 007d1888804..e9002a4174d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3416,7 +3416,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc) /** * ata_pio_poll - poll using PIO, depending on current state - * @ap: the target ata_port + * @qc: qc in progress * * LOCKING: * None. (executing in kernel thread context) @@ -3424,17 +3424,13 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc) * RETURNS: * timeout value to use */ - -static unsigned long ata_pio_poll(struct ata_port *ap) +static unsigned long ata_pio_poll(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; u8 status; unsigned int poll_state = HSM_ST_UNKNOWN; unsigned int reg_state = HSM_ST_UNKNOWN; - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - switch (ap->hsm_task_state) { case HSM_ST: case HSM_ST_POLL: @@ -3468,7 +3464,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap) /** * ata_pio_complete - check if drive is busy or idle - * @ap: the target ata_port + * @qc: qc to complete * * LOCKING: * None. (executing in kernel thread context) @@ -3476,10 +3472,9 @@ static unsigned long ata_pio_poll(struct ata_port *ap) * RETURNS: * Non-zero if qc completed, zero otherwise. */ - -static int ata_pio_complete (struct ata_port *ap) +static int ata_pio_complete(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; u8 drv_stat; /* @@ -3500,9 +3495,6 @@ static int ata_pio_complete (struct ata_port *ap) } } - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { qc->err_mask |= __ac_err_mask(drv_stat); @@ -3838,15 +3830,14 @@ err_out: /** * ata_pio_block - start PIO on a block - * @ap: the target ata_port + * @qc: qc to transfer block for * * LOCKING: * None. (executing in kernel thread context) */ - -static void ata_pio_block(struct ata_port *ap) +static void ata_pio_block(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; u8 status; /* @@ -3868,9 +3859,6 @@ static void ata_pio_block(struct ata_port *ap) } } - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - /* check error */ if (status & (ATA_ERR | ATA_DF)) { qc->err_mask |= AC_ERR_DEV; @@ -3899,12 +3887,9 @@ static void ata_pio_block(struct ata_port *ap) } } -static void ata_pio_error(struct ata_port *ap) +static void ata_pio_error(struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); + struct ata_port *ap = qc->ap; if (qc->tf.command != ATA_CMD_PACKET) printk(KERN_WARNING "ata%u: dev %u PIO error\n", @@ -3922,7 +3907,8 @@ static void ata_pio_error(struct ata_port *ap) static void ata_pio_task(void *_data) { - struct ata_port *ap = _data; + struct ata_queued_cmd *qc = _data; + struct ata_port *ap = qc->ap; unsigned long timeout; int qc_completed; @@ -3935,33 +3921,33 @@ fsm_start: return; case HSM_ST: - ata_pio_block(ap); + ata_pio_block(qc); break; case HSM_ST_LAST: - qc_completed = ata_pio_complete(ap); + qc_completed = ata_pio_complete(qc); break; case HSM_ST_POLL: case HSM_ST_LAST_POLL: - timeout = ata_pio_poll(ap); + timeout = ata_pio_poll(qc); break; case HSM_ST_TMOUT: case HSM_ST_ERR: - ata_pio_error(ap); + ata_pio_error(qc); return; } if (timeout) - ata_port_queue_task(ap, ata_pio_task, ap, timeout); + ata_port_queue_task(ap, ata_pio_task, qc, timeout); else if (!qc_completed) goto fsm_start; } /** * atapi_packet_task - Write CDB bytes to hardware - * @_data: Port to which ATAPI device is attached. + * @_data: qc in progress * * When device has indicated its readiness to accept * a CDB, this function is called. Send the CDB. @@ -3972,17 +3958,12 @@ fsm_start: * LOCKING: * Kernel thread context (may sleep) */ - static void atapi_packet_task(void *_data) { - struct ata_port *ap = _data; - struct ata_queued_cmd *qc; + struct ata_queued_cmd *qc = _data; + struct ata_port *ap = qc->ap; u8 status; - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); - /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) { @@ -4022,7 +4003,7 @@ static void atapi_packet_task(void *_data) /* PIO commands are handled by polling */ ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); } return; @@ -4328,26 +4309,26 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; case ATA_PROT_ATAPI: ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, atapi_packet_task, qc, 0); break; case ATA_PROT_ATAPI_NODATA: ap->flags |= ATA_FLAG_NOINTR; ata_tf_to_host(ap, &qc->tf); - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, atapi_packet_task, qc, 0); break; case ATA_PROT_ATAPI_DMA: ap->flags |= ATA_FLAG_NOINTR; ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ata_port_queue_task(ap, atapi_packet_task, qc, 0); break; default: From 058e55e120ca59d37392f9aa753da2d9ead24505 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 17/22] [PATCH] libata: always generate sense if qc->err_mask is non-zero Current sense generation code does not generate sense error if status register value doesn't indicate error condition. However, LLDD's may indicate errors which 't show up in status register. Completing such qc's without generating sense results in successful completion of failed commands. Invoke ata_to_sense_error() regardless of status register if qc->err_mask is not zero such that ata_to_sense_error() generates default sense error. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 234e1cadb07..ec628cea386 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -555,7 +555,8 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { + if (qc->err_mask || + tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, &sb[1], &sb[2], &sb[3]); sb[1] &= 0x0f; @@ -630,7 +631,8 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { + if (qc->err_mask || + tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, &sb[2], &sb[12], &sb[13]); sb[2] &= 0x0f; From 74e6c8c394ca2126a60e97bc1142ec2d91761e9a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 18/22] [PATCH] libata: don't read TF directly from sense generation functions TF register might not be directly accessible depending on errors. e.g. TF of failed NCQ command is in log page 10h. Make reading TF responsibility of error handlers. For the current EH, simply push TF reading into qc completion functions as they are practically part of EH. New EH will fill qc->tf with status registers before complting qcs. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ec628cea386..28706521773 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -545,12 +545,6 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* - * Read the controller registers. - */ - WARN_ON(qc->ap->ops->tf_read == NULL); - qc->ap->ops->tf_read(qc->ap, tf); - /* * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. @@ -621,12 +615,6 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* - * Read the controller registers. - */ - WARN_ON(qc->ap->ops->tf_read == NULL); - qc->ap->ops->tf_read(qc->ap, tf); - /* * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. @@ -1337,11 +1325,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) */ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && ((cdb[2] & 0x20) || need_sense)) { + qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); } else { if (!need_sense) { cmd->result = SAM_STAT_GOOD; } else { + qc->ap->ops->tf_read(qc->ap, &qc->tf); + /* TODO: decide which descriptor format to use * for 48b LBA devices and call that here * instead of the fixed desc, which is only @@ -2133,13 +2124,15 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 static void atapi_sense_complete(struct ata_queued_cmd *qc) { - if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) + if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) { /* FIXME: not quite right; we don't want the * translation of taskfile registers into * a sense descriptors, since that's only * correct for ATA, not ATAPI */ + qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); + } qc->scsidone(qc->scsicmd); ata_qc_free(qc); @@ -2207,17 +2200,15 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); return; - } - - else if (unlikely(err_mask)) + } else if (unlikely(err_mask)) { /* FIXME: not quite right; we don't want the * translation of taskfile registers into * a sense descriptors, since that's only * correct for ATA, not ATAPI */ + qc->ap->ops->tf_read(qc->ap, &qc->tf); ata_gen_ata_desc_sense(qc); - - else { + } else { u8 *scsicmd = cmd->cmnd; if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) { From d69cf37d5387801914bbf5297f070c7d2ee0206f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 19/22] [PATCH] libata: add @cdb to ata_exec_internal() Add @cdb to ata_exec_internal(). It will be used by new EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e9002a4174d..66b48b11fa0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -964,6 +964,7 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * @ap: Port to which the command is sent * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result + * @cdb: CDB for packet command * @dma_dir: Data tranfer direction of the command * @buf: Data buffer of the command * @buflen: Length of data buffer @@ -980,7 +981,7 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) static unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, - struct ata_taskfile *tf, + struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) { u8 command = tf->command; @@ -995,6 +996,8 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, BUG_ON(qc == NULL); qc->tf = *tf; + if (cdb) + memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); qc->dma_dir = dma_dir; if (dma_dir != DMA_NONE) { ata_sg_init_one(qc, buf, buflen); @@ -1144,7 +1147,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, tf.protocol = ATA_PROT_PIO; - err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, + err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { rc = -EIO; @@ -2988,7 +2991,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, tf.protocol = ATA_PROT_NODATA; tf.nsect = dev->xfer_mode; - err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -3028,7 +3031,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, tf.nsect = sectors; tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ - err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -4482,7 +4485,7 @@ static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, tf.flags |= ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; - err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) printk(KERN_ERR "%s: ata command failed: %d\n", __FUNCTION__, err); From 35e86b53b1a38e78ff0d70dae4aeb25f4572e433 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 20/22] [PATCH] libata: dec scmd->retries for qcs with zero err_mask qcs might get retried because of unrelated failure. e.g. NCQ command failure causes the whole command set to be aborted. Decrement scmd->retries for such retrials to avoid unnecessarily failing commands. Note that scmd->retries will be incremented the first time. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 28706521773..44008150d31 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -831,11 +831,14 @@ void ata_eh_qc_complete(struct ata_queued_cmd *qc) * should be retried. To be used from EH. * * SCSI midlayer limits the number of retries to scmd->allowed. - * This function might need to adjust scmd->retries for commands - * which get retried due to unrelated NCQ failures. + * scmd->retries is decremented for commands which get retried + * due to unrelated failures (qc->err_mask is zero). */ void ata_eh_qc_retry(struct ata_queued_cmd *qc) { + struct scsi_cmnd *scmd = qc->scsicmd; + if (!qc->err_mask && scmd->retries) + scmd->retries--; __ata_eh_qc_complete(qc); } From ece1d63619df010b8c4f08e43755e2a03f3b6eed Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 21/22] [PATCH] libata: separate out libata-eh.c A lot of EH codes are about to be added to libata. Separate out libata-eh.c. ata_scsi_timed_out(), ata_scsi_error(), ata_qc_timeout(), ata_eng_timeout(), ata_eh_qc_complete() and ata_eh_qc_retry() are moved. No code is changed by this patch. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/Makefile | 2 +- drivers/scsi/libata-core.c | 102 +------------- drivers/scsi/libata-eh.c | 264 +++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 130 ------------------ drivers/scsi/libata.h | 4 +- include/linux/libata.h | 12 +- 6 files changed, 281 insertions(+), 233 deletions(-) create mode 100644 drivers/scsi/libata-eh.c diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e513c3158ad..503f189dab3 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -165,7 +165,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) zalon7xx-objs := zalon.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o -libata-objs := libata-core.o libata-scsi.o libata-bmdma.o +libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o # Files generated that shall be removed upon make clean diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 66b48b11fa0..186a9ce4f07 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4015,99 +4015,6 @@ err_out: ata_poll_qc_complete(qc); } -/** - * ata_qc_timeout - Handle timeout of queued command - * @qc: Command that timed out - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -static void ata_qc_timeout(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - u8 host_stat = 0, drv_stat; - unsigned long flags; - - DPRINTK("ENTER\n"); - - ap->hsm_task_state = HSM_ST_IDLE; - - spin_lock_irqsave(&host_set->lock, flags); - - switch (qc->tf.protocol) { - - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - host_stat = ap->ops->bmdma_status(ap); - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - /* fall through */ - - default: - ata_altstatus(ap); - drv_stat = ata_chk_status(ap); - - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", - ap->id, qc->tf.command, drv_stat, host_stat); - - /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(drv_stat); - break; - } - - spin_unlock_irqrestore(&host_set->lock, flags); - - ata_eh_qc_complete(qc); - - DPRINTK("EXIT\n"); -} - -/** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -void ata_eng_timeout(struct ata_port *ap) -{ - DPRINTK("ENTER\n"); - - ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); - - DPRINTK("EXIT\n"); -} - /** * ata_qc_new - Request an available ATA command, for queueing * @ap: Port associated with device @dev @@ -5145,7 +5052,6 @@ EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(__ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); -EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load); EXPORT_SYMBOL_GPL(ata_tf_read); EXPORT_SYMBOL_GPL(ata_noop_dev_select); @@ -5185,15 +5091,12 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); -EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_scsi_simulate); -EXPORT_SYMBOL_GPL(ata_eh_qc_complete); -EXPORT_SYMBOL_GPL(ata_eh_qc_retry); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_compute); @@ -5215,3 +5118,8 @@ EXPORT_SYMBOL_GPL(ata_device_suspend); EXPORT_SYMBOL_GPL(ata_device_resume); EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); EXPORT_SYMBOL_GPL(ata_scsi_device_resume); + +EXPORT_SYMBOL_GPL(ata_scsi_error); +EXPORT_SYMBOL_GPL(ata_eng_timeout); +EXPORT_SYMBOL_GPL(ata_eh_qc_complete); +EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c new file mode 100644 index 00000000000..e73f5612aea --- /dev/null +++ b/drivers/scsi/libata-eh.c @@ -0,0 +1,264 @@ +/* + * libata-eh.c - libata error handling + * + * Maintained by: Jeff Garzik + * Please ALWAYS copy linux-ide@vger.kernel.org + * on emails. + * + * Copyright 2006 Tejun Heo + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * + * libata documentation is available via 'make {ps|pdf}docs', + * as Documentation/DocBook/libata.* + * + * Hardware documentation available from http://www.t13.org/ and + * http://www.sata-io.org/ + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "libata.h" + +/** + * ata_scsi_timed_out - SCSI layer time out callback + * @cmd: timed out SCSI command + * + * Handles SCSI layer timeout. We race with normal completion of + * the qc for @cmd. If the qc is already gone, we lose and let + * the scsi command finish (EH_HANDLED). Otherwise, the qc has + * timed out and EH should be invoked. Prevent ata_qc_complete() + * from finishing it by setting EH_SCHEDULED and return + * EH_NOT_HANDLED. + * + * LOCKING: + * Called from timer context + * + * RETURNS: + * EH_HANDLED or EH_NOT_HANDLED + */ +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + unsigned long flags; + struct ata_queued_cmd *qc; + enum scsi_eh_timer_return ret = EH_HANDLED; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + WARN_ON(qc->scsicmd != cmd); + qc->flags |= ATA_QCFLAG_EH_SCHEDULED; + qc->err_mask |= AC_ERR_TIMEOUT; + ret = EH_NOT_HANDLED; + } + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT, ret=%d\n", ret); + return ret; +} + +/** + * ata_scsi_error - SCSI layer error handler callback + * @host: SCSI host on which error occurred + * + * Handles SCSI-layer-thrown error events. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + * + * RETURNS: + * Zero. + */ +int ata_scsi_error(struct Scsi_Host *host) +{ + struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; + + DPRINTK("ENTER\n"); + + /* synchronize with IRQ handler and port task */ + spin_unlock_wait(&ap->host_set->lock); + ata_port_flush_task(ap); + + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + + ap->ops->eng_timeout(ap); + + WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); + + scsi_eh_flush_done_q(&ap->eh_done_q); + + DPRINTK("EXIT\n"); + return 0; +} + +/** + * ata_qc_timeout - Handle timeout of queued command + * @qc: Command that timed out + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +static void ata_qc_timeout(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_host_set *host_set = ap->host_set; + u8 host_stat = 0, drv_stat; + unsigned long flags; + + DPRINTK("ENTER\n"); + + ap->hsm_task_state = HSM_ST_IDLE; + + spin_lock_irqsave(&host_set->lock, flags); + + switch (qc->tf.protocol) { + + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: + host_stat = ap->ops->bmdma_status(ap); + + /* before we do anything else, clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + /* fall through */ + + default: + ata_altstatus(ap); + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ + ap->ops->irq_clear(ap); + + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", + ap->id, qc->tf.command, drv_stat, host_stat); + + /* complete taskfile transaction */ + qc->err_mask |= ac_err_mask(drv_stat); + break; + } + + spin_unlock_irqrestore(&host_set->lock, flags); + + ata_eh_qc_complete(qc); + + DPRINTK("EXIT\n"); +} + +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +void ata_eng_timeout(struct ata_port *ap) +{ + DPRINTK("ENTER\n"); + + ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); + + DPRINTK("EXIT\n"); +} + +static void ata_eh_scsidone(struct scsi_cmnd *scmd) +{ + /* nada */ +} + +static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *scmd = qc->scsicmd; + unsigned long flags; + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc->scsidone = ata_eh_scsidone; + __ata_qc_complete(qc); + WARN_ON(ata_tag_valid(qc->tag)); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); +} + +/** + * ata_eh_qc_complete - Complete an active ATA command from EH + * @qc: Command to complete + * + * Indicate to the mid and upper layers that an ATA command has + * completed. To be used from EH. + */ +void ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + scmd->retries = scmd->allowed; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH + * @qc: Command to retry + * + * Indicate to the mid and upper layers that an ATA command + * should be retried. To be used from EH. + * + * SCSI midlayer limits the number of retries to scmd->allowed. + * scmd->retries is decremented for commands which get retried + * due to unrelated failures (qc->err_mask is zero). + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + if (!qc->err_mask && scmd->retries) + scmd->retries--; + __ata_eh_qc_complete(qc); +} diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 44008150d31..745fc263fee 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -53,7 +53,6 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); #define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE_LEN 12 @@ -713,135 +712,6 @@ int ata_scsi_slave_config(struct scsi_device *sdev) return 0; /* scsi layer doesn't check return value, sigh */ } -/** - * ata_scsi_timed_out - SCSI layer time out callback - * @cmd: timed out SCSI command - * - * Handles SCSI layer timeout. We race with normal completion of - * the qc for @cmd. If the qc is already gone, we lose and let - * the scsi command finish (EH_HANDLED). Otherwise, the qc has - * timed out and EH should be invoked. Prevent ata_qc_complete() - * from finishing it by setting EH_SCHEDULED and return - * EH_NOT_HANDLED. - * - * LOCKING: - * Called from timer context - * - * RETURNS: - * EH_HANDLED or EH_NOT_HANDLED - */ -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *host = cmd->device->host; - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; - unsigned long flags; - struct ata_queued_cmd *qc; - enum scsi_eh_timer_return ret = EH_HANDLED; - - DPRINTK("ENTER\n"); - - spin_lock_irqsave(&ap->host_set->lock, flags); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc) { - WARN_ON(qc->scsicmd != cmd); - qc->flags |= ATA_QCFLAG_EH_SCHEDULED; - qc->err_mask |= AC_ERR_TIMEOUT; - ret = EH_NOT_HANDLED; - } - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("EXIT, ret=%d\n", ret); - return ret; -} - -/** - * ata_scsi_error - SCSI layer error handler callback - * @host: SCSI host on which error occurred - * - * Handles SCSI-layer-thrown error events. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - * - * RETURNS: - * Zero. - */ - -int ata_scsi_error(struct Scsi_Host *host) -{ - struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; - - DPRINTK("ENTER\n"); - - /* synchronize with IRQ handler and port task */ - spin_unlock_wait(&ap->host_set->lock); - ata_port_flush_task(ap); - - WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); - - ap->ops->eng_timeout(ap); - - WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); - - scsi_eh_flush_done_q(&ap->eh_done_q); - - DPRINTK("EXIT\n"); - return 0; -} - -static void ata_eh_scsidone(struct scsi_cmnd *scmd) -{ - /* nada */ -} - -static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct scsi_cmnd *scmd = qc->scsicmd; - unsigned long flags; - - spin_lock_irqsave(&ap->host_set->lock, flags); - qc->scsidone = ata_eh_scsidone; - __ata_qc_complete(qc); - WARN_ON(ata_tag_valid(qc->tag)); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - scsi_eh_finish_cmd(scmd, &ap->eh_done_q); -} - -/** - * ata_eh_qc_complete - Complete an active ATA command from EH - * @qc: Command to complete - * - * Indicate to the mid and upper layers that an ATA command has - * completed. To be used from EH. - */ -void ata_eh_qc_complete(struct ata_queued_cmd *qc) -{ - struct scsi_cmnd *scmd = qc->scsicmd; - scmd->retries = scmd->allowed; - __ata_eh_qc_complete(qc); -} - -/** - * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH - * @qc: Command to retry - * - * Indicate to the mid and upper layers that an ATA command - * should be retried. To be used from EH. - * - * SCSI midlayer limits the number of retries to scmd->allowed. - * scmd->retries is decremented for commands which get retried - * due to unrelated failures (qc->err_mask is zero). - */ -void ata_eh_qc_retry(struct ata_queued_cmd *qc) -{ - struct scsi_cmnd *scmd = qc->scsicmd; - if (!qc->err_mask && scmd->retries) - scmd->retries--; - __ata_eh_qc_complete(qc); -} - /** * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * @qc: Storage for translated ATA taskfile diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1c755b14521..75e9bd5833d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); -extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); @@ -90,4 +89,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); +/* libata-eh.c */ +extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); + #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index a6d829cb056..75bdee09c30 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -531,9 +531,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -extern int ata_scsi_error(struct Scsi_Host *host); -extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); -extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern int ata_scsi_device_resume(struct scsi_device *); @@ -582,7 +579,6 @@ extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void __ata_qc_complete(struct ata_queued_cmd *qc); -extern void ata_eng_timeout(struct ata_port *ap); extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); @@ -637,6 +633,14 @@ extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bit extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long); #endif /* CONFIG_PCI */ +/* + * EH + */ +extern int ata_scsi_error(struct Scsi_Host *host); +extern void ata_eng_timeout(struct ata_port *ap); +extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); +extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); + static inline int ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) From 1ad8e7f9eb051b040880e45337ed74bfd916ef7f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 2 Apr 2006 18:51:53 +0900 Subject: [PATCH 22/22] [PATCH] libata: make some libata-core routines extern Make libata-core routines which will be used by EH implementation extern. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 29 ++++++++++++----------------- drivers/scsi/libata.h | 13 +++++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 186a9ce4f07..8beba3cd9a5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,10 +65,6 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev, u16 heads, u16 sectors); -static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0); -static int ata_down_sata_spd_limit(struct ata_port *ap); -static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); @@ -412,7 +408,7 @@ static const char *sata_spd_string(unsigned int spd) return spd_str[spd - 1]; } -static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) +void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) { if (ata_dev_enabled(dev)) { printk(KERN_WARNING "ata%u: dev %u disabled\n", @@ -979,10 +975,9 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) * None. Should be called with kernel context, might sleep. */ -static unsigned -ata_exec_internal(struct ata_port *ap, struct ata_device *dev, - struct ata_taskfile *tf, const u8 *cdb, - int dma_dir, void *buf, unsigned int buflen) +unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, + struct ata_taskfile *tf, const u8 *cdb, + int dma_dir, void *buf, unsigned int buflen) { u8 command = tf->command; struct ata_queued_cmd *qc; @@ -1649,7 +1644,7 @@ void ata_port_disable(struct ata_port *ap) * RETURNS: * 0 on success, negative errno on failure */ -static int ata_down_sata_spd_limit(struct ata_port *ap) +int ata_down_sata_spd_limit(struct ata_port *ap) { u32 spd, mask; int highbit; @@ -1709,7 +1704,7 @@ static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) * RETURNS: * 1 if SATA spd configuration is needed, 0 otherwise. */ -static int ata_set_sata_spd_needed(struct ata_port *ap) +int ata_set_sata_spd_needed(struct ata_port *ap) { u32 scontrol; @@ -1913,8 +1908,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, * RETURNS: * 0 on success, negative errno on failure */ -static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, - int force_pio0) +int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0) { unsigned long xfer_mask; int highbit; @@ -1992,7 +1987,7 @@ static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) * RETURNS: * 0 on success, negative errno otherwise */ -static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) +int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) { struct ata_device *dev; int i, rc = 0, used_dma = 0, found = 0; @@ -2590,9 +2585,9 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_std_postreset, classes); } -static int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, ata_postreset_fn_t postreset, - int verbose, unsigned int *classes) +int ata_do_reset(struct ata_port *ap, + ata_reset_fn_t reset, ata_postreset_fn_t postreset, + int verbose, unsigned int *classes) { int i, rc; diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 75e9bd5833d..31efc2e60b6 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,7 +45,20 @@ extern int libata_fua; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern void ata_dev_disable(struct ata_port *ap, struct ata_device *dev); extern void ata_port_flush_task(struct ata_port *ap); +extern unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, + struct ata_taskfile *tf, const u8 *cdb, + int dma_dir, void *buf, unsigned int buflen); +extern int ata_down_sata_spd_limit(struct ata_port *ap); +extern int ata_set_sata_spd_needed(struct ata_port *ap); +extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, + int force_pio0); +extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); +extern int ata_do_reset(struct ata_port *ap, + ata_reset_fn_t reset, + ata_postreset_fn_t postreset, + int verbose, unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);