Skip to content

Commit 1152b26

Browse files
htejunJeff Garzik
authored andcommitted
libata: implement sata_link_scr_lpm() and make ata_dev_set_feature() global
Link power management is about to be reimplemented. Prepare for it. * Implement sata_link_scr_lpm(). * Drop static from ata_dev_set_feature() and make it available to other libata files. * Trivial whitespace adjustments. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
1 parent c93b263 commit 1152b26

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

drivers/ata/libata-core.c

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ const struct ata_port_operations sata_port_ops = {
9191
static unsigned int ata_dev_init_params(struct ata_device *dev,
9292
u16 heads, u16 sectors);
9393
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
94-
static unsigned int ata_dev_set_feature(struct ata_device *dev,
95-
u8 enable, u8 feature);
9694
static void ata_dev_xfermask(struct ata_device *dev);
9795
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
9896

@@ -3628,7 +3626,7 @@ int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
36283626
* @params: timing parameters { interval, duratinon, timeout } in msec
36293627
* @deadline: deadline jiffies for the operation
36303628
*
3631-
* Make sure SStatus of @link reaches stable state, determined by
3629+
* Make sure SStatus of @link reaches stable state, determined by
36323630
* holding the same value where DET is not 1 for @duration polled
36333631
* every @interval, before @timeout. Timeout constraints the
36343632
* beginning of the stable state. Because DET gets stuck at 1 on
@@ -3759,6 +3757,72 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
37593757
return rc != -EINVAL ? rc : 0;
37603758
}
37613759

3760+
/**
3761+
* sata_link_scr_lpm - manipulate SControl IPM and SPM fields
3762+
* @link: ATA link to manipulate SControl for
3763+
* @policy: LPM policy to configure
3764+
* @spm_wakeup: initiate LPM transition to active state
3765+
*
3766+
* Manipulate the IPM field of the SControl register of @link
3767+
* according to @policy. If @policy is ATA_LPM_MAX_POWER and
3768+
* @spm_wakeup is %true, the SPM field is manipulated to wake up
3769+
* the link. This function also clears PHYRDY_CHG before
3770+
* returning.
3771+
*
3772+
* LOCKING:
3773+
* EH context.
3774+
*
3775+
* RETURNS:
3776+
* 0 on succes, -errno otherwise.
3777+
*/
3778+
int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
3779+
bool spm_wakeup)
3780+
{
3781+
struct ata_eh_context *ehc = &link->eh_context;
3782+
bool woken_up = false;
3783+
u32 scontrol;
3784+
int rc;
3785+
3786+
rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
3787+
if (rc)
3788+
return rc;
3789+
3790+
switch (policy) {
3791+
case ATA_LPM_MAX_POWER:
3792+
/* disable all LPM transitions */
3793+
scontrol |= (0x3 << 8);
3794+
/* initiate transition to active state */
3795+
if (spm_wakeup) {
3796+
scontrol |= (0x4 << 12);
3797+
woken_up = true;
3798+
}
3799+
break;
3800+
case ATA_LPM_MED_POWER:
3801+
/* allow LPM to PARTIAL */
3802+
scontrol &= ~(0x1 << 8);
3803+
scontrol |= (0x2 << 8);
3804+
break;
3805+
case ATA_LPM_MIN_POWER:
3806+
/* no restrictions on LPM transitions */
3807+
scontrol &= ~(0x3 << 8);
3808+
break;
3809+
default:
3810+
WARN_ON(1);
3811+
}
3812+
3813+
rc = sata_scr_write(link, SCR_CONTROL, scontrol);
3814+
if (rc)
3815+
return rc;
3816+
3817+
/* give the link time to transit out of LPM state */
3818+
if (woken_up)
3819+
msleep(10);
3820+
3821+
/* clear PHYRDY_CHG from SError */
3822+
ehc->i.serror &= ~SERR_PHYRDY_CHG;
3823+
return sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
3824+
}
3825+
37623826
/**
37633827
* ata_std_prereset - prepare for reset
37643828
* @link: ATA link to be reset
@@ -4551,6 +4615,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
45514615
DPRINTK("EXIT, err_mask=%x\n", err_mask);
45524616
return err_mask;
45534617
}
4618+
45544619
/**
45554620
* ata_dev_set_feature - Issue SET FEATURES - SATA FEATURES
45564621
* @dev: Device to which command will be sent
@@ -4566,8 +4631,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
45664631
* RETURNS:
45674632
* 0 on success, AC_ERR_* mask otherwise.
45684633
*/
4569-
static unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable,
4570-
u8 feature)
4634+
unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)
45714635
{
45724636
struct ata_taskfile tf;
45734637
unsigned int err_mask;
@@ -6732,6 +6796,7 @@ EXPORT_SYMBOL_GPL(sata_set_spd);
67326796
EXPORT_SYMBOL_GPL(ata_wait_after_reset);
67336797
EXPORT_SYMBOL_GPL(sata_link_debounce);
67346798
EXPORT_SYMBOL_GPL(sata_link_resume);
6799+
EXPORT_SYMBOL_GPL(sata_link_scr_lpm);
67356800
EXPORT_SYMBOL_GPL(ata_std_prereset);
67366801
EXPORT_SYMBOL_GPL(sata_link_hardreset);
67376802
EXPORT_SYMBOL_GPL(sata_std_hardreset);

drivers/ata/libata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
8686
extern int ata_dev_configure(struct ata_device *dev);
8787
extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
8888
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
89+
extern unsigned int ata_dev_set_feature(struct ata_device *dev,
90+
u8 enable, u8 feature);
8991
extern void ata_sg_clean(struct ata_queued_cmd *qc);
9092
extern void ata_qc_free(struct ata_queued_cmd *qc);
9193
extern void ata_qc_issue(struct ata_queued_cmd *qc);

include/linux/libata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,8 @@ extern int sata_link_debounce(struct ata_link *link,
952952
const unsigned long *params, unsigned long deadline);
953953
extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
954954
unsigned long deadline);
955+
extern int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
956+
bool spm_wakeup);
955957
extern int sata_link_hardreset(struct ata_link *link,
956958
const unsigned long *timing, unsigned long deadline,
957959
bool *online, int (*check_ready)(struct ata_link *));

0 commit comments

Comments
 (0)