* [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
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 1/7] libata-pm-prep: add @new_class to ata_dev_revalidate() 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
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 2/7] libata-pm-prep: make a number of functions global to libata 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
` (2 preceding siblings ...)
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 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
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 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 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 4/7] libata-pm-prep: add @is_cmd to ata_tf_to_fis() 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
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 ` Tejun Heo
2006-05-11 16:37 ` [PATCH 3/7] libata-pm-prep: separate out sata_link_hardreset() 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
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
` (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 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action 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
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 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 6/7] libata-pm-prep: implement qc_defer helpers Tejun Heo
2006-05-11 16:37 ` [PATCH 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action 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
` (5 preceding siblings ...)
2006-05-11 16:37 ` [PATCH 6/7] libata-pm-prep: implement qc_defer 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
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 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 1/7] libata-pm-prep: add @new_class to ata_dev_revalidate() 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 5/7] libata-pm-prep: implement ops->qc_defer() Tejun Heo
2006-05-11 16:37 ` [PATCH 6/7] libata-pm-prep: implement qc_defer helpers Tejun Heo
2006-05-11 16:37 ` [PATCH 7/7] libata-pm-prep: add HRST_TO_RESUME and implement resume action helpers Tejun Heo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.