summaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/Kconfig13
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci.c28
-rw-r--r--drivers/ata/ata_piix.c6
-rw-r--r--drivers/ata/libata-acpi.c3
-rw-r--r--drivers/ata/libata-core.c235
-rw-r--r--drivers/ata/libata-eh.c62
-rw-r--r--drivers/ata/pata_amd.c11
-rw-r--r--drivers/ata/pata_artop.c11
-rw-r--r--drivers/ata/pata_atiixp.c4
-rw-r--r--drivers/ata/pata_cs5535.c1
-rw-r--r--drivers/ata/pata_efar.c5
-rw-r--r--drivers/ata/pata_hpt366.c4
-rw-r--r--drivers/ata/pata_hpt37x.c9
-rw-r--r--drivers/ata/pata_hpt3x2n.c5
-rw-r--r--drivers/ata/pata_icside.c686
-rw-r--r--drivers/ata/pata_it8213.c6
-rw-r--r--drivers/ata/pata_jmicron.c7
-rw-r--r--drivers/ata/pata_marvell.c7
-rw-r--r--drivers/ata/pata_mpiix.c5
-rw-r--r--drivers/ata/pata_ns87410.c6
-rw-r--r--drivers/ata/pata_oldpiix.c6
-rw-r--r--drivers/ata/pata_opti.c6
-rw-r--r--drivers/ata/pata_optidma.c5
-rw-r--r--drivers/ata/pata_pcmcia.c1
-rw-r--r--drivers/ata/pata_pdc2027x.c5
-rw-r--r--drivers/ata/pata_qdi.c2
-rw-r--r--drivers/ata/pata_scc.c4
-rw-r--r--drivers/ata/pata_serverworks.c4
-rw-r--r--drivers/ata/pata_sil680.c6
-rw-r--r--drivers/ata/pata_sis.c8
-rw-r--r--drivers/ata/pata_sl82c105.c5
-rw-r--r--drivers/ata/pata_triflex.c6
-rw-r--r--drivers/ata/pata_via.c5
-rw-r--r--drivers/ata/sata_inic162x.c15
-rw-r--r--drivers/ata/sata_nv.c97
-rw-r--r--drivers/ata/sata_promise.c24
-rw-r--r--drivers/ata/sata_sil24.c10
-rw-r--r--drivers/ata/sata_svw.c2
-rw-r--r--drivers/ata/sata_via.c13
40 files changed, 1122 insertions, 217 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 365c306..f031b87 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -3,6 +3,7 @@
#
menu "Serial ATA (prod) and Parallel ATA (experimental) drivers"
+ depends on HAS_IOMEM
config ATA
tristate "ATA device support"
@@ -435,7 +436,7 @@ config PATA_OPTIDMA
help
This option enables DMA/PIO support for the later OPTi
controllers found on some old motherboards and in some
- latops
+ laptops.
If unsure, say N.
@@ -550,13 +551,21 @@ config PATA_WINBOND_VLB
config PATA_PLATFORM
tristate "Generic platform device PATA support"
- depends on EMBEDDED
+ depends on EMBEDDED || ARCH_RPC
help
This option enables support for generic directly connected ATA
devices commonly found on embedded systems.
If unsure, say N.
+config PATA_ICSIDE
+ tristate "Acorn ICS PATA support"
+ depends on ARM && ARCH_ACORN
+ help
+ On Acorn systems, say Y here if you wish to use the ICS PATA
+ interface card. This is not required for ICS partition support.
+ If you are unsure, say N to this.
+
config PATA_IXP4XX_CF
tristate "IXP4XX Compact Flash support"
depends on ARCH_IXP4XX
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index b7055e3..6f42a0e 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
+obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
# Should be last but one libata driver
obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
# Should be last libata driver
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 34c5534..d961789 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -874,7 +874,8 @@ static int ahci_clo(struct ata_port *ap)
return 0;
}
-static int ahci_softreset(struct ata_port *ap, unsigned int *class)
+static int ahci_softreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
struct ahci_port_priv *pp = ap->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
@@ -959,15 +960,13 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
*/
msleep(150);
- *class = ATA_DEV_NONE;
- if (ata_port_online(ap)) {
- if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
- rc = -EIO;
- reason = "device not ready";
- goto fail;
- }
- *class = ahci_dev_classify(ap);
+ rc = ata_wait_ready(ap, deadline);
+ /* link occupied, -ENODEV too is an error */
+ if (rc) {
+ reason = "device not ready";
+ goto fail;
}
+ *class = ahci_dev_classify(ap);
DPRINTK("EXIT, class=%u\n", *class);
return 0;
@@ -979,7 +978,8 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
return rc;
}
-static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
+static int ahci_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
struct ahci_port_priv *pp = ap->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
@@ -995,7 +995,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
tf.command = 0x80;
ata_tf_to_fis(&tf, d2h_fis, 0);
- rc = sata_std_hardreset(ap, class);
+ rc = sata_std_hardreset(ap, class, deadline);
ahci_start_engine(ap);
@@ -1008,7 +1008,8 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
return rc;
}
-static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
+static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
int rc;
@@ -1016,7 +1017,8 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
ahci_stop_engine(ap);
- rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
+ rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context),
+ deadline);
/* vt8251 needs SError cleared for the port to operate */
ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 55d306a..4a795fd 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -625,17 +625,18 @@ static int ich_pata_cable_detect(struct ata_port *ap)
/**
* piix_pata_prereset - prereset for PATA host controller
* @ap: Target port
+ * @deadline: deadline jiffies for the operation
*
* LOCKING:
* None (inherited from caller).
*/
-static int piix_pata_prereset(struct ata_port *ap)
+static int piix_pata_prereset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
static void piix_pata_error_handler(struct ata_port *ap)
@@ -644,7 +645,6 @@ static void piix_pata_error_handler(struct ata_port *ap)
ata_std_postreset);
}
-
static void piix_sata_error_handler(struct ata_port *ap)
{
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 03a0acf..cb3eab6e 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -489,8 +489,7 @@ static void taskfile_load_raw(struct ata_port *ap,
/* convert gtf to tf */
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
- tf.protocol = atadev->class == ATA_DEV_ATAPI ?
- ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA;
+ tf.protocol = ATA_PROT_NODATA;
tf.feature = gtf->tfa[0]; /* 0x1f1 */
tf.nsect = gtf->tfa[1]; /* 0x1f2 */
tf.lbal = gtf->tfa[2]; /* 0x1f3 */
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index ca67484..4595d1f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -895,6 +895,7 @@ static u64 ata_read_native_max_address(struct ata_device *dev)
/**
* ata_set_native_max_address_ext - LBA48 native max set
* @dev: Device to query
+ * @new_sectors: new max sectors value to set for the device
*
* Perform an LBA48 size set max upon the device in question. Return the
* actual LBA48 size or zero if the command fails.
@@ -932,6 +933,7 @@ static u64 ata_set_native_max_address_ext(struct ata_device *dev, u64 new_sector
/**
* ata_set_native_max_address - LBA28 native max set
* @dev: Device to query
+ * @new_sectors: new max sectors value to set for the device
*
* Perform an LBA28 size set max upon the device in question. Return the
* actual LBA28 size or zero if the command fails.
@@ -1316,7 +1318,7 @@ void ata_port_flush_task(struct ata_port *ap)
spin_unlock_irqrestore(ap->lock, flags);
DPRINTK("flush #1\n");
- flush_workqueue(ata_wq);
+ cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */
/*
* At this point, if a task is running, it's guaranteed to see
@@ -1327,7 +1329,7 @@ void ata_port_flush_task(struct ata_port *ap)
if (ata_msg_ctl(ap))
ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
__FUNCTION__);
- flush_workqueue(ata_wq);
+ cancel_work_sync(&ap->port_task.work);
}
spin_lock_irqsave(ap->lock, flags);
@@ -2979,23 +2981,71 @@ int ata_busy_sleep(struct ata_port *ap,
return 0;
}
-static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+/**
+ * ata_wait_ready - sleep until BSY clears, or timeout
+ * @ap: port containing status register to be polled
+ * @deadline: deadline jiffies for the operation
+ *
+ * Sleep until ATA Status register bit BSY clears, or timeout
+ * occurs.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
+{
+ unsigned long start = jiffies;
+ int warned = 0;
+
+ while (1) {
+ u8 status = ata_chk_status(ap);
+ unsigned long now = jiffies;
+
+ if (!(status & ATA_BUSY))
+ return 0;
+ if (status == 0xff)
+ return -ENODEV;
+ if (time_after(now, deadline))
+ return -EBUSY;
+
+ if (!warned && time_after(now, start + 5 * HZ) &&
+ (deadline - now > 3 * HZ)) {
+ ata_port_printk(ap, KERN_WARNING,
+ "port is slow to respond, please be patient "
+ "(Status 0x%x)\n", status);
+ warned = 1;
+ }
+
+ msleep(50);
+ }
+}
+
+static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+ unsigned long deadline)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int dev0 = devmask & (1 << 0);
unsigned int dev1 = devmask & (1 << 1);
- unsigned long timeout;
+ int rc, ret = 0;
/* if device 0 was found in ata_devchk, wait for its
* BSY bit to clear
*/
- if (dev0)
- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ if (dev0) {
+ rc = ata_wait_ready(ap, deadline);
+ if (rc) {
+ if (rc != -ENODEV)
+ return rc;
+ ret = rc;
+ }
+ }
/* if device 1 was found in ata_devchk, wait for
* register access, then wait for BSY to clear
*/
- timeout = jiffies + ATA_TMOUT_BOOT;
while (dev1) {
u8 nsect, lbal;
@@ -3004,14 +3054,18 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
lbal = ioread8(ioaddr->lbal_addr);
if ((nsect == 1) && (lbal == 1))
break;
- if (time_after(jiffies, timeout)) {
- dev1 = 0;
- break;
- }
+ if (time_after(jiffies, deadline))
+ return -EBUSY;
msleep(50); /* give drive a breather */
}
- if (dev1)
- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ if (dev1) {
+ rc = ata_wait_ready(ap, deadline);
+ if (rc) {
+ if (rc != -ENODEV)
+ return rc;
+ ret = rc;
+ }
+ }
/* is all this really necessary? */
ap->ops->dev_select(ap, 0);
@@ -3019,10 +3073,12 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
ap->ops->dev_select(ap, 1);
if (dev0)
ap->ops->dev_select(ap, 0);
+
+ return ret;
}
-static unsigned int ata_bus_softreset(struct ata_port *ap,
- unsigned int devmask)
+static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
+ unsigned long deadline)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
@@ -3052,11 +3108,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
* pulldown resistor.
*/
if (ata_check_status(ap) == 0xFF)
- return 0;
-
- ata_bus_post_reset(ap, devmask);
+ return -ENODEV;
- return 0;
+ return ata_bus_post_reset(ap, devmask, deadline);
}
/**
@@ -3085,6 +3139,7 @@ void ata_bus_reset(struct ata_port *ap)
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
u8 err;
unsigned int dev0, dev1 = 0, devmask = 0;
+ int rc;
DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
@@ -3106,9 +3161,11 @@ void ata_bus_reset(struct ata_port *ap)
ap->ops->dev_select(ap, 0);
/* issue bus reset */
- if (ap->flags & ATA_FLAG_SRST)
- if (ata_bus_softreset(ap, devmask))
+ if (ap->flags & ATA_FLAG_SRST) {
+ rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
+ if (rc && rc != -ENODEV)
goto err_out;
+ }
/*
* determine by signature whether we have ATA or ATAPI devices
@@ -3150,29 +3207,37 @@ err_out:
* sata_phy_debounce - debounce SATA phy status
* @ap: ATA port to debounce SATA phy status for
* @params: timing parameters { interval, duratinon, timeout } in msec
+ * @deadline: deadline jiffies for the operation
*
* Make sure SStatus of @ap reaches stable state, determined by
* holding the same value where DET is not 1 for @duration polled
* every @interval, before @timeout. Timeout constraints the
- * beginning of the stable state. Because, after hot unplugging,
- * DET gets stuck at 1 on some controllers, this functions waits
+ * beginning of the stable state. Because DET gets stuck at 1 on
+ * some controllers after hot unplugging, this functions waits
* until timeout then returns 0 if DET is stable at 1.
*
+ * @timeout is further limited by @deadline. The sooner of the
+ * two is used.
+ *
* LOCKING:
* Kernel thread context (may sleep)
*
* RETURNS:
* 0 on success, -errno on failure.
*/
-int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
+int sata_phy_debounce(struct ata_port *ap, const unsigned long *params,
+ unsigned long deadline)
{
unsigned long interval_msec = params[0];
- unsigned long duration = params[1] * HZ / 1000;
- unsigned long timeout = jiffies + params[2] * HZ / 1000;
- unsigned long last_jiffies;
+ unsigned long duration = msecs_to_jiffies(params[1]);
+ unsigned long last_jiffies, t;
u32 last, cur;
int rc;
+ t = jiffies + msecs_to_jiffies(params[2]);
+ if (time_before(t, deadline))
+ deadline = t;
+
if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
return rc;
cur &= 0xf;
@@ -3188,7 +3253,7 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
/* DET stable? */
if (cur == last) {
- if (cur == 1 && time_before(jiffies, timeout))
+ if (cur == 1 && time_before(jiffies, deadline))
continue;
if (time_after(jiffies, last_jiffies + duration))
return 0;
@@ -3199,8 +3264,8 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
last = cur;
last_jiffies = jiffies;
- /* check timeout */
- if (time_after(jiffies, timeout))
+ /* check deadline */
+ if (time_after(jiffies, deadline))
return -EBUSY;
}
}
@@ -3209,6 +3274,7 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
* sata_phy_resume - resume SATA phy
* @ap: ATA port to resume SATA phy for
* @params: timing parameters { interval, duratinon, timeout } in msec
+ * @deadline: deadline jiffies for the operation
*
* Resume SATA phy of @ap and debounce it.
*
@@ -3218,7 +3284,8 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
* RETURNS:
* 0 on success, -errno on failure.
*/
-int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
+int sata_phy_resume(struct ata_port *ap, const unsigned long *params,
+ unsigned long deadline)
{
u32 scontrol;
int rc;
@@ -3236,43 +3303,19 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
*/
msleep(200);
- return sata_phy_debounce(ap, params);
-}
-
-static void ata_wait_spinup(struct ata_port *ap)
-{
- struct ata_eh_context *ehc = &ap->eh_context;
- unsigned long end, secs;
- int rc;
-
- /* first, debounce phy if SATA */
- if (ap->cbl == ATA_CBL_SATA) {
- rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);
-
- /* if debounced successfully and offline, no need to wait */
- if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
- return;
- }
-
- /* okay, let's give the drive time to spin up */
- end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
- secs = ((end - jiffies) + HZ - 1) / HZ;
-
- if (time_after(jiffies, end))
- return;
-
- if (secs > 5)
- ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
- "(%lu secs)\n", secs);
-
- schedule_timeout_uninterruptible(end - jiffies);
+ return sata_phy_debounce(ap, params, deadline);
}
/**
* ata_std_prereset - prepare for reset
* @ap: ATA port to be reset
+ * @deadline: deadline jiffies for the operation
*
- * @ap is about to be reset. Initialize it.
+ * @ap is about to be reset. Initialize it. Failure from
+ * prereset makes libata abort whole reset sequence and give up
+ * that port, so prereset should be best-effort. It does its
+ * best to prepare for reset sequence but if things go wrong, it
+ * should just whine, not fail.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -3280,41 +3323,41 @@ static void ata_wait_spinup(struct ata_port *ap)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_std_prereset(struct ata_port *ap)
+int ata_std_prereset(struct ata_port *ap, unsigned long deadline)
{
struct ata_eh_context *ehc = &ap->eh_context;
const unsigned long *timing = sata_ehc_deb_timing(ehc);
int rc;
- /* handle link resume & hotplug spinup */
+ /* handle link resume */
if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
(ap->flags & ATA_FLAG_HRST_TO_RESUME))
ehc->i.action |= ATA_EH_HARDRESET;
- if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
- (ap->flags & ATA_FLAG_SKIP_D2H_BSY))
- ata_wait_spinup(ap);
-
/* if we're about to do hardreset, nothing more to do */
if (ehc->i.action & ATA_EH_HARDRESET)
return 0;
/* if SATA, resume phy */
if (ap->cbl == ATA_CBL_SATA) {
- rc = sata_phy_resume(ap, timing);
- if (rc && rc != -EOPNOTSUPP) {
- /* phy resume failed */
+ rc = sata_phy_resume(ap, timing, deadline);
+ /* whine about phy resume failure but proceed */
+ if (rc && rc != -EOPNOTSUPP)
ata_port_printk(ap, KERN_WARNING, "failed to resume "
"link for reset (errno=%d)\n", rc);
- return rc;
- }
}
/* Wait for !BSY if the controller can wait for the first D2H
* Reg FIS and we don't know that no device is attached.
*/
- if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap))
- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) {
+ rc = ata_wait_ready(ap, deadline);
+ if (rc) {
+ ata_port_printk(ap, KERN_WARNING, "device not ready "
+ "(errno=%d), forcing hardreset\n", rc);
+ ehc->i.action |= ATA_EH_HARDRESET;
+ }
+ }
return 0;
}
@@ -3323,6 +3366,7 @@ int ata_std_prereset(struct ata_port *ap)
* ata_std_softreset - reset host port via ATA SRST
* @ap: port to reset
* @classes: resulting classes of attached devices
+ * @deadline: deadline jiffies for the operation
*
* Reset host port using ATA SRST.
*
@@ -3332,10 +3376,12 @@ int ata_std_prereset(struct ata_port *ap)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
+int ata_std_softreset(struct ata_port *ap, unsigned int *classes,
+ unsigned long deadline)
{
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
- unsigned int devmask = 0, err_mask;
+ unsigned int devmask = 0;
+ int rc;
u8 err;
DPRINTK("ENTER\n");
@@ -3356,11 +3402,11 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
/* issue bus reset */
DPRINTK("about to softreset, devmask=%x\n", devmask);
- err_mask = ata_bus_softreset(ap, devmask);
- if (err_mask) {
- ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
- err_mask);
- return -EIO;
+ rc = ata_bus_softreset(ap, devmask, deadline);
+ /* if link is occupied, -ENODEV too is an error */
+ if (rc && (rc != -ENODEV || sata_scr_valid(ap))) {
+ ata_port_printk(ap, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+ return rc;
}
/* determine by signature whether we have ATA or ATAPI devices */
@@ -3377,6 +3423,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
* sata_port_hardreset - reset port via SATA phy reset
* @ap: port to reset
* @timing: timing parameters { interval, duratinon, timeout } in msec
+ * @deadline: deadline jiffies for the operation
*
* SATA phy-reset host port using DET bits of SControl register.
*
@@ -3386,7 +3433,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
+int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing,
+ unsigned long deadline)
{
u32 scontrol;
int rc;
@@ -3425,7 +3473,7 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
msleep(1);
/* bring phy back */
- rc = sata_phy_resume(ap, timing);
+ rc = sata_phy_resume(ap, timing, deadline);
out:
DPRINTK("EXIT, rc=%d\n", rc);
return rc;
@@ -3435,6 +3483,7 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
* sata_std_hardreset - reset host port via SATA phy reset
* @ap: port to reset
* @class: resulting class of attached device
+ * @deadline: deadline jiffies for the operation
*
* SATA phy-reset host port using DET bits of SControl register,
* wait for !BSY and classify the attached device.
@@ -3445,7 +3494,8 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
+int sata_std_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
int rc;
@@ -3453,7 +3503,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
DPRINTK("ENTER\n");
/* do hardreset */
- rc = sata_port_hardreset(ap, timing);
+ rc = sata_port_hardreset(ap, timing, deadline);
if (rc) {
ata_port_printk(ap, KERN_ERR,
"COMRESET failed (errno=%d)\n", rc);
@@ -3470,10 +3520,12 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
/* wait a while before checking status, see SRST for more info */
msleep(150);
- if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+ rc = ata_wait_ready(ap, deadline);
+ /* link occupied, -ENODEV too is an error */
+ if (rc) {
ata_port_printk(ap, KERN_ERR,
- "COMRESET failed (device not ready)\n");
- return -EIO;
+ "COMRESET failed (errno=%d)\n", rc);
+ return rc;
}
ap->ops->dev_select(ap, 0); /* probably unnecessary */
@@ -6425,9 +6477,9 @@ void ata_port_detach(struct ata_port *ap)
/* Flush hotplug task. The sequence is similar to
* ata_port_flush_task().
*/
- flush_workqueue(ata_aux_wq);
+ cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
cancel_delayed_work(&ap->hotplug_task);
- flush_workqueue(ata_aux_wq);
+ cancel_work_sync(&ap->hotplug_task.work);
skip_eh:
/* remove the associated SCSI host */
@@ -6793,6 +6845,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_ready);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 2bff9ad..8256655 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -50,6 +50,28 @@ enum {
ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2),
};
+/* Waiting in ->prereset can never be reliable. It's sometimes nice
+ * to wait there but it can't be depended upon; otherwise, we wouldn't
+ * be resetting. Just give it enough time for most drives to spin up.
+ */
+enum {
+ ATA_EH_PRERESET_TIMEOUT = 10 * HZ,
+};
+
+/* The following table determines how we sequence resets. Each entry
+ * represents timeout for that try. The first try can be soft or
+ * hardreset. All others are hardreset if available. In most cases
+ * the first reset w/ 10sec timeout should succeed. Following entries
+ * are mostly for error handling, hotplug and retarded devices.
+ */
+static const unsigned long ata_eh_reset_timeouts[] = {
+ 10 * HZ, /* most drives spin up by 10sec */
+ 10 * HZ, /* > 99% working drives spin up before 20sec */
+ 35 * HZ, /* give > 30 secs of idleness for retarded devices */
+ 5 * HZ, /* and sweet one last chance */
+ /* > 1 min has elapsed, give up */
+};
+
static void __ata_port_freeze(struct ata_port *ap);
static void ata_eh_finish(struct ata_port *ap);
#ifdef CONFIG_PM
@@ -1558,14 +1580,14 @@ static void ata_eh_report(struct ata_port *ap)
}
static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
- unsigned int *classes)
+ unsigned int *classes, unsigned long deadline)
{
int i, rc;
for (i = 0; i < ATA_MAX_DEVICES; i++)
classes[i] = ATA_DEV_UNKNOWN;
- rc = reset(ap, classes);
+ rc = reset(ap, classes, deadline);
if (rc)
return rc;
@@ -1603,8 +1625,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
{
struct ata_eh_context *ehc = &ap->eh_context;
unsigned int *classes = ehc->classes;
- int tries = ATA_EH_RESET_TRIES;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
+ int try = 0;
+ unsigned long deadline;
unsigned int action;
ata_reset_fn_t reset;
int i, did_followup_srst, rc;
@@ -1624,7 +1647,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
ehc->i.action |= ATA_EH_HARDRESET;
if (prereset) {
- rc = prereset(ap);
+ rc = prereset(ap, jiffies + ATA_EH_PRERESET_TIMEOUT);
if (rc) {
if (rc == -ENOENT) {
ata_port_printk(ap, KERN_DEBUG,
@@ -1665,6 +1688,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}
retry:
+ deadline = jiffies + ata_eh_reset_timeouts[try++];
+
/* shut up during boot probing */
if (verbose)
ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
@@ -1676,7 +1701,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
else
ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
- rc = ata_do_reset(ap, reset, classes);
+ rc = ata_do_reset(ap, reset, classes, deadline);
did_followup_srst = 0;
if (reset == hardreset &&
@@ -1693,7 +1718,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}
ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
- rc = ata_do_reset(ap, reset, classes);
+ rc = ata_do_reset(ap, reset, classes, deadline);
if (rc == 0 && classify &&
classes[0] == ATA_DEV_UNKNOWN) {
@@ -1703,22 +1728,21 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}
}
- if (rc && --tries) {
- const char *type;
+ if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
+ unsigned long now = jiffies;
- if (reset == softreset) {
- if (did_followup_srst)
- type = "follow-up soft";
- else
- type = "soft";
- } else
- type = "hard";
+ if (time_before(now, deadline)) {
+ unsigned long delta = deadline - jiffies;
- ata_port_printk(ap, KERN_WARNING,
- "%sreset failed, retrying in 5 secs\n", type);
- ssleep(5);
+ ata_port_printk(ap, KERN_WARNING, "reset failed "
+ "(errno=%d), retrying in %u secs\n",
+ rc, (jiffies_to_msecs(delta) + 999) / 1000);
+
+ schedule_timeout_uninterruptible(delta);
+ }
- if (reset == hardreset)
+ if (reset == hardreset &&
+ try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1)
sata_down_spd_limit(ap);
if (hardreset)
reset = hardreset;
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 536ee89..67c7e87 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -121,12 +121,13 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
/**
* amd_probe_init - perform reset handling
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Reset sequence checking enable bits to see which ports are
* active.
*/
-static int amd_pre_reset(struct ata_port *ap)
+static int amd_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits amd_enable_bits[] = {
{ 0x40, 1, 0x02, 0x02 },
@@ -138,8 +139,7 @@ static int amd_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
-
+ return ata_std_prereset(ap, deadline);
}
static void amd_error_handler(struct ata_port *ap)
@@ -227,7 +227,8 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
* space for us.
*/
-static int nv_pre_reset(struct ata_port *ap) {
+static int nv_pre_reset(struct ata_port *ap, unsigned long deadline)
+{
static const struct pci_bits nv_enable_bits[] = {
{ 0x50, 1, 0x02, 0x02 },
{ 0x50, 1, 0x01, 0x01 }
@@ -238,7 +239,7 @@ static int nv_pre_reset(struct ata_port *ap) {
if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
static void nv_error_handler(struct ata_port *ap)
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 00e9ec3..ef51940 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -39,7 +39,7 @@
static int clock = 0;
-static int artop6210_pre_reset(struct ata_port *ap)
+static int artop6210_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
const struct pci_bits artop_enable_bits[] = {
@@ -49,7 +49,8 @@ static int artop6210_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
@@ -70,12 +71,13 @@ static void artop6210_error_handler(struct ata_port *ap)
/**
* artop6260_pre_reset - check for 40/80 pin
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* The ARTOP hardware reports the cable detect bits in register 0x49.
* Nothing complicated needed here.
*/
-static int artop6260_pre_reset(struct ata_port *ap)
+static int artop6260_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits artop_enable_bits[] = {
{ 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
@@ -87,7 +89,8 @@ static int artop6260_pre_reset(struct ata_port *ap)
/* Odd numbered device ids are the units with enable bits (the -R cards) */
if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 39c871a..2151538 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -33,7 +33,7 @@ enum {
ATIIXP_IDE_UDMA_MODE = 0x56
};
-static int atiixp_pre_reset(struct ata_port *ap)
+static int atiixp_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits atiixp_enable_bits[] = {
{ 0x48, 1, 0x01, 0x00 },
@@ -44,7 +44,7 @@ static int atiixp_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
static void atiixp_error_handler(struct ata_port *ap)
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 08cccc9..22006ae 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -72,6 +72,7 @@
/**
* cs5535_cable_detect - detect cable type
* @ap: Port to detect on
+ * @deadline: deadline jiffies for the operation
*
* Perform cable detection for ATA66 capable cable. Return a libata
* cable type.
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index a321685..d0f52e0 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -27,12 +27,13 @@
/**
* efar_pre_reset - Enable bits
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* Perform cable detection for the EFAR ATA interface. This is
* different to the PIIX arrangement
*/
-static int efar_pre_reset(struct ata_port *ap)
+static int efar_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits efar_enable_bits[] = {
{ 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
@@ -43,7 +44,7 @@ static int efar_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 93cfa6d..e64e05e 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -220,7 +220,7 @@ static int hpt36x_cable_detect(struct ata_port *ap)
return ATA_CBL_PATA80;
}
-static int hpt36x_pre_reset(struct ata_port *ap)
+static int hpt36x_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits hpt36x_enable_bits[] = {
{ 0x50, 1, 0x04, 0x04 },
@@ -231,7 +231,7 @@ static int hpt36x_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 41d83129..1614e8c 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -307,11 +307,12 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
/**
* hpt37x_pre_reset - reset the hpt37x bus
* @ap: ATA port to reset
+ * @deadline: deadline jiffies for the operation
*
* Perform the initial reset handling for the 370/372 and 374 func 0
*/
-static int hpt37x_pre_reset(struct ata_port *ap)
+static int hpt37x_pre_reset(struct ata_port *ap, unsigned long deadline)
{
u8 scr2, ata66;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -338,7 +339,7 @@ static int hpt37x_pre_reset(struct ata_port *ap)
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
udelay(100);
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
@@ -353,7 +354,7 @@ static void hpt37x_error_handler(struct ata_port *ap)
ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
}
-static int hpt374_pre_reset(struct ata_port *ap)
+static int hpt374_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits hpt37x_enable_bits[] = {
{ 0x50, 1, 0x04, 0x04 },
@@ -388,7 +389,7 @@ static int hpt374_pre_reset(struct ata_port *ap)
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
udelay(100);
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 6a34521..ea1037d 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -148,13 +148,14 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
* Reset the hardware and state machine,
*/
-static int hpt3xn_pre_reset(struct ata_port *ap)
+static int hpt3xn_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
/* Reset the state machine */
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
udelay(100);
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
new file mode 100644
index 0000000..dbc8ee2
--- /dev/null
+++ b/drivers/ata/pata_icside.c
@@ -0,0 +1,686 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
+#include <linux/ata.h>
+#include <linux/libata.h>
+
+#include <asm/dma.h>
+#include <asm/ecard.h>
+
+#define DRV_NAME "pata_icside"
+
+#define ICS_IDENT_OFFSET 0x2280
+
+#define ICS_ARCIN_V5_INTRSTAT 0x0000
+#define ICS_ARCIN_V5_INTROFFSET 0x0004
+
+#define ICS_ARCIN_V6_INTROFFSET_1 0x2200
+#define ICS_ARCIN_V6_INTRSTAT_1 0x2290
+#define ICS_ARCIN_V6_INTROFFSET_2 0x3200
+#define ICS_ARCIN_V6_INTRSTAT_2 0x3290
+
+struct portinfo {
+ unsigned int dataoffset;
+ unsigned int ctrloffset;
+ unsigned int stepping;
+};
+
+static const struct portinfo pata_icside_portinfo_v5 = {
+ .dataoffset = 0x2800,
+ .ctrloffset = 0x2b80,
+ .stepping = 6,
+};
+
+static const struct portinfo pata_icside_portinfo_v6_1 = {
+ .dataoffset = 0x2000,
+ .ctrloffset = 0x2380,
+ .stepping = 6,
+};
+
+static const struct portinfo pata_icside_portinfo_v6_2 = {
+ .dataoffset = 0x3000,
+ .ctrloffset = 0x3380,
+ .stepping = 6,
+};
+
+#define PATA_ICSIDE_MAX_SG 128
+
+struct pata_icside_state {
+ void __iomem *irq_port;
+ void __iomem *ioc_base;
+ unsigned int type;
+ unsigned int dma;
+ struct {
+ u8 port_sel;
+ u8 disabled;
+ unsigned int speed[ATA_MAX_DEVICES];
+ } port[2];
+ struct scatterlist sg[PATA_ICSIDE_MAX_SG];
+};
+
+#define ICS_TYPE_A3IN 0
+#define ICS_TYPE_A3USER 1
+#define ICS_TYPE_V6 3
+#define ICS_TYPE_V5 15
+#define ICS_TYPE_NOTYPE ((unsigned int)-1)
+
+/* ---------------- Version 5 PCB Support Functions --------------------- */
+/* Prototype: pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
+ * Purpose : enable interrupts from card
+ */
+static void pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
+{
+ struct pata_icside_state *state = ec->irq_data;
+
+ writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
+}
+
+/* Prototype: pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
+ * Purpose : disable interrupts from card
+ */
+static void pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
+{
+ struct pata_icside_state *state = ec->irq_data;
+
+ readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
+}
+
+static const expansioncard_ops_t pata_icside_ops_arcin_v5 = {
+ .irqenable = pata_icside_irqenable_arcin_v5,
+ .irqdisable = pata_icside_irqdisable_arcin_v5,
+};
+
+
+/* ---------------- Version 6 PCB Support Functions --------------------- */
+/* Prototype: pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
+ * Purpose : enable interrupts from card
+ */
+static void pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
+{
+ struct pata_icside_state *state = ec->irq_data;
+ void __iomem *base = state->irq_port;
+
+ if (!state->port[0].disabled)
+ writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
+ if (!state->port[1].disabled)
+ writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
+}
+
+/* Prototype: pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
+ * Purpose : disable interrupts from card
+ */
+static void pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
+{
+ struct pata_icside_state *state = ec->irq_data;
+
+ readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+ readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+}
+
+/* Prototype: pata_icside_irqprobe(struct expansion_card *ec)
+ * Purpose : detect an active interrupt from card
+ */
+static int pata_icside_irqpending_arcin_v6(struct expansion_card *ec)
+{
+ struct pata_icside_state *state = ec->irq_data;
+
+ return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
+ readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
+}
+
+static const expansioncard_ops_t pata_icside_ops_arcin_v6 = {
+ .irqenable = pata_icside_irqenable_arcin_v6,
+ .irqdisable = pata_icside_irqdisable_arcin_v6,
+ .irqpending = pata_icside_irqpending_arcin_v6,
+};
+
+
+/*
+ * SG-DMA support.
+ *
+ * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
+ * There is only one DMA controller per card, which means that only
+ * one drive can be accessed at one time. NOTE! We do not enforce that
+ * here, but we rely on the main IDE driver spotting that both
+ * interfaces use the same IRQ, which should guarantee this.
+ */
+
+/*
+ * Configure the IOMD to give the appropriate timings for the transfer
+ * mode being requested. We take the advice of the ATA standards, and
+ * calculate the cycle time based on the transfer mode, and the EIDE
+ * MW DMA specs that the drive provides in the IDENTIFY command.
+ *
+ * We have the following IOMD DMA modes to choose from:
+ *
+ * Type Active Recovery Cycle
+ * A 250 (250) 312 (550) 562 (800)
+ * B 187 (200) 250 (550) 437 (750)
+ * C 125 (125) 125 (375) 250 (500)
+ * D 62 (50) 125 (375) 187 (425)
+ *
+ * (figures in brackets are actual measured timings on DIOR/DIOW)
+ *
+ * However, we also need to take care of the read/write active and
+ * recovery timings:
+ *
+ * Read Write
+ * Mode Active -- Recovery -- Cycle IOMD type
+ * MW0 215 50 215 480 A
+ * MW1 80 50 50 150 C
+ * MW2 70 25 25 120 C
+ */
+static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pata_icside_state *state = ap->host->private_data;
+ struct ata_timing t;
+ unsigned int cycle;
+ char iomd_type;
+
+ /*
+ * DMA is based on a 16MHz clock
+ */
+ if (ata_timing_compute(adev, adev->dma_mode, &t, 1000, 1))
+ return;
+
+ /*
+ * Choose the IOMD cycle timing which ensure that the interface
+ * satisfies the measured active, recovery and cycle times.
+ */
+ if (t.active <= 50 && t.recover <= 375 && t.cycle <= 425)
+ iomd_type = 'D', cycle = 187;
+ else if (t.active <= 125 && t.recover <= 375 && t.cycle <= 500)
+ iomd_type = 'C', cycle = 250;
+ else if (t.active <= 200 && t.recover <= 550 && t.cycle <= 750)
+ iomd_type = 'B', cycle = 437;
+ else
+ iomd_type = 'A', cycle = 562;
+
+ ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n",
+ t.active, t.recover, t.cycle, iomd_type);
+
+ state->port[ap->port_no].speed[adev->devno] = cycle;
+}
+
+static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pata_icside_state *state = ap->host->private_data;
+ struct scatterlist *sg, *rsg = state->sg;
+ unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
+
+ /*
+ * We are simplex; BUG if we try to fiddle with DMA
+ * while it's active.
+ */
+ BUG_ON(dma_channel_active(state->dma));
+
+ /*
+ * Copy ATAs scattered sg list into a contiguous array of sg
+ */
+ ata_for_each_sg(sg, qc) {
+ memcpy(rsg, sg, sizeof(*sg));
+ rsg++;
+ }
+
+ /*
+ * Route the DMA signals to the correct interface
+ */
+ writeb(state->port[ap->port_no].port_sel, state->ioc_base);
+
+ set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]);
+ set_dma_sg(state->dma, state->sg, rsg - state->sg);
+ set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
+
+ /* issue r/w command */
+ ap->ops->exec_command(ap, &qc->tf);
+}
+
+static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pata_icside_state *state = ap->host->private_data;
+
+ BUG_ON(dma_channel_active(state->dma));
+ enable_dma(state->dma);
+}
+
+static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pata_icside_state *state = ap->host->private_data;
+
+ disable_dma(state->dma);
+
+ /* see ata_bmdma_stop */
+ ata_altstatus(ap);
+}
+
+static u8 pata_icside_bmdma_status(struct ata_port *ap)
+{
+ struct pata_icside_state *state = ap->host->private_data;
+ void __iomem *irq_port;
+
+ irq_port = state->irq_port + (ap->port_no ? ICS_ARCIN_V6_INTRSTAT_2 :
+ ICS_ARCIN_V6_INTRSTAT_1);
+
+ return readb(irq_port) & 1 ? ATA_DMA_INTR : 0;
+}
+
+static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
+{
+ struct pata_icside_state *state = ae->private_data;
+ int i;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ state->port[0].speed[i] = 480;
+ state->port[1].speed[i] = 480;
+ }
+
+ if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
+ state->dma = ec->dma;
+ ae->mwdma_mask = 0x07; /* MW0..2 */
+ }
+
+ return 0;
+}
+
+
+static int pata_icside_port_start(struct ata_port *ap)
+{
+ /* No PRD to alloc */
+ return ata_pad_alloc(ap, ap->dev);
+}
+
+static struct scsi_host_template pata_icside_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = PATA_ICSIDE_MAX_SG,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ~0, /* no dma boundaries */
+ .slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+};
+
+/* wish this was exported from libata-core */
+static void ata_dummy_noret(struct ata_port *port)
+{
+}
+
+/*
+ * We need to shut down unused ports to prevent spurious interrupts.
+ * FIXME: the libata core doesn't call this function for PATA interfaces.
+ */
+static void pata_icside_port_disable(struct ata_port *ap)
+{
+ struct pata_icside_state *state = ap->host->private_data;
+
+ ata_port_printk(ap, KERN_ERR, "disabling icside port\n");
+
+ ata_port_disable(ap);
+
+ state->port[ap->port_no].disabled = 1;
+
+ if (state->type == ICS_TYPE_V6) {
+ /*
+ * Disable interrupts from this port, otherwise we
+ * receive spurious interrupts from the floating
+ * interrupt line.
+ */
+ void __iomem *irq_port = state->irq_port +
+ (ap->port_no ? ICS_ARCIN_V6_INTROFFSET_2 : ICS_ARCIN_V6_INTROFFSET_1);
+ readb(irq_port);
+ }
+}
+
+static u8 pata_icside_irq_ack(struct ata_port *ap, unsigned int chk_drq)
+{
+ unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
+ u8 status;
+
+ status = ata_busy_wait(ap, bits, 1000);
+ if (status & bits)
+ if (ata_msg_err(ap))
+ printk(KERN_ERR "abnormal status 0x%X\n", status);
+
+ if (ata_msg_intr(ap))
+ printk(KERN_INFO "%s: irq ack: drv_stat 0x%X\n",
+ __FUNCTION__, status);
+
+ return status;
+}
+
+static struct ata_port_operations pata_icside_port_ops = {
+ .port_disable = pata_icside_port_disable,
+
+ .set_dmamode = pata_icside_set_dmamode,
+
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .exec_command = ata_exec_command,
+ .check_status = ata_check_status,
+ .dev_select = ata_std_dev_select,
+
+ .bmdma_setup = pata_icside_bmdma_setup,
+ .bmdma_start = pata_icside_bmdma_start,
+
+ .data_xfer = ata_data_xfer_noirq,
+
+ /* no need to build any PRD tables for DMA */
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = pata_icside_bmdma_stop,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_dummy_noret,
+ .irq_on = ata_irq_on,
+ .irq_ack = pata_icside_irq_ack,
+
+ .port_start = pata_icside_port_start,
+
+ .bmdma_stop = pata_icside_bmdma_stop,
+ .bmdma_status = pata_icside_bmdma_status,
+};
+
+static void
+pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base,
+ const struct portinfo *info)
+{
+ struct ata_ioports *ioaddr = &ae->port[ae->n_ports++];
+ void __iomem *cmd = base + info->dataoffset;
+
+ ioaddr->cmd_addr = cmd;
+ ioaddr->data_addr = cmd + (ATA_REG_DATA << info->stepping);
+ ioaddr->error_addr = cmd + (ATA_REG_ERR << info->stepping);
+ ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << info->stepping);
+ ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << info->stepping);
+ ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << info->stepping);
+ ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << info->stepping);
+ ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << info->stepping);
+ ioaddr->device_addr = cmd + (ATA_REG_DEVICE << info->stepping);
+ ioaddr->status_addr = cmd + (ATA_REG_STATUS << info->stepping);
+ ioaddr->command_addr = cmd + (ATA_REG_CMD << info->stepping);
+
+ ioaddr->ctl_addr = base + info->ctrloffset;
+ ioaddr->altstatus_addr = ioaddr->ctl_addr;
+}
+
+static int __init
+pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec)
+{
+ struct pata_icside_state *state = ae->private_data;
+ void __iomem *base;
+
+ base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
+ ecard_resource_len(ec, ECARD_RES_MEMC));
+ if (!base)
+ return -ENOMEM;
+
+ state->irq_port = base;
+
+ ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
+ ec->irqmask = 1;
+ ec->irq_data = state;
+ ec->ops = &pata_icside_ops_arcin_v5;
+
+ /*
+ * Be on the safe side - disable interrupts
+ */
+ ec->ops->irqdisable(ec, ec->irq);
+
+ pata_icside_add_port(ae, base, &pata_icside_portinfo_v5);
+
+ return 0;
+}
+
+static int __init
+pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
+{
+ struct pata_icside_state *state = ae->private_data;
+ void __iomem *ioc_base, *easi_base;
+ unsigned int sel = 0;
+ int ret;
+
+ ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+ ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ if (!ioc_base) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ easi_base = ioc_base;
+
+ if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
+ easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
+ ecard_resource_len(ec, ECARD_RES_EASI));
+ if (!easi_base) {
+ ret = -ENOMEM;
+ goto unmap_slot;
+ }
+
+ /*
+ * Enable access to the EASI region.
+ */
+ sel = 1 << 5;
+ }
+
+ writeb(sel, ioc_base);
+
+ ec->irq_data = state;
+ ec->ops = &pata_icside_ops_arcin_v6;
+
+ state->irq_port = easi_base;
+ state->ioc_base = ioc_base;
+ state->port[0].port_sel = sel;
+ state->port[1].port_sel = sel | 1;
+
+ /*
+ * Be on the safe side - disable interrupts
+ */
+ ec->ops->irqdisable(ec, ec->irq);
+
+ /*
+ * Find and register the interfaces.
+ */
+ pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1);
+ pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2);
+
+ /*
+ * FIXME: work around libata's aversion to calling port_disable.
+ * This permanently disables interrupts on port 0 - bad luck if
+ * you have a drive on that port.
+ */
+ state->port[0].disabled = 1;
+
+ return icside_dma_init(ae, ec);
+
+ unmap_slot:
+ iounmap(ioc_base);
+ out:
+ return ret;
+}
+
+static int __devinit
+pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+ struct pata_icside_state *state;
+ struct ata_probe_ent ae;
+ void __iomem *idmem;
+ int ret;
+
+ ret = ecard_request_resources(ec);
+ if (ret)
+ goto out;
+
+ state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL);
+ if (!state) {
+ ret = -ENOMEM;
+ goto release;
+ }
+
+ state->type = ICS_TYPE_NOTYPE;
+ state->dma = NO_DMA;
+
+ idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+ ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ if (idmem) {
+ unsigned int type;
+
+ type = readb(idmem + ICS_IDENT_OFFSET) & 1;
+ type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
+ type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
+ type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
+ iounmap(idmem);
+
+ state->type = type;
+ }
+
+ memset(&ae, 0, sizeof(ae));
+ INIT_LIST_HEAD(&ae.node);
+ ae.dev = &ec->dev;
+ ae.port_ops = &pata_icside_port_ops;
+ ae.sht = &pata_icside_sht;
+ ae.pio_mask = 0x1f;
+ ae.irq = ec->irq;
+ ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ ae._host_flags = ATA_HOST_SIMPLEX;
+ ae.private_data = state;
+
+ switch (state->type) {
+ case ICS_TYPE_A3IN:
+ dev_warn(&ec->dev, "A3IN unsupported\n");
+ ret = -ENODEV;
+ break;
+
+ case ICS_TYPE_A3USER:
+ dev_warn(&ec->dev, "A3USER unsupported\n");
+ ret = -ENODEV;
+ break;
+
+ case ICS_TYPE_V5:
+ ret = pata_icside_register_v5(&ae, ec);
+ break;
+
+ case ICS_TYPE_V6:
+ ret = pata_icside_register_v6(&ae, ec);
+ break;
+
+ default:
+ dev_warn(&ec->dev, "unknown interface type\n");
+ ret = -ENODEV;
+ break;
+ }
+
+ if (ret == 0)
+ ret = ata_device_add(&ae) == 0 ? -ENODEV : 0;
+
+ if (ret == 0)
+ goto out;
+
+ kfree(state);
+ release:
+ ecard_release_resources(ec);
+ out:
+ return ret;
+}
+
+static void pata_icside_shutdown(struct expansion_card *ec)
+{
+ struct ata_host *host = ecard_get_drvdata(ec);
+ unsigned long flags;
+
+ /*
+ * Disable interrupts from this card. We need to do
+ * this before disabling EASI since we may be accessing
+ * this register via that region.
+ */
+ local_irq_save(flags);
+ if (ec->ops)
+ ec->ops->irqdisable(ec, ec->irq);
+ local_irq_restore(flags);
+
+ /*
+ * Reset the ROM pointer so that we can read the ROM
+ * after a soft reboot. This also disables access to
+ * the IDE taskfile via the EASI region.
+ */
+ if (host) {
+ struct pata_icside_state *state = host->private_data;
+ if (state->ioc_base)
+ writeb(0, state->ioc_base);
+ }
+}
+
+static void __devexit pata_icside_remove(struct expansion_card *ec)
+{
+ struct ata_host *host = ecard_get_drvdata(ec);
+ struct pata_icside_state *state = host->private_data;
+
+ ata_host_detach(host);
+
+ pata_icside_shutdown(ec);
+
+ /*
+ * don't NULL out the drvdata - devres/libata wants it
+ * to free the ata_host structure.
+ */
+ ec->ops = NULL;
+ ec->irq_data = NULL;
+
+ if (state->dma != NO_DMA)
+ free_dma(state->dma);
+ if (state->ioc_base)
+ iounmap(state->ioc_base);
+ if (state->ioc_base != state->irq_port)
+ iounmap(state->irq_port);
+
+ kfree(state);
+ ecard_release_resources(ec);
+}
+
+static const struct ecard_id pata_icside_ids[] = {
+ { MANU_ICS, PROD_ICS_IDE },
+ { MANU_ICS2, PROD_ICS2_IDE },
+ { 0xffff, 0xffff }
+};
+
+static struct ecard_driver pata_icside_driver = {
+ .probe = pata_icside_probe,
+ .remove = __devexit_p(pata_icside_remove),
+ .shutdown = pata_icside_shutdown,
+ .id_table = pata_icside_ids,
+ .drv = {
+ .name = DRV_NAME,
+ },
+};
+
+static int __init pata_icside_init(void)
+{
+ return ecard_register_driver(&pata_icside_driver);
+}
+
+static void __exit pata_icside_exit(void)
+{
+ ecard_remove_driver(&pata_icside_driver);
+}
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ICS PATA driver");
+
+module_init(pata_icside_init);
+module_exit(pata_icside_exit);
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 011306e..17bf9f3 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -24,12 +24,13 @@
/**
* it8213_pre_reset - check for 40/80 pin
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* Filter out ports by the enable bits before doing the normal reset
* and probe.
*/
-static int it8213_pre_reset(struct ata_port *ap)
+static int it8213_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits it8213_enable_bits[] = {
{ 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
@@ -37,7 +38,8 @@ static int it8213_pre_reset(struct ata_port *ap)
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 43763c99..1daf78a 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -30,16 +30,17 @@ typedef enum {
/**
* jmicron_pre_reset - check for 40/80 pin
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* Perform the PATA port setup we need.
-
+ *
* On the Jmicron 361/363 there is a single PATA port that can be mapped
* either as primary or secondary (or neither). We don't do any policy
* and setup here. We assume that has been done by init_one and the
* BIOS.
*/
-static int jmicron_pre_reset(struct ata_port *ap)
+static int jmicron_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 control;
@@ -102,7 +103,7 @@ static int jmicron_pre_reset(struct ata_port *ap)
ap->cbl = ATA_CBL_SATA;
break;
}
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index d9b94a1..837b7fe 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -25,11 +25,12 @@
/**
* marvell_pre_reset - check for 40/80 pin
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* Perform the PATA port setup we need.
*/
-static int marvell_pre_reset(struct ata_port *ap)
+static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 devices;
@@ -52,7 +53,8 @@ static int marvell_pre_reset(struct ata_port *ap)
if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
(!(devices & 0x10))) /* PATA enable ? */
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
static int marvell_cable_detect(struct ata_port *ap)
@@ -67,6 +69,7 @@ static int marvell_cable_detect(struct ata_port *ap)
case 1: /* Legacy SATA port */
return ATA_CBL_SATA;
}
+
BUG();
return 0; /* Our BUG macro needs the right markup */
}
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 987c5fa..3bfbd49 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -46,14 +46,15 @@ enum {
SECONDARY = (1 << 14)
};
-static int mpiix_pre_reset(struct ata_port *ap)
+static int mpiix_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits mpiix_enable_bits = { 0x6D, 1, 0x80, 0x80 };
if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 078aeda..ebc58a9 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -33,11 +33,12 @@
/**
* ns87410_pre_reset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Check enabled ports
*/
-static int ns87410_pre_reset(struct ata_port *ap)
+static int ns87410_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits ns87410_enable_bits[] = {
@@ -47,7 +48,8 @@ static int ns87410_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index dea4690..4d75d32 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -30,11 +30,12 @@
/**
* oldpiix_pre_reset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Set up cable type and use generic probe init
*/
-static int oldpiix_pre_reset(struct ata_port *ap)
+static int oldpiix_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits oldpiix_enable_bits[] = {
@@ -44,7 +45,8 @@ static int oldpiix_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 13b63e2..0af8a2c 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -47,11 +47,12 @@ enum {
/**
* opti_pre_reset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Set up cable type and use generic probe init
*/
-static int opti_pre_reset(struct ata_port *ap)
+static int opti_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits opti_enable_bits[] = {
@@ -61,7 +62,8 @@ static int opti_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index b70e04c..2843e48 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -48,11 +48,12 @@ static int pci_clock; /* 0 = 33 1 = 25 */
/**
* optidma_pre_reset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Set up cable type and use generic probe init
*/
-static int optidma_pre_reset(struct ata_port *ap)
+static int optidma_pre_reset(struct ata_port *ap, unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits optidma_enable_bits = {
@@ -62,7 +63,7 @@ static int optidma_pre_reset(struct ata_port *ap)
if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 75dc847..11245e3 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -357,6 +357,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index a61cbc1..0d2cc49 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -301,6 +301,7 @@ static inline int pdc2027x_port_enabled(struct ata_port *ap)
/**
* pdc2027x_prereset - prereset for PATA host controller
* @ap: Target port
+ * @deadline: deadline jiffies for the operation
*
* Probeinit including cable detection.
*
@@ -308,12 +309,12 @@ static inline int pdc2027x_port_enabled(struct ata_port *ap)
* None (inherited from caller).
*/
-static int pdc2027x_prereset(struct ata_port *ap)
+static int pdc2027x_prereset(struct ata_port *ap, unsigned long deadline)
{
/* Check whether port enabled */
if (!pdc2027x_port_enabled(ap))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 27685ce..fb8c9e1 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -375,7 +375,7 @@ static __init int qdi_init(void)
res = inb(port + 3);
if (res & 1) {
/* Single channel mode */
- if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04))
+ if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
ct++;
} else {
/* Dual channel mode */
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 5df354d..203f463 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -1142,14 +1142,14 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
unsigned int board_idx = (unsigned int) ent->driver_data;
const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL };
- struct device *dev = &pdev->dev;
+ struct ata_host *host;
int rc;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev,
"version " DRV_VERSION "\n");
- host = ata_port_alloc_pinfo(&pdev->dev, ppi, 1);
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);
if (!host)
return -ENOMEM;
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 3956ef2..b6e0203 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -139,12 +139,14 @@ static struct sv_cable_table cable_detect[] = {
/**
* serverworks_cable_detect - cable detection
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Perform cable detection according to the device and subvendor
* identifications
*/
-static int serverworks_cable_detect(struct ata_port *ap) {
+static int serverworks_cable_detect(struct ata_port *ap)
+{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct sv_cable_table *cb = cable_detect;
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 6770820..a5886f0 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -94,11 +94,13 @@ static int sil680_cable_detect(struct ata_port *ap) {
/**
* sil680_bus_reset - reset the SIL680 bus
* @ap: ATA port to reset
+ * @deadline: deadline jiffies for the operation
*
* Perform the SIL680 housekeeping when doing an ATA bus reset
*/
-static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes)
+static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes,
+ unsigned long deadline)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long addr = sil680_selreg(ap, 0);
@@ -108,7 +110,7 @@ static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes)
pci_write_config_byte(pdev, addr, reset | 0x03);
udelay(25);
pci_write_config_byte(pdev, addr, reset);
- return ata_std_softreset(ap, classes);
+ return ata_std_softreset(ap, classes, deadline);
}
static void sil680_error_handler(struct ata_port *ap)
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index a3fbcee..f5838cc 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -88,6 +88,7 @@ static int sis_port_base(struct ata_device *adev)
/**
* sis_133_cable_detect - check for 40/80 pin
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* Perform cable detection for the later UDMA133 capable
* SiS chipset.
@@ -108,6 +109,7 @@ static int sis_133_cable_detect(struct ata_port *ap)
/**
* sis_66_cable_detect - check for 40/80 pin
* @ap: Port
+ * @deadline: deadline jiffies for the operation
*
* Perform cable detection on the UDMA66, UDMA100 and early UDMA133
* SiS IDE controllers.
@@ -130,11 +132,12 @@ static int sis_66_cable_detect(struct ata_port *ap)
/**
* sis_pre_reset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Set up cable type and use generic probe init
*/
-static int sis_pre_reset(struct ata_port *ap)
+static int sis_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits sis_enable_bits[] = {
{ 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */
@@ -145,7 +148,8 @@ static int sis_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index da9e22b..9aeffdb 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -44,11 +44,12 @@ enum {
/**
* sl82c105_pre_reset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Set up cable type and use generic probe init
*/
-static int sl82c105_pre_reset(struct ata_port *ap)
+static int sl82c105_pre_reset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits sl82c105_enable_bits[] = {
{ 0x40, 1, 0x01, 0x01 },
@@ -58,7 +59,7 @@ static int sl82c105_pre_reset(struct ata_port *ap)
if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index e618ffd..349887b 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -48,11 +48,12 @@
/**
* triflex_prereset - probe begin
* @ap: ATA port
+ * @deadline: deadline jiffies for the operation
*
* Set up cable type and use generic probe init
*/
-static int triflex_prereset(struct ata_port *ap)
+static int triflex_prereset(struct ata_port *ap, unsigned long deadline)
{
static const struct pci_bits triflex_enable_bits[] = {
{ 0x80, 1, 0x01, 0x01 },
@@ -63,7 +64,8 @@ static int triflex_prereset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
return -ENOENT;
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 96b7179..362beb2 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -154,7 +154,7 @@ static int via_cable_detect(struct ata_port *ap) {
return ATA_CBL_PATA40;
}
-static int via_pre_reset(struct ata_port *ap)
+static int via_pre_reset(struct ata_port *ap, unsigned long deadline)
{
const struct via_isa_bridge *config = ap->host->private_data;
@@ -167,7 +167,8 @@ static int via_pre_reset(struct ata_port *ap)
if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no]))
return -ENOENT;
}
- return ata_std_prereset(ap);
+
+ return ata_std_prereset(ap, deadline);
}
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index f099a1d..b3b62e9 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -420,7 +420,8 @@ static void inic_thaw(struct ata_port *ap)
* SRST and SControl hardreset don't give valid signature on this
* controller. Only controller specific hardreset mechanism works.
*/
-static int inic_hardreset(struct ata_port *ap, unsigned int *class)
+static int inic_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
void __iomem *port_base = inic_port_base(ap);
void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
@@ -437,7 +438,7 @@ static int inic_hardreset(struct ata_port *ap, unsigned int *class)
msleep(1);
writew(val & ~IDMA_CTL_RST_ATA, idma_ctl);
- rc = sata_phy_resume(ap, timing);
+ rc = sata_phy_resume(ap, timing, deadline);
if (rc) {
ata_port_printk(ap, KERN_WARNING, "failed to resume "
"link after reset (errno=%d)\n", rc);
@@ -451,10 +452,12 @@ static int inic_hardreset(struct ata_port *ap, unsigned int *class)
/* wait a while before checking status */
msleep(150);
- if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
- ata_port_printk(ap, KERN_WARNING,
- "device busy after hardreset\n");
- return -EIO;
+ rc = ata_wait_ready(ap, deadline);
+ /* link occupied, -ENODEV too is an error */
+ if (rc) {
+ ata_port_printk(ap, KERN_WARNING, "device not ready "
+ "after hardreset (errno=%d)\n", rc);
+ return rc;
}
ata_tf_read(ap, &tf);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 0216974..a097595 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -257,6 +257,8 @@ static void nv_adma_port_stop(struct ata_port *ap);
static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
static int nv_adma_port_resume(struct ata_port *ap);
#endif
+static void nv_adma_freeze(struct ata_port *ap);
+static void nv_adma_thaw(struct ata_port *ap);
static void nv_adma_error_handler(struct ata_port *ap);
static void nv_adma_host_stop(struct ata_host *host);
static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
@@ -444,8 +446,8 @@ static const struct ata_port_operations nv_adma_ops = {
.bmdma_status = ata_bmdma_status,
.qc_prep = nv_adma_qc_prep,
.qc_issue = nv_adma_qc_issue,
- .freeze = nv_ck804_freeze,
- .thaw = nv_ck804_thaw,
+ .freeze = nv_adma_freeze,
+ .thaw = nv_adma_thaw,
.error_handler = nv_adma_error_handler,
.post_internal_cmd = nv_adma_post_internal_cmd,
.data_xfer = ata_data_xfer,
@@ -815,8 +817,16 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
u16 status;
u32 gen_ctl;
u32 notifier, notifier_error;
+
+ /* if ADMA is disabled, use standard ata interrupt handler */
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
+ u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
+ >> (NV_INT_PORT_SHIFT * i);
+ handled += nv_host_intr(ap, irq_stat);
+ continue;
+ }
- /* if in ATA register mode, use standard ata interrupt handler */
+ /* if in ATA register mode, check for standard interrupts */
if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
>> (NV_INT_PORT_SHIFT * i);
@@ -826,7 +836,6 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
command is active, to prevent losing interrupts. */
irq_stat |= NV_INT_DEV;
handled += nv_host_intr(ap, irq_stat);
- continue;
}
notifier = readl(mmio + NV_ADMA_NOTIFIER);
@@ -912,22 +921,77 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
return IRQ_RETVAL(handled);
}
+static void nv_adma_freeze(struct ata_port *ap)
+{
+ struct nv_adma_port_priv *pp = ap->private_data;
+ void __iomem *mmio = pp->ctl_block;
+ u16 tmp;
+
+ nv_ck804_freeze(ap);
+
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+ return;
+
+ /* clear any outstanding CK804 notifications */
+ writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+ ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
+
+ /* Disable interrupt */
+ tmp = readw(mmio + NV_ADMA_CTL);
+ writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+ mmio + NV_ADMA_CTL);
+ readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+}
+
+static void nv_adma_thaw(struct ata_port *ap)
+{
+ struct nv_adma_port_priv *pp = ap->private_data;
+ void __iomem *mmio = pp->ctl_block;
+ u16 tmp;
+
+ nv_ck804_thaw(ap);
+
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+ return;
+
+ /* Enable interrupt */
+ tmp = readw(mmio + NV_ADMA_CTL);
+ writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+ mmio + NV_ADMA_CTL);
+ readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+}
+
static void nv_adma_irq_clear(struct ata_port *ap)
{
struct nv_adma_port_priv *pp = ap->private_data;
void __iomem *mmio = pp->ctl_block;
- u16 status = readw(mmio + NV_ADMA_STAT);
- u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
- u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
- void __iomem *dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+ u32 notifier_clears[2];
- /* clear ADMA status */
- writew(status, mmio + NV_ADMA_STAT);
- writel(notifier | notifier_error,
- pp->notifier_clear_block);
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
+ ata_bmdma_irq_clear(ap);
+ return;
+ }
+
+ /* clear any outstanding CK804 notifications */
+ writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+ ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
- /** clear legacy status */
- iowrite8(ioread8(dma_stat_addr), dma_stat_addr);
+ /* clear ADMA status */
+ writew(0xffff, mmio + NV_ADMA_STAT);
+
+ /* clear notifiers - note both ports need to be written with
+ something even though we are only clearing on one */
+ if (ap->port_no == 0) {
+ notifier_clears[0] = 0xFFFFFFFF;
+ notifier_clears[1] = 0;
+ } else {
+ notifier_clears[0] = 0;
+ notifier_clears[1] = 0xFFFFFFFF;
+ }
+ pp = ap->host->ports[0]->private_data;
+ writel(notifier_clears[0], pp->notifier_clear_block);
+ pp = ap->host->ports[1]->private_data;
+ writel(notifier_clears[1], pp->notifier_clear_block);
}
static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -1405,7 +1469,8 @@ static void nv_ck804_thaw(struct ata_port *ap)
writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
}
-static int nv_hardreset(struct ata_port *ap, unsigned int *class)
+static int nv_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
unsigned int dummy;
@@ -1413,7 +1478,7 @@ static int nv_hardreset(struct ata_port *ap, unsigned int *class)
* some controllers. Don't classify on hardreset. For more
* info, see http://bugme.osdl.org/show_bug.cgi?id=3352
*/
- return sata_std_hardreset(ap, &dummy);
+ return sata_std_hardreset(ap, &dummy, deadline);
}
static void nv_error_handler(struct ata_port *ap)
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index f56549b..3a7d9b5 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -45,7 +45,7 @@
#include "sata_promise.h"
#define DRV_NAME "sata_promise"
-#define DRV_VERSION "2.05"
+#define DRV_VERSION "2.07"
enum {
@@ -653,6 +653,8 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
qc->err_mask |= ac_err_mask;
pdc_reset_port(ap);
+
+ ata_port_abort(ap);
}
static inline unsigned int pdc_host_intr( struct ata_port *ap,
@@ -924,6 +926,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
struct ata_host *host;
void __iomem *base;
int n_ports, i, rc;
+ int is_sataii_tx4;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -962,10 +965,23 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
}
host->iomap = pcim_iomap_table(pdev);
- for (i = 0; i < host->n_ports; i++)
+ is_sataii_tx4 = 0;
+ if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) {
+ is_sataii_tx4 = 1;
+ dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n");
+ }
+ for (i = 0; i < host->n_ports; i++) {
+ static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+ int ata_nr;
+
+ ata_nr = i;
+ if (is_sataii_tx4)
+ ata_nr = sataii_tx4_port_remap[i];
+
pdc_ata_setup_port(host->ports[i],
- base + 0x200 + i * 0x80,
- base + 0x400 + i * 0x100);
+ base + 0x200 + ata_nr * 0x80,
+ base + 0x400 + ata_nr * 0x100);
+ }
/* initialize adapter */
pdc_host_init(host);
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index e6223ba..b97ee9f 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -534,7 +534,8 @@ static int sil24_init_port(struct ata_port *ap)
return 0;
}
-static int sil24_softreset(struct ata_port *ap, unsigned int *class)
+static int sil24_softreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
void __iomem *port = ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data;
@@ -566,7 +567,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)
mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
- 100, ATA_TMOUT_BOOT / HZ * 1000);
+ 100, jiffies_to_msecs(deadline - jiffies));
writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
irq_stat >>= PORT_IRQ_RAW_SHIFT;
@@ -594,7 +595,8 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)
return -EIO;
}
-static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
+static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
void __iomem *port = ap->ioaddr.cmd_addr;
const char *reason;
@@ -615,7 +617,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
/* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it.
*/
- rc = sata_phy_debounce(ap, sata_deb_timing_long);
+ rc = sata_phy_debounce(ap, sata_deb_timing_long, deadline);
if (rc) {
reason = "PHY debouncing failed";
goto err;
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index cc07aac..1724673 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -288,7 +288,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
/* Match it to a port node */
index = (ap == ap->host->ports[0]) ? 0 : 1;
for (np = np->child; np != NULL; np = np->sibling) {
- const u32 *reg = get_property(np, "reg", NULL);
+ const u32 *reg = of_get_property(np, "reg", NULL);
if (!reg)
continue;
if (index == *reg)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1d855f5..939c924 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -93,6 +93,10 @@ static struct pci_driver svia_pci_driver = {
.name = DRV_NAME,
.id_table = svia_pci_tbl,
.probe = svia_init_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = ata_pci_device_resume,
+#endif
.remove = ata_pci_remove_one,
};
@@ -112,6 +116,10 @@ static struct scsi_host_template svia_sht = {
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+#ifdef CONFIG_PM
+ .suspend = ata_scsi_device_suspend,
+ .resume = ata_scsi_device_resume,
+#endif
};
static const struct ata_port_operations vt6420_sata_ops = {
@@ -268,6 +276,7 @@ static void svia_noop_freeze(struct ata_port *ap)
/**
* vt6420_prereset - prereset for vt6420
* @ap: target ATA port
+ * @deadline: deadline jiffies for the operation
*
* SCR registers on vt6420 are pieces of shit and may hang the
* whole machine completely if accessed with the wrong timing.
@@ -284,7 +293,7 @@ static void svia_noop_freeze(struct ata_port *ap)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-static int vt6420_prereset(struct ata_port *ap)
+static int vt6420_prereset(struct ata_port *ap, unsigned long deadline)
{
struct ata_eh_context *ehc = &ap->eh_context;
unsigned long timeout = jiffies + (HZ * 5);
@@ -329,7 +338,7 @@ static int vt6420_prereset(struct ata_port *ap)
skip_scr:
/* wait for !BSY */
- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ ata_wait_ready(ap, deadline);
return 0;
}
OpenPOWER on IntegriCloud