libata: implement and use sata_std_hardreset()
Implement sata_std_hardreset(), which simply wraps around sata_link_hardreset(). sata_std_hardreset() becomes new standard hardreset method for sata_port_ops and sata_sff_hardreset() moves from ata_base_port_ops to ata_sff_port_ops, which is where it really belongs. ata_is_builtin_hardreset() is added so that both ata_std_error_handler() and ata_sff_error_handler() skip both builtin hardresets if SCR isn't accessible. piix_sidpr_hardreset() in ata_piix.c is identical to sata_std_hardreset() in functionality and got replaced with the standard function. Signed-off-by: Tejun Heo <htejun@gmail.com>
This commit is contained in:
Родитель
9dadd45b24
Коммит
57c9efdfb3
|
@ -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 void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
|
||||||
static int ich_pata_cable_detect(struct ata_port *ap);
|
static int ich_pata_cable_detect(struct ata_port *ap);
|
||||||
static u8 piix_vmw_bmdma_status(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_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);
|
static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
@ -319,7 +317,7 @@ static struct ata_port_operations piix_sata_ops = {
|
||||||
|
|
||||||
static struct ata_port_operations piix_sidpr_sata_ops = {
|
static struct ata_port_operations piix_sidpr_sata_ops = {
|
||||||
.inherits = &piix_sata_ops,
|
.inherits = &piix_sata_ops,
|
||||||
.hardreset = piix_sidpr_hardreset,
|
.hardreset = sata_std_hardreset,
|
||||||
.scr_read = piix_sidpr_scr_read,
|
.scr_read = piix_sidpr_scr_read,
|
||||||
.scr_write = piix_sidpr_scr_write,
|
.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;
|
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
|
#ifdef CONFIG_PM
|
||||||
static int piix_broken_suspend(void)
|
static int piix_broken_suspend(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,7 +75,6 @@ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
|
||||||
|
|
||||||
const struct ata_port_operations ata_base_port_ops = {
|
const struct ata_port_operations ata_base_port_ops = {
|
||||||
.prereset = ata_std_prereset,
|
.prereset = ata_std_prereset,
|
||||||
.hardreset = sata_sff_hardreset,
|
|
||||||
.postreset = ata_std_postreset,
|
.postreset = ata_std_postreset,
|
||||||
.error_handler = ata_std_error_handler,
|
.error_handler = ata_std_error_handler,
|
||||||
};
|
};
|
||||||
|
@ -84,6 +83,7 @@ const struct ata_port_operations sata_port_ops = {
|
||||||
.inherits = &ata_base_port_ops,
|
.inherits = &ata_base_port_ops,
|
||||||
|
|
||||||
.qc_defer = ata_std_qc_defer,
|
.qc_defer = ata_std_qc_defer,
|
||||||
|
.hardreset = sata_std_hardreset,
|
||||||
.sff_dev_select = ata_noop_dev_select,
|
.sff_dev_select = ata_noop_dev_select,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3660,6 +3660,33 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* ata_std_postreset - standard postreset callback
|
||||||
* @link: the target ata_link
|
* @link: the target ata_link
|
||||||
|
@ -6225,6 +6252,7 @@ EXPORT_SYMBOL_GPL(sata_link_debounce);
|
||||||
EXPORT_SYMBOL_GPL(sata_link_resume);
|
EXPORT_SYMBOL_GPL(sata_link_resume);
|
||||||
EXPORT_SYMBOL_GPL(ata_std_prereset);
|
EXPORT_SYMBOL_GPL(ata_std_prereset);
|
||||||
EXPORT_SYMBOL_GPL(sata_link_hardreset);
|
EXPORT_SYMBOL_GPL(sata_link_hardreset);
|
||||||
|
EXPORT_SYMBOL_GPL(sata_std_hardreset);
|
||||||
EXPORT_SYMBOL_GPL(ata_std_postreset);
|
EXPORT_SYMBOL_GPL(ata_std_postreset);
|
||||||
EXPORT_SYMBOL_GPL(ata_dev_classify);
|
EXPORT_SYMBOL_GPL(ata_dev_classify);
|
||||||
EXPORT_SYMBOL_GPL(ata_dev_pair);
|
EXPORT_SYMBOL_GPL(ata_dev_pair);
|
||||||
|
|
|
@ -2857,11 +2857,8 @@ void ata_std_error_handler(struct ata_port *ap)
|
||||||
struct ata_port_operations *ops = ap->ops;
|
struct ata_port_operations *ops = ap->ops;
|
||||||
ata_reset_fn_t hardreset = ops->hardreset;
|
ata_reset_fn_t hardreset = ops->hardreset;
|
||||||
|
|
||||||
/* sata_std_hardreset is inherited to all drivers from
|
/* ignore built-in hardreset if SCR access is not available */
|
||||||
* ata_base_port_ops. Ignore it if SCR access is not
|
if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
if (hardreset == sata_sff_hardreset && !sata_scr_valid(&ap->link))
|
|
||||||
hardreset = NULL;
|
hardreset = NULL;
|
||||||
|
|
||||||
ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
|
ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
|
||||||
|
|
|
@ -49,6 +49,7 @@ const struct ata_port_operations ata_sff_port_ops = {
|
||||||
.thaw = ata_sff_thaw,
|
.thaw = ata_sff_thaw,
|
||||||
.prereset = ata_sff_prereset,
|
.prereset = ata_sff_prereset,
|
||||||
.softreset = ata_sff_softreset,
|
.softreset = ata_sff_softreset,
|
||||||
|
.hardreset = sata_sff_hardreset,
|
||||||
.postreset = ata_sff_postreset,
|
.postreset = ata_sff_postreset,
|
||||||
.error_handler = ata_sff_error_handler,
|
.error_handler = ata_sff_error_handler,
|
||||||
.post_internal_cmd = ata_sff_post_internal_cmd,
|
.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 */
|
/* PIO and DMA engines have been stopped, perform recovery */
|
||||||
|
|
||||||
/* ata_sff_softreset and sata_sff_hardreset are inherited to
|
/* Ignore ata_sff_softreset if ctl isn't accessible and
|
||||||
* all SFF drivers from ata_sff_port_ops. Ignore softreset if
|
* built-in hardresets if SCR access isn't available.
|
||||||
* ctl isn't accessible. Ignore hardreset if SCR access isn't
|
|
||||||
* available.
|
|
||||||
*/
|
*/
|
||||||
if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
|
if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
|
||||||
softreset = NULL;
|
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;
|
hardreset = NULL;
|
||||||
|
|
||||||
ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
|
ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
|
||||||
|
|
|
@ -38,6 +38,15 @@ struct ata_scsi_args {
|
||||||
void (*done)(struct scsi_cmnd *);
|
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 */
|
/* libata-core.c */
|
||||||
enum {
|
enum {
|
||||||
/* flags for ata_dev_read_id() */
|
/* flags for ata_dev_read_id() */
|
||||||
|
|
|
@ -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,
|
extern int sata_link_hardreset(struct ata_link *link,
|
||||||
const unsigned long *timing, unsigned long deadline,
|
const unsigned long *timing, unsigned long deadline,
|
||||||
bool *online, int (*check_ready)(struct ata_link *));
|
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_std_postreset(struct ata_link *link, unsigned int *classes);
|
||||||
extern void ata_port_disable(struct ata_port *);
|
extern void ata_port_disable(struct ata_port *);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче