ata: libata-eh: Move and rename ata_eh_set_lpm()
Move the definition of the function ata_eh_set_lpm() to avoid its unnecessary forward declaration and rename the function to ata_eh_link_set_lpm() to clarify that it acts on a link. No functional changes. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Niklas Cassel <cassel@kernel.org>
This commit is contained in:
parent
3a382b9b13
commit
0013ddc4cf
|
|
@ -153,8 +153,6 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
|
|||
#undef CMDS
|
||||
|
||||
static void __ata_port_freeze(struct ata_port *ap);
|
||||
static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
|
||||
struct ata_device **r_failed_dev);
|
||||
#ifdef CONFIG_PM
|
||||
static void ata_eh_handle_port_suspend(struct ata_port *ap);
|
||||
static void ata_eh_handle_port_resume(struct ata_port *ap);
|
||||
|
|
@ -2073,6 +2071,154 @@ out:
|
|||
ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_eh_link_set_lpm - configure SATA interface power management
|
||||
* @link: link to configure
|
||||
* @policy: the link power management policy
|
||||
* @r_failed_dev: out parameter for failed device
|
||||
*
|
||||
* Enable SATA Interface power management. This will enable
|
||||
* Device Interface Power Management (DIPM) for min_power and
|
||||
* medium_power_with_dipm policies, and then call driver specific
|
||||
* callbacks for enabling Host Initiated Power management.
|
||||
*
|
||||
* LOCKING:
|
||||
* EH context.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno on failure.
|
||||
*/
|
||||
static int ata_eh_link_set_lpm(struct ata_link *link,
|
||||
enum ata_lpm_policy policy,
|
||||
struct ata_device **r_failed_dev)
|
||||
{
|
||||
struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
|
||||
enum ata_lpm_policy old_policy = link->lpm_policy;
|
||||
bool host_has_dipm = !(link->ap->flags & ATA_FLAG_NO_DIPM);
|
||||
unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
|
||||
unsigned int err_mask;
|
||||
int rc;
|
||||
|
||||
/* if the link or host doesn't do LPM, noop */
|
||||
if (!IS_ENABLED(CONFIG_SATA_HOST) ||
|
||||
(link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This function currently assumes that it will never be supplied policy
|
||||
* ATA_LPM_UNKNOWN.
|
||||
*/
|
||||
if (WARN_ON_ONCE(policy == ATA_LPM_UNKNOWN))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* DIPM is enabled only for ATA_LPM_MIN_POWER,
|
||||
* ATA_LPM_MIN_POWER_WITH_PARTIAL, and ATA_LPM_MED_POWER_WITH_DIPM, as
|
||||
* some devices misbehave when the host NACKs transition to SLUMBER.
|
||||
*/
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
bool dev_has_hipm = ata_id_has_hipm(dev->id);
|
||||
bool dev_has_dipm = ata_id_has_dipm(dev->id);
|
||||
|
||||
/* find the first enabled and LPM enabled devices */
|
||||
if (!link_dev)
|
||||
link_dev = dev;
|
||||
|
||||
if (!lpm_dev &&
|
||||
(dev_has_hipm || (dev_has_dipm && host_has_dipm)))
|
||||
lpm_dev = dev;
|
||||
|
||||
hints &= ~ATA_LPM_EMPTY;
|
||||
if (!dev_has_hipm)
|
||||
hints &= ~ATA_LPM_HIPM;
|
||||
|
||||
/* disable DIPM before changing link config */
|
||||
if (dev_has_dipm) {
|
||||
err_mask = ata_dev_set_feature(dev,
|
||||
SETFEATURES_SATA_DISABLE, SATA_DIPM);
|
||||
if (err_mask && err_mask != AC_ERR_DEV) {
|
||||
ata_dev_warn(dev,
|
||||
"failed to disable DIPM, Emask 0x%x\n",
|
||||
err_mask);
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ap) {
|
||||
rc = ap->ops->set_lpm(link, policy, hints);
|
||||
if (!rc && ap->slave_link)
|
||||
rc = ap->ops->set_lpm(ap->slave_link, policy, hints);
|
||||
} else
|
||||
rc = sata_pmp_set_lpm(link, policy, hints);
|
||||
|
||||
/*
|
||||
* Attribute link config failure to the first (LPM) enabled
|
||||
* device on the link.
|
||||
*/
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
link->flags |= ATA_LFLAG_NO_LPM;
|
||||
return 0;
|
||||
}
|
||||
dev = lpm_dev ? lpm_dev : link_dev;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low level driver acked the transition. Issue DIPM command
|
||||
* with the new policy set.
|
||||
*/
|
||||
link->lpm_policy = policy;
|
||||
if (ap && ap->slave_link)
|
||||
ap->slave_link->lpm_policy = policy;
|
||||
|
||||
/*
|
||||
* Host config updated, enable DIPM if transitioning to
|
||||
* ATA_LPM_MIN_POWER, ATA_LPM_MIN_POWER_WITH_PARTIAL, or
|
||||
* ATA_LPM_MED_POWER_WITH_DIPM.
|
||||
*/
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
bool dev_has_dipm = ata_id_has_dipm(dev->id);
|
||||
|
||||
if (policy >= ATA_LPM_MED_POWER_WITH_DIPM && host_has_dipm &&
|
||||
dev_has_dipm) {
|
||||
err_mask = ata_dev_set_feature(dev,
|
||||
SETFEATURES_SATA_ENABLE, SATA_DIPM);
|
||||
if (err_mask && err_mask != AC_ERR_DEV) {
|
||||
ata_dev_warn(dev,
|
||||
"failed to enable DIPM, Emask 0x%x\n",
|
||||
err_mask);
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
link->last_lpm_change = jiffies;
|
||||
link->flags |= ATA_LFLAG_CHANGED;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/* restore the old policy */
|
||||
link->lpm_policy = old_policy;
|
||||
if (ap && ap->slave_link)
|
||||
ap->slave_link->lpm_policy = old_policy;
|
||||
|
||||
/* if no device or only one more chance is left, disable LPM */
|
||||
if (!dev || ehc->tries[dev->devno] <= 2) {
|
||||
ata_link_warn(link, "disabling LPM on the link\n");
|
||||
link->flags |= ATA_LFLAG_NO_LPM;
|
||||
}
|
||||
if (r_failed_dev)
|
||||
*r_failed_dev = dev;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_eh_link_autopsy - analyze error and determine recovery action
|
||||
* @link: host link to perform autopsy on
|
||||
|
|
@ -3123,8 +3269,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
|
|||
* to ap->target_lpm_policy after revalidation is done.
|
||||
*/
|
||||
if (link->lpm_policy > ATA_LPM_MAX_POWER) {
|
||||
rc = ata_eh_set_lpm(link, ATA_LPM_MAX_POWER,
|
||||
r_failed_dev);
|
||||
rc = ata_eh_link_set_lpm(link, ATA_LPM_MAX_POWER,
|
||||
r_failed_dev);
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -3408,153 +3554,6 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_eh_set_lpm - configure SATA interface power management
|
||||
* @link: link to configure power management
|
||||
* @policy: the link power management policy
|
||||
* @r_failed_dev: out parameter for failed device
|
||||
*
|
||||
* Enable SATA Interface power management. This will enable
|
||||
* Device Interface Power Management (DIPM) for min_power and
|
||||
* medium_power_with_dipm policies, and then call driver specific
|
||||
* callbacks for enabling Host Initiated Power management.
|
||||
*
|
||||
* LOCKING:
|
||||
* EH context.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno on failure.
|
||||
*/
|
||||
static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
|
||||
struct ata_device **r_failed_dev)
|
||||
{
|
||||
struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
|
||||
enum ata_lpm_policy old_policy = link->lpm_policy;
|
||||
bool host_has_dipm = !(link->ap->flags & ATA_FLAG_NO_DIPM);
|
||||
unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
|
||||
unsigned int err_mask;
|
||||
int rc;
|
||||
|
||||
/* if the link or host doesn't do LPM, noop */
|
||||
if (!IS_ENABLED(CONFIG_SATA_HOST) ||
|
||||
(link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This function currently assumes that it will never be supplied policy
|
||||
* ATA_LPM_UNKNOWN.
|
||||
*/
|
||||
if (WARN_ON_ONCE(policy == ATA_LPM_UNKNOWN))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* DIPM is enabled only for ATA_LPM_MIN_POWER,
|
||||
* ATA_LPM_MIN_POWER_WITH_PARTIAL, and ATA_LPM_MED_POWER_WITH_DIPM, as
|
||||
* some devices misbehave when the host NACKs transition to SLUMBER.
|
||||
*/
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
bool dev_has_hipm = ata_id_has_hipm(dev->id);
|
||||
bool dev_has_dipm = ata_id_has_dipm(dev->id);
|
||||
|
||||
/* find the first enabled and LPM enabled devices */
|
||||
if (!link_dev)
|
||||
link_dev = dev;
|
||||
|
||||
if (!lpm_dev &&
|
||||
(dev_has_hipm || (dev_has_dipm && host_has_dipm)))
|
||||
lpm_dev = dev;
|
||||
|
||||
hints &= ~ATA_LPM_EMPTY;
|
||||
if (!dev_has_hipm)
|
||||
hints &= ~ATA_LPM_HIPM;
|
||||
|
||||
/* disable DIPM before changing link config */
|
||||
if (dev_has_dipm) {
|
||||
err_mask = ata_dev_set_feature(dev,
|
||||
SETFEATURES_SATA_DISABLE, SATA_DIPM);
|
||||
if (err_mask && err_mask != AC_ERR_DEV) {
|
||||
ata_dev_warn(dev,
|
||||
"failed to disable DIPM, Emask 0x%x\n",
|
||||
err_mask);
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ap) {
|
||||
rc = ap->ops->set_lpm(link, policy, hints);
|
||||
if (!rc && ap->slave_link)
|
||||
rc = ap->ops->set_lpm(ap->slave_link, policy, hints);
|
||||
} else
|
||||
rc = sata_pmp_set_lpm(link, policy, hints);
|
||||
|
||||
/*
|
||||
* Attribute link config failure to the first (LPM) enabled
|
||||
* device on the link.
|
||||
*/
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
link->flags |= ATA_LFLAG_NO_LPM;
|
||||
return 0;
|
||||
}
|
||||
dev = lpm_dev ? lpm_dev : link_dev;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low level driver acked the transition. Issue DIPM command
|
||||
* with the new policy set.
|
||||
*/
|
||||
link->lpm_policy = policy;
|
||||
if (ap && ap->slave_link)
|
||||
ap->slave_link->lpm_policy = policy;
|
||||
|
||||
/*
|
||||
* Host config updated, enable DIPM if transitioning to
|
||||
* ATA_LPM_MIN_POWER, ATA_LPM_MIN_POWER_WITH_PARTIAL, or
|
||||
* ATA_LPM_MED_POWER_WITH_DIPM.
|
||||
*/
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
bool dev_has_dipm = ata_id_has_dipm(dev->id);
|
||||
|
||||
if (policy >= ATA_LPM_MED_POWER_WITH_DIPM && host_has_dipm &&
|
||||
dev_has_dipm) {
|
||||
err_mask = ata_dev_set_feature(dev,
|
||||
SETFEATURES_SATA_ENABLE, SATA_DIPM);
|
||||
if (err_mask && err_mask != AC_ERR_DEV) {
|
||||
ata_dev_warn(dev,
|
||||
"failed to enable DIPM, Emask 0x%x\n",
|
||||
err_mask);
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
link->last_lpm_change = jiffies;
|
||||
link->flags |= ATA_LFLAG_CHANGED;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/* restore the old policy */
|
||||
link->lpm_policy = old_policy;
|
||||
if (ap && ap->slave_link)
|
||||
ap->slave_link->lpm_policy = old_policy;
|
||||
|
||||
/* if no device or only one more chance is left, disable LPM */
|
||||
if (!dev || ehc->tries[dev->devno] <= 2) {
|
||||
ata_link_warn(link, "disabling LPM on the link\n");
|
||||
link->flags |= ATA_LFLAG_NO_LPM;
|
||||
}
|
||||
if (r_failed_dev)
|
||||
*r_failed_dev = dev;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ata_link_nr_enabled(struct ata_link *link)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
|
|
@ -3943,7 +3942,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
|||
config_lpm:
|
||||
/* configure link power saving */
|
||||
if (link->lpm_policy != ap->target_lpm_policy) {
|
||||
rc = ata_eh_set_lpm(link, ap->target_lpm_policy, &dev);
|
||||
rc = ata_eh_link_set_lpm(link, ap->target_lpm_policy,
|
||||
&dev);
|
||||
if (rc)
|
||||
goto rest_fail;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue