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:
Damien Le Moal 2025-06-18 14:11:24 +09:00
parent 3a382b9b13
commit 0013ddc4cf
1 changed files with 152 additions and 152 deletions

View File

@ -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;
}