summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/ata_piix.c27
-rw-r--r--drivers/ata/libata-core.c30
-rw-r--r--drivers/ata/libata-eh.c7
-rw-r--r--drivers/ata/libata-sff.c9
-rw-r--r--drivers/ata/libata.h9
-rw-r--r--include/linux/libata.h2
6 files changed, 47 insertions, 37 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index f59a55bfade4..b7c38eeb498f 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -165,8 +165,6 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
#ifdef CONFIG_PM
@@ -319,7 +317,7 @@ static struct ata_port_operations piix_sata_ops = {
static struct ata_port_operations piix_sidpr_sata_ops = {
.inherits = &piix_sata_ops,
- .hardreset = piix_sidpr_hardreset,
+ .hardreset = sata_std_hardreset,
.scr_read = piix_sidpr_scr_read,
.scr_write = piix_sidpr_scr_write,
};
@@ -1015,29 +1013,6 @@ static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
return 0;
}
-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
-{
- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
- int rc;
-
- /* do hardreset */
- rc = sata_link_hardreset(link, timing, deadline, NULL, NULL);
- if (rc) {
- ata_link_printk(link, KERN_ERR,
- "COMRESET failed (errno=%d)\n", rc);
- return rc;
- }
-
- /* TODO: phy layer with polling, timeouts, etc. */
- if (ata_link_offline(link)) {
- *class = ATA_DEV_NONE;
- return 0;
- }
-
- return -EAGAIN;
-}
-
#ifdef CONFIG_PM
static int piix_broken_suspend(void)
{
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b607292b6480..c4fd4afbf349 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -75,7 +75,6 @@ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
const struct ata_port_operations ata_base_port_ops = {
.prereset = ata_std_prereset,
- .hardreset = sata_sff_hardreset,
.postreset = ata_std_postreset,
.error_handler = ata_std_error_handler,
};
@@ -84,6 +83,7 @@ const struct ata_port_operations sata_port_ops = {
.inherits = &ata_base_port_ops,
.qc_defer = ata_std_qc_defer,
+ .hardreset = sata_std_hardreset,
.sff_dev_select = ata_noop_dev_select,
};
@@ -3661,6 +3661,33 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
}
/**
+ * sata_std_hardreset - COMRESET w/o waiting or classification
+ * @link: link to reset
+ * @class: resulting class of attached device
+ * @deadline: deadline jiffies for the operation
+ *
+ * Standard SATA COMRESET w/o waiting or classification.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 if link offline, -EAGAIN if link online, -errno on errors.
+ */
+int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+ bool online;
+ int rc;
+
+ /* do hardreset */
+ rc = sata_link_hardreset(link, timing, deadline, &online, NULL);
+ *class = ATA_DEV_NONE;
+ return online ? -EAGAIN : rc;
+}
+
+/**
* ata_std_postreset - standard postreset callback
* @link: the target ata_link
* @classes: classes of attached devices
@@ -6225,6 +6252,7 @@ EXPORT_SYMBOL_GPL(sata_link_debounce);
EXPORT_SYMBOL_GPL(sata_link_resume);
EXPORT_SYMBOL_GPL(ata_std_prereset);
EXPORT_SYMBOL_GPL(sata_link_hardreset);
+EXPORT_SYMBOL_GPL(sata_std_hardreset);
EXPORT_SYMBOL_GPL(ata_std_postreset);
EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_pair);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index f4f9c2783821..21687bbd9a70 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2857,11 +2857,8 @@ void ata_std_error_handler(struct ata_port *ap)
struct ata_port_operations *ops = ap->ops;
ata_reset_fn_t hardreset = ops->hardreset;
- /* sata_std_hardreset is inherited to all drivers from
- * ata_base_port_ops. Ignore it if SCR access is not
- * available.
- */
- if (hardreset == sata_sff_hardreset && !sata_scr_valid(&ap->link))
+ /* ignore built-in hardreset if SCR access is not available */
+ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
hardreset = NULL;
ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 0b97e84d3af6..f464ca1fa261 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -49,6 +49,7 @@ const struct ata_port_operations ata_sff_port_ops = {
.thaw = ata_sff_thaw,
.prereset = ata_sff_prereset,
.softreset = ata_sff_softreset,
+ .hardreset = sata_sff_hardreset,
.postreset = ata_sff_postreset,
.error_handler = ata_sff_error_handler,
.post_internal_cmd = ata_sff_post_internal_cmd,
@@ -2031,14 +2032,12 @@ void ata_sff_error_handler(struct ata_port *ap)
/* PIO and DMA engines have been stopped, perform recovery */
- /* ata_sff_softreset and sata_sff_hardreset are inherited to
- * all SFF drivers from ata_sff_port_ops. Ignore softreset if
- * ctl isn't accessible. Ignore hardreset if SCR access isn't
- * available.
+ /* Ignore ata_sff_softreset if ctl isn't accessible and
+ * built-in hardresets if SCR access isn't available.
*/
if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
softreset = NULL;
- if (hardreset == sata_sff_hardreset && !sata_scr_valid(&ap->link))
+ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
hardreset = NULL;
ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 08af43e2c081..87f54a1db3b0 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -38,6 +38,15 @@ struct ata_scsi_args {
void (*done)(struct scsi_cmnd *);
};
+static inline int ata_is_builtin_hardreset(ata_reset_fn_t reset)
+{
+ if (reset == sata_std_hardreset)
+ return 1;
+ if (reset == sata_sff_hardreset)
+ return 1;
+ return 0;
+}
+
/* libata-core.c */
enum {
/* flags for ata_dev_read_id() */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d9ebce2bf5e7..c060cd3cba66 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -853,6 +853,8 @@ extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
extern int sata_link_hardreset(struct ata_link *link,
const unsigned long *timing, unsigned long deadline,
bool *online, int (*check_ready)(struct ata_link *));
+extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
extern void ata_port_disable(struct ata_port *);