* [PATCH 3/7] libata-pm-prep: separate out sata_link_hardreset()
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
` (2 preceding siblings ...)
2006-05-11 16:37 ` [PATCH 2/7] libata-pm-prep: make a number of functions global to libata Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 5/7] libata-pm-prep: implement ops->qc_defer() Tejun Heo
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Separate out sata_link_hardreset() from sata_std_hardreset(). This
will be used by PM.
---
drivers/scsi/libata-core.c | 54 ++++++++++++++++++++++++++++++++++----------
drivers/scsi/libata.h | 1 +
2 files changed, 43 insertions(+), 12 deletions(-)
618a80782b3044ecbfff23f978aa0066942332d0
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index d4e3b37..53b5ed0 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2620,11 +2620,10 @@ int ata_std_softreset(struct ata_link *l
}
/**
- * sata_std_hardreset - reset host port via SATA phy reset
+ * sata_link_hardreset - reset link via SATA phy reset
* @link: link to reset
- * @class: resulting class of attached device
*
- * SATA phy-reset host port using DET bits of SControl register.
+ * SATA phy-reset @link using DET bits of SControl register.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -2632,11 +2631,10 @@ int ata_std_softreset(struct ata_link *l
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int sata_std_hardreset(struct ata_link *link, unsigned int *class)
+int sata_link_hardreset(struct ata_link *link)
{
- struct ata_port *ap = link->ap;
u32 scontrol;
- int rc;
+ int rc = 0;
DPRINTK("ENTER\n");
@@ -2647,24 +2645,24 @@ int sata_std_hardreset(struct ata_link *
* and Sil3124.
*/
if ((rc = ata_scr_read(link, SCR_CONTROL, &scontrol)))
- return rc;
+ goto out;
scontrol = (scontrol & 0x0f0) | 0x302;
if ((rc = ata_scr_write(link, SCR_CONTROL, scontrol)))
- return rc;
+ goto out;
ata_set_sata_spd(link);
}
/* issue phy wake/reset */
if ((rc = ata_scr_read(link, SCR_CONTROL, &scontrol)))
- return rc;
+ goto out;
scontrol = (scontrol & 0x0f0) | 0x301;
if ((rc = ata_scr_write_flush(link, SCR_CONTROL, scontrol)))
- return rc;
+ goto out;
/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
* 10.4.2 says at least 1 ms.
@@ -2672,9 +2670,41 @@ int sata_std_hardreset(struct ata_link *
msleep(1);
/* bring phy back */
- sata_link_resume(link, 0);
+ rc = sata_link_resume(link, 0);
+ out:
+ if (rc)
+ ata_link_printk(link, KERN_ERR,
+ "COMRESET failed (errno=%d)\n", rc);
+ DPRINTK("EXIT, rc=%d\n", rc);
+ return rc;
+}
+
+/**
+ * sata_std_hardreset - reset host port via SATA phy reset
+ * @link: link to reset
+ * @class: resulting class of attached device
+ *
+ * SATA phy-reset host port using DET bits of SControl register,
+ * wait for !BSY and classify the attached device.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int sata_std_hardreset(struct ata_link *link, unsigned int *class)
+{
+ struct ata_port *ap = link->ap;
+ int rc;
+
+ DPRINTK("ENTER\n");
+
+ /* do hardreset */
+ rc = sata_link_hardreset(link);
+ if (rc)
+ return rc;
- /* TODO: phy layer with polling, timeouts, etc. */
if (ata_link_offline(link)) {
*class = ATA_DEV_NONE;
DPRINTK("EXIT, link offline\n");
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index e4d21aa..0f3cefe 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -54,6 +54,7 @@ extern int ata_dev_read_id(struct ata_de
int post_reset, u16 *id);
extern int ata_dev_configure(struct ata_device *dev, int print_info);
extern void sata_print_link_status(struct ata_link *link);
+extern int sata_link_hardreset(struct ata_link *link);
extern int ata_down_sata_spd_limit(struct ata_link *link);
extern int ata_set_sata_spd_needed(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHSET 10/11] prep for PM support
@ 2006-05-11 16:37 Tejun Heo
2006-05-11 16:37 ` [PATCH 4/7] libata-pm-prep: add @is_cmd to ata_tf_to_fis() Tejun Heo
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide,
htejun
Howdy,
This is part of patchset series described in [T].
This is the first take of prep-for-PM-support patchset. This patchset
contains 7 patches and implements various stuff needed for PM.
One of important updates is the addition of ops->qc_defer(). This is
to let LLDDs determine which commands they can accept at the moment.
This is necessary for PM and controllers have wildely different
capabilities regarding how many/different commands can be issued to
how many devices concurrently. More info is in the message [T].
This patchset is against
upstream (acc696d93dcf993dec123d69d599979e1456ffec)
+ [1] prep-for-new-EH patchset
+ [2] new-EH-framework patchset, take 3
+ [3] new-EH-implementation patchset, take 3
+ [4] merge-irq-pio patchset
+ [5] add-NCQ-support patchset, take 3
+ [6] prep-for-hotplug support, take 2
+ [7] prep-LLDDs-for-hotplug-support, take 1
+ [8] add-hotplug-support, take 2
+ [9] implement-ata_link, take 1
--
tejun
[T] http://article.gmane.org/gmane.linux.ide/9957
[1] http://article.gmane.org/gmane.linux.ide/9959
[2] http://article.gmane.org/gmane.linux.ide/9984
[3] http://article.gmane.org/gmane.linux.ide/9995
[4] http://article.gmane.org/gmane.linux.ide/10005
[5] http://article.gmane.org/gmane.linux.ide/10011
[6] http://article.gmane.org/gmane.linux.ide/10028
[7] http://article.gmane.org/gmane.linux.ide/10063
[8] http://article.gmane.org/gmane.linux.ide/10073
[9] http://article.gmane.org/gmane.linux.ide/10106
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/7] libata-pm-prep: add @is_cmd to ata_tf_to_fis()
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 1/7] libata-pm-prep: add @new_class to ata_dev_revalidate() Tejun Heo
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Add @is_cmd to ata_tf_to_fis(). This controls bit 7 of the second
byte of the constructed FIS which tells the device whether it is for a
command or not. This cleans up ahci a bit and will be used by PM.
---
drivers/scsi/ahci.c | 8 +++-----
drivers/scsi/libata-core.c | 14 ++++++++------
drivers/scsi/sata_qstor.c | 2 +-
drivers/scsi/sata_sil24.c | 2 +-
include/linux/libata.h | 3 ++-
5 files changed, 15 insertions(+), 14 deletions(-)
b3b89cc12158046907c50b2112e6bb4e87c5b8cc
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 3254cd2..526150b 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -628,8 +628,7 @@ static int ahci_softreset(struct ata_lin
cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
tf.ctl |= ATA_SRST;
- ata_tf_to_fis(&tf, fis, 0);
- fis[1] &= ~(1 << 7); /* turn off Command FIS bit */
+ ata_tf_to_fis(&tf, 0, 0, fis);
writel(1, port_mmio + PORT_CMD_ISSUE);
@@ -647,8 +646,7 @@ static int ahci_softreset(struct ata_lin
ahci_fill_cmd_slot(pp, 0, cmd_fis_len);
tf.ctl &= ~ATA_SRST;
- ata_tf_to_fis(&tf, fis, 0);
- fis[1] &= ~(1 << 7); /* turn off Command FIS bit */
+ ata_tf_to_fis(&tf, 0, 0, fis);
writel(1, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); /* flush */
@@ -787,7 +785,7 @@ static void ahci_qc_prep(struct ata_queu
*/
cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
- ata_tf_to_fis(&qc->tf, cmd_tbl, 0);
+ ata_tf_to_fis(&qc->tf, 0, 1, cmd_tbl);
if (is_atapi) {
memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 53b5ed0..b9feefb 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -92,8 +92,9 @@ MODULE_VERSION(DRV_VERSION);
/**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* @tf: Taskfile to convert
- * @fis: Buffer into which data will output
* @pmp: Port multiplier port
+ * @is_cmd: This FIS is for command
+ * @fis: Buffer into which data will output
*
* Converts a standard ATA taskfile to a Serial ATA
* FIS structure (Register - Host to Device).
@@ -101,12 +102,13 @@ MODULE_VERSION(DRV_VERSION);
* LOCKING:
* Inherited from caller.
*/
-
-void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
+void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis)
{
- fis[0] = 0x27; /* Register - Host to Device FIS */
- fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
- bit 7 indicates Command FIS */
+ fis[0] = 0x27; /* Register - Host to Device FIS */
+ fis[1] = pmp & 0xf; /* Port multiplier number*/
+ if (is_cmd)
+ fis[1] |= (1 << 7); /* bit 7 indicates Command FIS */
+
fis[2] = tf->command;
fis[3] = tf->feature;
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index fe2a6cf..d1877e0 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -335,7 +335,7 @@ static void qs_qc_prep(struct ata_queued
buf[28] = dflags;
/* frame information structure (FIS) */
- ata_tf_to_fis(&qc->tf, &buf[32], 0);
+ ata_tf_to_fis(&qc->tf, 0, 1, &buf[32]);
}
static inline void qs_packet_start(struct ata_queued_cmd *qc)
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 103e5d3..a952513 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -682,7 +682,7 @@ static void sil24_qc_prep(struct ata_que
}
prb->ctrl = cpu_to_le16(ctrl);
- ata_tf_to_fis(&qc->tf, prb->fis, 0);
+ ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, prb->fis);
if (qc->flags & ATA_QCFLAG_DMAMAP)
sil24_fill_sg(qc, sge);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 1fec322..17a4af4 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -678,7 +678,8 @@ extern u32 ata_wait_register(void __iome
*/
extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp);
+extern void ata_tf_to_fis(const struct ata_taskfile *tf,
+ u8 pmp, int is_cmd, u8 *fis);
extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
extern u8 ata_noop_check_status(struct ata_port *ap);
extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 1/7] libata-pm-prep: add @new_class to ata_dev_revalidate()
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
2006-05-11 16:37 ` [PATCH 4/7] libata-pm-prep: add @is_cmd to ata_tf_to_fis() Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 2/7] libata-pm-prep: make a number of functions global to libata Tejun Heo
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Consider newly found class code while revalidating. PM resetting
always results in valid class code and issuing PM commands to
ATA/ATAPI devices isn't a very attractive idea. Add @new_class to
ata_dev_revalidate() and check class during revalidation.
---
drivers/scsi/libata-core.c | 20 +++++++++++++++-----
drivers/scsi/libata-eh.c | 2 +-
include/linux/libata.h | 3 ++-
3 files changed, 18 insertions(+), 7 deletions(-)
e9ad06f7ef8413f1027baad8b64bc860b85fa85e
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 32ea394..71f9ea7 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2052,7 +2052,7 @@ static int ata_dev_set_mode(struct ata_d
return -EIO;
}
- rc = ata_dev_revalidate(dev, 0);
+ rc = ata_dev_revalidate(dev, ATA_DEV_UNKNOWN, 0);
if (rc)
return rc;
@@ -2813,6 +2813,7 @@ static int ata_dev_same_device(struct at
/**
* ata_dev_revalidate - Revalidate ATA device
* @dev: device to revalidate
+ * @new_class: new class code
* @post_reset: is this revalidation after reset?
*
* Re-read IDENTIFY page and make sure @dev is still attached to
@@ -2824,9 +2825,9 @@ static int ata_dev_same_device(struct at
* RETURNS:
* 0 on success, negative errno otherwise
*/
-int ata_dev_revalidate(struct ata_device *dev, int post_reset)
+int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
+ int post_reset)
{
- unsigned int class = dev->class;
u16 *id = (void *)dev->link->ap->sector_buf;
int rc;
@@ -2835,13 +2836,22 @@ int ata_dev_revalidate(struct ata_device
goto fail;
}
+ if (ata_class_enabled(new_class)) {
+ /* sometimes wrong class is reported, let it retry */
+ if (new_class != ATA_DEV_ATA && new_class != ATA_DEV_ATAPI) {
+ rc = -EIO;
+ goto fail;
+ }
+ } else
+ new_class = dev->class;
+
/* read ID data */
- rc = ata_dev_read_id(dev, &class, post_reset, id);
+ rc = ata_dev_read_id(dev, &new_class, post_reset, id);
if (rc)
goto fail;
/* is the device still there? */
- if (!ata_dev_same_device(dev, class, id)) {
+ if (!ata_dev_same_device(dev, new_class, id)) {
rc = -ENODEV;
goto fail;
}
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index ecfb9c5..7abeb11 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -1570,7 +1570,7 @@ static int ata_eh_revalidate_and_attach(
}
ata_eh_about_to_do(link, ATA_EH_REVALIDATE);
- rc = ata_dev_revalidate(dev,
+ rc = ata_dev_revalidate(dev, ehc->classes[dev->devno],
ehc->flags & ATA_EHC_DID_RESET);
if (rc)
break;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 7db9b80..1fec322 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -633,7 +633,8 @@ extern int ata_std_prereset(struct ata_l
extern int ata_std_softreset(struct ata_link *link, unsigned int *classes);
extern int sata_std_hardreset(struct ata_link *link, unsigned int *class);
extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
-extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
+extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
+ int post_reset);
extern void ata_port_disable(struct ata_port *);
extern void ata_std_ports(struct ata_ioports *ioaddr);
#ifdef CONFIG_PCI
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/7] libata-pm-prep: make a number of functions global to libata
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
2006-05-11 16:37 ` [PATCH 4/7] libata-pm-prep: add @is_cmd to ata_tf_to_fis() Tejun Heo
2006-05-11 16:37 ` [PATCH 1/7] libata-pm-prep: add @new_class to ata_dev_revalidate() Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 3/7] libata-pm-prep: separate out sata_link_hardreset() Tejun Heo
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Make a number of functions from libata-core.c and libata-eh.c global
to libata (drivers/scsi/libata.h). These will be used by PM.
---
drivers/scsi/libata-core.c | 7 +++----
drivers/scsi/libata-eh.c | 24 ++++++++++++------------
drivers/scsi/libata.h | 15 +++++++++++++++
3 files changed, 30 insertions(+), 16 deletions(-)
9827f37046db8165d763573523d3cd864966a1be
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 71f9ea7..d4e3b37 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -65,7 +65,6 @@ static unsigned int ata_dev_init_params(
u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static void ata_dev_xfermask(struct ata_device *dev);
-static int ata_link_init_sata_spd_limit(struct ata_link *link);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
@@ -1594,7 +1593,7 @@ void ata_port_probe(struct ata_port *ap)
* LOCKING:
* None.
*/
-static void sata_print_link_status(struct ata_link *link)
+void sata_print_link_status(struct ata_link *link)
{
u32 sstatus, scontrol, tmp;
@@ -5118,7 +5117,7 @@ void ata_dev_init(struct ata_device *dev
* LOCKING:
* Kernel thread context (may sleep)
*/
-static void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
+void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
{
struct ata_device *dev;
@@ -5151,7 +5150,7 @@ static void ata_link_init(struct ata_por
* RETURNS:
* 0 on success, -errno on failure.
*/
-static int ata_link_init_sata_spd_limit(struct ata_link *link)
+int ata_link_init_sata_spd_limit(struct ata_link *link)
{
u32 scontrol, spd;
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 7abeb11..3764e21 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -679,7 +679,7 @@ void ata_eh_qc_retry(struct ata_queued_c
* LOCKING:
* None.
*/
-static void ata_eh_detach_dev(struct ata_device *dev)
+void ata_eh_detach_dev(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
unsigned long flags;
@@ -710,7 +710,7 @@ static void ata_eh_detach_dev(struct ata
* LOCKING:
* None.
*/
-static void ata_eh_about_to_do(struct ata_link *link, unsigned int action)
+void ata_eh_about_to_do(struct ata_link *link, unsigned int action)
{
struct ata_port *ap = link->ap;
unsigned long flags;
@@ -1296,7 +1296,7 @@ static void ata_eh_link_autopsy(struct a
* LOCKING:
* Kernel thread context (may sleep).
*/
-static void ata_eh_autopsy(struct ata_port *ap)
+void ata_eh_autopsy(struct ata_port *ap)
{
struct ata_link *link;
@@ -1382,7 +1382,7 @@ static void ata_eh_link_report(struct at
* LOCKING:
* None.
*/
-static void ata_eh_report(struct ata_port *ap)
+void ata_eh_report(struct ata_port *ap)
{
struct ata_link *link;
@@ -1431,9 +1431,9 @@ static int ata_eh_followup_srst_needed(i
return 0;
}
-static int ata_eh_reset(struct ata_link *link, int classify,
- ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
- ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
+int ata_eh_reset(struct ata_link *link, int classify,
+ ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+ ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
struct ata_eh_context *ehc = &link->eh_context;
unsigned int *classes = ehc->classes;
@@ -1665,10 +1665,10 @@ static int ata_eh_skip_recovery(struct a
* RETURNS:
* 0 on success, -errno on failure.
*/
-static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
- ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
- ata_postreset_fn_t postreset,
- struct ata_link **r_failed_link)
+int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+ ata_postreset_fn_t postreset,
+ struct ata_link **r_failed_link)
{
struct ata_link *link;
struct ata_eh_context *ehc;
@@ -1843,7 +1843,7 @@ static int ata_eh_recover(struct ata_por
* LOCKING:
* None.
*/
-static void ata_eh_finish(struct ata_port *ap)
+void ata_eh_finish(struct ata_port *ap)
{
int tag;
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index f09c23e..e4d21aa 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -53,6 +53,7 @@ extern unsigned ata_exec_internal(struct
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
int post_reset, u16 *id);
extern int ata_dev_configure(struct ata_device *dev, int print_info);
+extern void sata_print_link_status(struct ata_link *link);
extern int ata_down_sata_spd_limit(struct ata_link *link);
extern int ata_set_sata_spd_needed(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
@@ -66,6 +67,8 @@ extern void ata_dev_select(struct ata_po
unsigned int wait, unsigned int can_sleep);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
extern void ata_dev_init(struct ata_device *dev);
+extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
+extern int ata_link_init_sata_spd_limit(struct ata_link *link);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
@@ -111,6 +114,18 @@ extern void ata_ering_init(struct ata_er
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
+extern void ata_eh_detach_dev(struct ata_device *dev);
+extern void ata_eh_about_to_do(struct ata_link *link, unsigned int action);
+extern void ata_eh_autopsy(struct ata_port *ap);
+extern void ata_eh_report(struct ata_port *ap);
+extern int ata_eh_reset(struct ata_link *link, int classify,
+ ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+ ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
+extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+ ata_postreset_fn_t postreset,
+ struct ata_link **r_failed_disk);
+extern void ata_eh_finish(struct ata_port *ap);
extern void ata_eh_scsi_hotplug(void *data);
#endif /* __LIBATA_H__ */
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/7] libata-pm-prep: implement qc_defer helpers
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
` (5 preceding siblings ...)
2006-05-11 16:37 ` [PATCH 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action helpers Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Implement ap->nr_active_links (the number of links with active qcs),
ap->excl_link (pointer to link which can be used by ->qc_defer and is
cleared when a qc with ATA_QCFLAG_CLEAR_EXCL completes), and
ata_link_active().
These can be used by ->qc_defer() to implement proper command
exclusion. This set of helpers seem enough for both sil24 (ATAPI
exclusion needed) and cmd-switching PM.
---
drivers/scsi/libata-core.c | 22 +++++++++++++++++++---
drivers/scsi/libata-eh.c | 5 +++++
include/linux/libata.h | 8 ++++++++
3 files changed, 32 insertions(+), 3 deletions(-)
7deb1fc49ea4e26d9f1bc4258094086e0bcb27f2
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 5dd5a28..fb64a0f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -994,7 +994,6 @@ void ata_qc_complete_internal(struct ata
* LOCKING:
* None. Should be called with kernel context, might sleep.
*/
-
unsigned ata_exec_internal(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, void *buf, unsigned int buflen)
@@ -1005,6 +1004,7 @@ unsigned ata_exec_internal(struct ata_de
struct ata_queued_cmd *qc;
unsigned int tag, preempted_tag;
u32 preempted_sactive, preempted_qc_active;
+ int preempted_nr_active_links;
DECLARE_COMPLETION(wait);
unsigned long flags;
unsigned int err_mask;
@@ -1043,9 +1043,11 @@ unsigned ata_exec_internal(struct ata_de
preempted_tag = link->active_tag;
preempted_sactive = link->sactive;
preempted_qc_active = ap->qc_active;
+ preempted_nr_active_links = ap->nr_active_links;
link->active_tag = ATA_TAG_POISON;
link->sactive = 0;
ap->qc_active = 0;
+ ap->nr_active_links = 0;
/* prepare & issue qc */
qc->tf = *tf;
@@ -1112,6 +1114,7 @@ unsigned ata_exec_internal(struct ata_de
link->active_tag = preempted_tag;
link->sactive = preempted_sactive;
ap->qc_active = preempted_qc_active;
+ ap->nr_active_links = preempted_nr_active_links;
/* XXX - Some LLDDs (sata_mv) disable port on command failure.
* Until those drivers are fixed, we detect the condition
@@ -4327,10 +4330,18 @@ void __ata_qc_complete(struct ata_queued
ata_sg_clean(qc);
/* command should be marked inactive atomically with qc completion */
- if (qc->tf.protocol == ATA_PROT_NCQ)
+ if (qc->tf.protocol == ATA_PROT_NCQ) {
link->sactive &= ~(1 << qc->tag);
- else
+ if (!link->sactive)
+ ap->nr_active_links--;
+ } else {
link->active_tag = ATA_TAG_POISON;
+ ap->nr_active_links--;
+ }
+
+ /* clear exclusive status */
+ if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL))
+ ap->excl_link = NULL;
/* atapi: mark qc as inactive to prevent the interrupt handler
* from completing the command twice later, before the error handler
@@ -4503,9 +4514,14 @@ void ata_qc_issue(struct ata_queued_cmd
if (qc->tf.protocol == ATA_PROT_NCQ) {
WARN_ON(link->sactive & (1 << qc->tag));
+
+ if (!link->sactive)
+ ap->nr_active_links++;
link->sactive |= 1 << qc->tag;
} else {
WARN_ON(link->sactive);
+
+ ap->nr_active_links++;
link->active_tag = qc->tag;
}
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 3764e21..ffbd028 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -248,6 +248,7 @@ void ata_scsi_error(struct Scsi_Host *ho
}
ap->flags &= ~ATA_FLAG_EH_PENDING;
+ ap->excl_link = NULL; /* don't maintain exclusion over EH */
spin_unlock_irqrestore(hs_lock, flags);
@@ -1873,6 +1874,10 @@ void ata_eh_finish(struct ata_port *ap)
}
}
}
+
+ /* make sure nr_active_links is zero after EH */
+ WARN_ON(ap->nr_active_links);
+ ap->nr_active_links = 0;
}
static void ata_eh_scsi_handle_link_detach(struct ata_link *link)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a26b6a6..df78f3e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -181,6 +181,7 @@ enum {
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
+ ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */
ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
@@ -520,12 +521,14 @@ struct ata_port {
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
unsigned long qc_allocated;
unsigned int qc_active;
+ int nr_active_links; /* #links with active qcs */
struct ata_link link; /* host default link */
struct ata_device __dev1; /* storage for link.device[1] */
int nr_pm_links; /* nr of available PM links */
struct ata_link *pm_link; /* array of PM links */
+ struct ata_link *excl_link; /* for PM qc exclusion */
struct ata_host_stats stats;
struct ata_host_set *host_set;
@@ -931,6 +934,11 @@ static inline int ata_link_max_devices(c
return 1;
}
+static inline int ata_link_active(struct ata_link *link)
+{
+ return ata_tag_valid(link->active_tag) || link->sactive;
+}
+
static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
{
if (ap->nr_pm_links)
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/7] libata-pm-prep: implement ops->qc_defer()
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
` (3 preceding siblings ...)
2006-05-11 16:37 ` [PATCH 3/7] libata-pm-prep: separate out sata_link_hardreset() Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action helpers Tejun Heo
2006-05-11 16:37 ` [PATCH 6/7] libata-pm-prep: implement qc_defer helpers Tejun Heo
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Controllers which support PM have various restrictions on which
combinations of commands are allowed to what number of devices
concurrently. This patch implements ops->qc_defer() which determines
whether a qc can be issued at the moment or should be deferred.
If the function returns ATA_DEFER_LINK, the qc will be deferred until
a qc completes on the link. If ATA_DEFER_PORT, until a qc completes
on any link. The defer types are advisory and in general
ATA_DEFER_LINK can simply be considered as having lower priority than
ATA_DEFER_PORT.
ops->qc_defer() replaces fixed ata_scmd_need_defer(). For standard
NCQ/non-NCQ exclusion, ata_std_qc_defer() is implemented. ahci and
sata_sil24 are converted to use ata_std_qc_defer().
ops->qc_defer() is heavier than the original mechanism because full qc
is prepped before determining to defer it, but various information is
needed to determine defer conditinos and fully translating a qc is the
only way to supply such information in generic manner.
IMHO, this shouldn't cause any noticeable performance issues as
* for most cases deferring occurs rarely (except for NCQ-aware
cmd-switching PM)
* translation itself isn't that expensive
* once deferred, the command won't be repeated until another command
completes which usually is a very long time cpu-wise.
---
drivers/scsi/ahci.c | 1 +
drivers/scsi/libata-core.c | 32 ++++++++++++++++++++++++++++
drivers/scsi/libata-scsi.c | 50 +++++++++++---------------------------------
drivers/scsi/sata_sil24.c | 1 +
include/linux/libata.h | 6 +++++
5 files changed, 52 insertions(+), 38 deletions(-)
6f73e35cbbea07d45cc5fb153d74c273517b5b57
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 526150b..c95309c 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -239,6 +239,7 @@ static const struct ata_port_operations
.tf_read = ahci_tf_read,
+ .qc_defer = ata_std_qc_defer,
.qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue,
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index b9feefb..5dd5a28 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3253,6 +3253,37 @@ int ata_check_atapi_dma(struct ata_queue
return rc;
}
+
+/**
+ * ata_std_qc_defer - Check whether a qc needs to be deferred
+ * @qc: ATA command in question
+ *
+ * Non-NCQ commands cannot run with any other command, NCQ or
+ * not. As upper layer only knows the queue depth, we are
+ * responsible for maintaining exclusion. This function checks
+ * whether a new command @qc can be issued.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
+ * RETURNS:
+ * ATA_DEFER_* if deferring is needed, 0 otherwise.
+ */
+int ata_std_qc_defer(struct ata_queued_cmd *qc)
+{
+ struct ata_link *link = qc->dev->link;
+
+ if (qc->tf.protocol == ATA_PROT_NCQ) {
+ if (!ata_tag_valid(link->active_tag))
+ return 0;
+ } else {
+ if (!ata_tag_valid(link->active_tag) && !link->sactive)
+ return 0;
+ }
+
+ return ATA_DEFER_LINK;
+}
+
/**
* ata_qc_prep - Prepare taskfile for submission
* @qc: Metadata associated with taskfile to be prepared
@@ -5837,6 +5868,7 @@ EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
EXPORT_SYMBOL_GPL(ata_host_stop);
EXPORT_SYMBOL_GPL(ata_interrupt);
+EXPORT_SYMBOL_GPL(ata_std_qc_defer);
EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 021e4a3..9589013 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1339,39 +1339,6 @@ static void ata_scsi_qc_complete(struct
}
/**
- * ata_scmd_need_defer - Check whether we need to defer scmd
- * @dev: ATA device to which the command is addressed
- * @is_io: Is the command IO (and thus possibly NCQ)?
- *
- * NCQ and non-NCQ commands cannot run together. As upper layer
- * only knows the queue depth, we are responsible for maintaining
- * exclusion. This function checks whether a new command can be
- * issued to @dev.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- *
- * RETURNS:
- * 1 if deferring is needed, 0 otherwise.
- */
-static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
-{
- struct ata_link *link = dev->link;
-
- if (!(dev->flags & ATA_DFLAG_NCQ))
- return 0;
-
- if (is_io) {
- if (!ata_tag_valid(link->active_tag))
- return 0;
- } else {
- if (!ata_tag_valid(link->active_tag) && !link->sactive)
- return 0;
- }
- return 1;
-}
-
-/**
* ata_scsi_translate - Translate then issue SCSI command to ATA device
* @dev: ATA device to which the command is addressed
* @cmd: SCSI command to execute
@@ -1402,15 +1369,13 @@ static int ata_scsi_translate(struct ata
void (*done)(struct scsi_cmnd *),
ata_xlat_func_t xlat_func)
{
+ struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
u8 *scsicmd = cmd->cmnd;
- int is_io = xlat_func == ata_scsi_rw_xlat;
+ int rc;
VPRINTK("ENTER\n");
- if (unlikely(ata_scmd_need_defer(dev, is_io)))
- goto defer;
-
qc = ata_scsi_qc_new(dev, cmd, done);
if (!qc)
goto err_mem;
@@ -1438,6 +1403,11 @@ static int ata_scsi_translate(struct ata
if (xlat_func(qc, scsicmd))
goto early_finish;
+ if (ap->ops->qc_defer) {
+ if ((rc = ap->ops->qc_defer(qc)))
+ goto defer;
+ }
+
/* select device, send command to hardware */
ata_qc_issue(qc);
@@ -1459,8 +1429,12 @@ err_mem:
return 0;
defer:
+ ata_qc_free(qc);
DPRINTK("EXIT - defer\n");
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ if (rc == ATA_DEFER_LINK)
+ return SCSI_MLQUEUE_DEVICE_BUSY;
+ else
+ return SCSI_MLQUEUE_HOST_BUSY;
}
/**
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index a952513..e3d13d6 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -380,6 +380,7 @@ static const struct ata_port_operations
.check_altstatus = ata_noop_check_status,
.dev_select = ata_noop_dev_select,
+ .qc_defer = ata_std_qc_defer,
.qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 17a4af4..a26b6a6 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -235,6 +235,10 @@ enum {
ATA_PORT_PRIMARY = (1 << 0),
ATA_PORT_SECONDARY = (1 << 1),
+ /* return values for ->qc_defer */
+ ATA_DEFER_LINK = 1,
+ ATA_DEFER_PORT = 2,
+
/* desc_len for ata_eh_info and context */
ATA_EH_DESC_LEN = 80,
@@ -566,6 +570,7 @@ struct ata_port_operations {
void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc);
+ int (*qc_defer) (struct ata_queued_cmd *qc);
void (*qc_prep) (struct ata_queued_cmd *qc);
unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
@@ -691,6 +696,7 @@ extern int ata_port_start (struct ata_po
extern void ata_port_stop (struct ata_port *ap);
extern void ata_host_stop (struct ata_host_set *host_set);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action helpers
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
` (4 preceding siblings ...)
2006-05-11 16:37 ` [PATCH 5/7] libata-pm-prep: implement ops->qc_defer() Tejun Heo
@ 2006-05-11 16:37 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 6/7] libata-pm-prep: implement qc_defer helpers Tejun Heo
6 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-05-11 16:37 UTC (permalink / raw)
To: jgarzik, alan, axboe, albertcc, forrest.zhao, efalk, linux-ide; +Cc: Tejun Heo
Some PM needs hardreset to resume link. Add ATA_LFLAG_HRST_TO_RESUME
to mark such links and separate out ata_link_resume_action() such that
the test can be done in one place and, while at it, separate out
ata_link_init_probe() which sets resume action and probe mask from
ata_device_add(). These resume/probing related helpers will be used
by PM.
---
drivers/scsi/libata-core.c | 7 +------
drivers/scsi/libata-eh.c | 6 +++---
drivers/scsi/libata-scsi.c | 4 ++--
include/linux/libata.h | 17 +++++++++++++++++
4 files changed, 23 insertions(+), 11 deletions(-)
b23bfeecdddff57fd54e62193ae8b05e88729c63
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index fb64a0f..148d84d 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5472,14 +5472,9 @@ int ata_device_add(const struct ata_prob
ata_port_probe(ap);
spin_lock_irqsave(&ap->host_set->lock, flags);
-
- ap->link.eh_info.probe_mask =
- (1 << ata_link_max_devices(&ap->link)) - 1;
- ap->link.eh_info.action |= ATA_EH_SOFTRESET;
-
set_bit(bit, &ap->flags);
+ ata_link_init_probe(&ap->link);
ata_port_schedule_eh(ap);
-
spin_unlock_irqrestore(&ap->host_set->lock, flags);
wait_on_bit(&ap->flags, bit, ata_boot_probe_wait,
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index ffbd028..d62a529 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -941,7 +941,7 @@ static void ata_eh_analyze_serror(struct
}
if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) {
err_mask |= AC_ERR_ATA_BUS;
- action |= ATA_EH_HARDRESET;
+ action |= ata_link_resume_action(link);
ehc->i.probe_mask |= 1;
}
@@ -1695,7 +1695,7 @@ int ata_eh_recover(struct ata_port *ap,
ata_eh_detach_dev(dev);
ata_dev_init(dev);
ehc->did_probe_mask |= (1 << dev->devno);
- ehc->i.action |= ATA_EH_SOFTRESET;
+ ehc->i.action |= ata_link_resume_action(link);
}
}
}
@@ -1805,7 +1805,7 @@ int ata_eh_recover(struct ata_port *ap,
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
ehc->did_probe_mask |= (1 << dev->devno);
- ehc->i.action |= ATA_EH_SOFTRESET;
+ ehc->i.action |= ata_link_resume_action(link);
}
} else {
/* soft didn't work? be haaaaard */
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 9589013..de40b80 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2903,7 +2903,7 @@ static int ata_scsi_user_scan(struct Scs
ata_port_for_each_link(link, ap) {
link->eh_info.probe_mask |=
(1 << ata_link_max_devices(link)) - 1;
- link->eh_info.action |= ATA_EH_SOFTRESET;
+ link->eh_info.action |= ata_link_resume_action(link);
}
} else {
struct ata_device *dev = ata_find_dev(ap, id);
@@ -2911,7 +2911,7 @@ static int ata_scsi_user_scan(struct Scs
if (dev) {
link = dev->link;
link->eh_info.probe_mask |= 1 << dev->devno;
- link->eh_info.action |= ATA_EH_SOFTRESET;
+ link->eh_info.action |= ata_link_resume_action(link);
} else
rc = -EINVAL;
}
diff --git a/include/linux/libata.h b/include/linux/libata.h
index df78f3e..bbfd176 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -143,6 +143,9 @@ enum {
ATA_DEV_ERING_SIZE = 32, /* record 32 recent errors */
+ /* struct ata_link flags */
+ ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset needed to resume */
+
/* struct ata_port flags */
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
/* (doesn't imply presence) */
@@ -934,6 +937,20 @@ static inline int ata_link_max_devices(c
return 1;
}
+static inline unsigned int ata_link_resume_action(struct ata_link *link)
+{
+ if (link->flags & ATA_LFLAG_HRST_TO_RESUME)
+ return ATA_EH_HARDRESET;
+ return ATA_EH_SOFTRESET;
+}
+
+static inline void ata_link_init_probe(struct ata_link *link)
+{
+ link->eh_info.probe_mask = (1 << ata_link_max_devices(link)) - 1;
+ link->eh_info.action = ata_link_resume_action(link);
+ link->eh_context.i = link->eh_info;
+}
+
static inline int ata_link_active(struct ata_link *link)
{
return ata_tag_valid(link->active_tag) || link->sactive;
--
1.2.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-05-11 16:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-11 16:37 [PATCHSET 10/11] prep for PM support Tejun Heo
2006-05-11 16:37 ` [PATCH 4/7] libata-pm-prep: add @is_cmd to ata_tf_to_fis() Tejun Heo
2006-05-11 16:37 ` [PATCH 1/7] libata-pm-prep: add @new_class to ata_dev_revalidate() Tejun Heo
2006-05-11 16:37 ` [PATCH 2/7] libata-pm-prep: make a number of functions global to libata Tejun Heo
2006-05-11 16:37 ` [PATCH 3/7] libata-pm-prep: separate out sata_link_hardreset() Tejun Heo
2006-05-11 16:37 ` [PATCH 5/7] libata-pm-prep: implement ops->qc_defer() Tejun Heo
2006-05-11 16:37 ` [PATCH 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action helpers Tejun Heo
2006-05-11 16:37 ` [PATCH 6/7] libata-pm-prep: implement qc_defer helpers Tejun Heo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).