summaryrefslogtreecommitdiff
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-29 19:11:54 (GMT)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-29 19:11:54 (GMT)
commit00cda56d39f013cce60f44f1e3da19b87eba5d85 (patch)
tree2cfe7bf556562a846ff46a558a31ca1939d2e12c /drivers/ata/libata-core.c
parentda8e5aa21e037be02e0752e80b9444ff60185a3f (diff)
parentab6fc95f609b372a19e18ea689986846ab1ba29c (diff)
downloadlinux-fsl-qoriq-00cda56d39f013cce60f44f1e3da19b87eba5d85.tar.xz
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: [libata] AHCI: fix newly introduced host-reset bug [libata] sata_nv: fix SWNCQ enabling libata: add MAXTOR 7V300F0/VA111900 to NCQ blacklist libata: no need to speed down if already at PIO0 libata: relocate forcing PIO0 on reset pata_ns87415: define SUPERIO_IDE_MAX_RETRIES [libata] Address some checkpatch-spotted issues [libata] fix 'if(' and similar areas that lack whitespace libata: implement ata_wait_after_reset() libata: track SLEEP state and issue SRST to wake it up libata: relocate and fix post-command processing
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c146
1 files changed, 106 insertions, 40 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 7ef515b..e512903 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2219,6 +2219,25 @@ int ata_bus_probe(struct ata_port *ap)
tries[dev->devno] = ATA_PROBE_MAX_TRIES;
retry:
+ ata_link_for_each_dev(dev, &ap->link) {
+ /* If we issue an SRST then an ATA drive (not ATAPI)
+ * may change configuration and be in PIO0 timing. If
+ * we do a hard reset (or are coming from power on)
+ * this is true for ATA or ATAPI. Until we've set a
+ * suitable controller mode we should not touch the
+ * bus as we may be talking too fast.
+ */
+ dev->pio_mode = XFER_PIO_0;
+
+ /* If the controller has a pio mode setup function
+ * then use it to set the chipset to rights. Don't
+ * touch the DMA setup as that will be dealt with when
+ * configuring devices.
+ */
+ if (ap->ops->set_piomode)
+ ap->ops->set_piomode(ap, dev);
+ }
+
/* reset and determine device classes */
ap->ops->phy_reset(ap);
@@ -2234,12 +2253,6 @@ int ata_bus_probe(struct ata_port *ap)
ata_port_probe(ap);
- /* after the reset the device state is PIO 0 and the controller
- state is undefined. Record the mode */
-
- ata_link_for_each_dev(dev, &ap->link)
- dev->pio_mode = XFER_PIO_0;
-
/* read IDENTIFY page and configure devices. We have to do the identify
specific sequence bass-ackwards so that PDIAG- is released by
the slave device */
@@ -3118,6 +3131,55 @@ int ata_busy_sleep(struct ata_port *ap,
}
/**
+ * ata_wait_after_reset - wait before checking status after reset
+ * @ap: port containing status register to be polled
+ * @deadline: deadline jiffies for the operation
+ *
+ * After reset, we need to pause a while before reading status.
+ * Also, certain combination of controller and device report 0xff
+ * for some duration (e.g. until SATA PHY is up and running)
+ * which is interpreted as empty port in ATA world. This
+ * function also waits for such devices to get out of 0xff
+ * status.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
+{
+ unsigned long until = jiffies + ATA_TMOUT_FF_WAIT;
+
+ if (time_before(until, deadline))
+ deadline = until;
+
+ /* Spec mandates ">= 2ms" before checking status. We wait
+ * 150ms, because that was the magic delay used for ATAPI
+ * devices in Hale Landis's ATADRVR, for the period of time
+ * between when the ATA command register is written, and then
+ * status is checked. Because waiting for "a while" before
+ * checking status is fine, post SRST, we perform this magic
+ * delay here as well.
+ *
+ * Old drivers/ide uses the 2mS rule and then waits for ready.
+ */
+ msleep(150);
+
+ /* Wait for 0xff to clear. Some SATA devices take a long time
+ * to clear 0xff after reset. For example, HHD424020F7SV00
+ * iVDR needs >= 800ms while. Quantum GoVault needs even more
+ * than that.
+ */
+ while (1) {
+ u8 status = ata_chk_status(ap);
+
+ if (status != 0xff || time_after(jiffies, deadline))
+ return;
+
+ msleep(50);
+ }
+}
+
+/**
* ata_wait_ready - sleep until BSY clears, or timeout
* @ap: port containing status register to be polled
* @deadline: deadline jiffies for the operation
@@ -3223,8 +3285,6 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
unsigned long deadline)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- struct ata_device *dev;
- int i = 0;
DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
@@ -3235,36 +3295,8 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
udelay(20); /* FIXME: flush */
iowrite8(ap->ctl, ioaddr->ctl_addr);
- /* If we issued an SRST then an ATA drive (not ATAPI)
- * may have changed configuration and be in PIO0 timing. If
- * we did a hard reset (or are coming from power on) this is
- * true for ATA or ATAPI. Until we've set a suitable controller
- * mode we should not touch the bus as we may be talking too fast.
- */
-
- ata_link_for_each_dev(dev, &ap->link)
- dev->pio_mode = XFER_PIO_0;
-
- /* If the controller has a pio mode setup function then use
- it to set the chipset to rights. Don't touch the DMA setup
- as that will be dealt with when revalidating */
- if (ap->ops->set_piomode) {
- ata_link_for_each_dev(dev, &ap->link)
- if (devmask & (1 << i++))
- ap->ops->set_piomode(ap, dev);
- }
-
- /* spec mandates ">= 2ms" before checking status.
- * We wait 150ms, because that was the magic delay used for
- * ATAPI devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- *
- * Old drivers/ide uses the 2mS rule and then waits for ready
- */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* Before we perform post reset processing we want to see if
* the bus shows 0xFF because the odd clown forgets the D7
@@ -3691,8 +3723,8 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
return 0;
}
- /* wait a while before checking status, see SRST for more info */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* If PMP is supported, we have to do follow-up SRST. Note
* that some PMPs don't send D2H Reg FIS after hardreset at
@@ -3992,6 +4024,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, },
{ "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, },
{ "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, },
+ { "Maxtor 7V300F0", "VA111900", ATA_HORKAGE_NONCQ, },
/* devices which puke on READ_NATIVE_MAX */
{ "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, },
@@ -5595,6 +5628,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* taken care of.
*/
if (ap->ops->error_handler) {
+ struct ata_device *dev = qc->dev;
+ struct ata_eh_info *ehi = &dev->link->eh_info;
+
WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
if (unlikely(qc->err_mask))
@@ -5613,6 +5649,27 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
if (qc->flags & ATA_QCFLAG_RESULT_TF)
fill_result_tf(qc);
+ /* Some commands need post-processing after successful
+ * completion.
+ */
+ switch (qc->tf.command) {
+ case ATA_CMD_SET_FEATURES:
+ if (qc->tf.feature != SETFEATURES_WC_ON &&
+ qc->tf.feature != SETFEATURES_WC_OFF)
+ break;
+ /* fall through */
+ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+ case ATA_CMD_SET_MULTI: /* multi_count changed */
+ /* revalidate device */
+ ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ break;
+
+ case ATA_CMD_SLEEP:
+ dev->flags |= ATA_DFLAG_SLEEPING;
+ break;
+ }
+
__ata_qc_complete(qc);
} else {
if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
@@ -5750,6 +5807,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
qc->flags &= ~ATA_QCFLAG_DMAMAP;
}
+ /* if device is sleeping, schedule softreset and abort the link */
+ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
+ link->eh_info.action |= ATA_EH_SOFTRESET;
+ ata_ehi_push_desc(&link->eh_info, "waking up from sleep");
+ ata_link_abort(link);
+ return;
+ }
+
ap->ops->qc_prep(qc);
qc->err_mask |= ap->ops->qc_issue(qc);
@@ -7327,6 +7392,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_wait_after_reset);
EXPORT_SYMBOL_GPL(ata_wait_ready);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);