scsi: ufs: ufs-sysfs: Expose UFS power info

Having UFS power info available in sysfs makes it easier to tell the state
of the link during runtime considering we have a bunch of power saving
features and various combinations for backward compatibility.

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Bean Huo <beanhuo@micron.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Can Guo <quic_cang@quicinc.com>
Link: https://lore.kernel.org/r/1698890324-7374-1-git-send-email-quic_cang@quicinc.com
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Can Guo 2023-11-01 18:58:36 -07:00 committed by Martin K. Petersen
parent 2aee050cef
commit 4f6dd2a4bf
3 changed files with 171 additions and 2 deletions

View File

@ -1223,6 +1223,55 @@ Description: This file shows the total latency (in micro seconds) of write
The file is read only. The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/power_info/lane
What: /sys/bus/platform/devices/*.ufs/power_info/lane
Date: September 2023
Contact: Can Guo <quic_cang@quicinc.com>
Description: This file shows how many lanes are enabled on the UFS link,
i.e., an output 2 means UFS link is operating with 2 lanes.
The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/power_info/mode
What: /sys/bus/platform/devices/*.ufs/power_info/mode
Date: September 2023
Contact: Can Guo <quic_cang@quicinc.com>
Description: This file shows the PA power mode of UFS.
The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/power_info/rate
What: /sys/bus/platform/devices/*.ufs/power_info/rate
Date: September 2023
Contact: Can Guo <quic_cang@quicinc.com>
Description: This file shows the speed rate of UFS link.
The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/power_info/gear
What: /sys/bus/platform/devices/*.ufs/power_info/gear
Date: September 2023
Contact: Can Guo <quic_cang@quicinc.com>
Description: This file shows the gear of UFS link.
The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/power_info/dev_pm
What: /sys/bus/platform/devices/*.ufs/power_info/dev_pm
Date: September 2023
Contact: Can Guo <quic_cang@quicinc.com>
Description: This file shows the UFS device power mode.
The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/power_info/link_state
What: /sys/bus/platform/devices/*.ufs/power_info/link_state
Date: September 2023
Contact: Can Guo <quic_cang@quicinc.com>
Description: This file shows the state of UFS link.
The file is read only.
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en
What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en
Date: June 2020 Date: June 2020

View File

@ -7,9 +7,56 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <ufs/ufs.h> #include <ufs/ufs.h>
#include <ufs/unipro.h>
#include "ufs-sysfs.h" #include "ufs-sysfs.h"
#include "ufshcd-priv.h" #include "ufshcd-priv.h"
static const char *ufs_pa_pwr_mode_to_string(enum ufs_pa_pwr_mode mode)
{
switch (mode) {
case FAST_MODE: return "FAST_MODE";
case SLOW_MODE: return "SLOW_MODE";
case FASTAUTO_MODE: return "FASTAUTO_MODE";
case SLOWAUTO_MODE: return "SLOWAUTO_MODE";
default: return "UNKNOWN";
}
}
static const char *ufs_hs_gear_rate_to_string(enum ufs_hs_gear_rate rate)
{
switch (rate) {
case PA_HS_MODE_A: return "HS_RATE_A";
case PA_HS_MODE_B: return "HS_RATE_B";
default: return "UNKNOWN";
}
}
static const char *ufs_pwm_gear_to_string(enum ufs_pwm_gear_tag gear)
{
switch (gear) {
case UFS_PWM_G1: return "PWM_GEAR1";
case UFS_PWM_G2: return "PWM_GEAR2";
case UFS_PWM_G3: return "PWM_GEAR3";
case UFS_PWM_G4: return "PWM_GEAR4";
case UFS_PWM_G5: return "PWM_GEAR5";
case UFS_PWM_G6: return "PWM_GEAR6";
case UFS_PWM_G7: return "PWM_GEAR7";
default: return "UNKNOWN";
}
}
static const char *ufs_hs_gear_to_string(enum ufs_hs_gear_tag gear)
{
switch (gear) {
case UFS_HS_G1: return "HS_GEAR1";
case UFS_HS_G2: return "HS_GEAR2";
case UFS_HS_G3: return "HS_GEAR3";
case UFS_HS_G4: return "HS_GEAR4";
case UFS_HS_G5: return "HS_GEAR5";
default: return "UNKNOWN";
}
}
static const char *ufshcd_uic_link_state_to_string( static const char *ufshcd_uic_link_state_to_string(
enum uic_link_state state) enum uic_link_state state)
{ {
@ -628,6 +675,78 @@ static const struct attribute_group ufs_sysfs_monitor_group = {
.attrs = ufs_sysfs_monitor_attrs, .attrs = ufs_sysfs_monitor_attrs,
}; };
static ssize_t lane_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
return sysfs_emit(buf, "%u\n", hba->pwr_info.lane_rx);
}
static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
return sysfs_emit(buf, "%s\n", ufs_pa_pwr_mode_to_string(hba->pwr_info.pwr_rx));
}
static ssize_t rate_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
return sysfs_emit(buf, "%s\n", ufs_hs_gear_rate_to_string(hba->pwr_info.hs_rate));
}
static ssize_t gear_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
return sysfs_emit(buf, "%s\n", hba->pwr_info.hs_rate ?
ufs_hs_gear_to_string(hba->pwr_info.gear_rx) :
ufs_pwm_gear_to_string(hba->pwr_info.gear_rx));
}
static ssize_t dev_pm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(hba->curr_dev_pwr_mode));
}
static ssize_t link_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(hba->uic_link_state));
}
static DEVICE_ATTR_RO(lane);
static DEVICE_ATTR_RO(mode);
static DEVICE_ATTR_RO(rate);
static DEVICE_ATTR_RO(gear);
static DEVICE_ATTR_RO(dev_pm);
static DEVICE_ATTR_RO(link_state);
static struct attribute *ufs_power_info_attrs[] = {
&dev_attr_lane.attr,
&dev_attr_mode.attr,
&dev_attr_rate.attr,
&dev_attr_gear.attr,
&dev_attr_dev_pm.attr,
&dev_attr_link_state.attr,
NULL
};
static const struct attribute_group ufs_sysfs_power_info_group = {
.name = "power_info",
.attrs = ufs_power_info_attrs,
};
static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba, static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
enum desc_idn desc_id, enum desc_idn desc_id,
u8 desc_index, u8 desc_index,
@ -1233,6 +1352,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_default_group, &ufs_sysfs_default_group,
&ufs_sysfs_capabilities_group, &ufs_sysfs_capabilities_group,
&ufs_sysfs_monitor_group, &ufs_sysfs_monitor_group,
&ufs_sysfs_power_info_group,
&ufs_sysfs_device_descriptor_group, &ufs_sysfs_device_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group, &ufs_sysfs_interconnect_descriptor_group,
&ufs_sysfs_geometry_descriptor_group, &ufs_sysfs_geometry_descriptor_group,

View File

@ -193,7 +193,7 @@
#define DME_LocalAFC0ReqTimeOutVal 0xD043 #define DME_LocalAFC0ReqTimeOutVal 0xD043
/* PA power modes */ /* PA power modes */
enum { enum ufs_pa_pwr_mode {
FAST_MODE = 1, FAST_MODE = 1,
SLOW_MODE = 2, SLOW_MODE = 2,
FASTAUTO_MODE = 4, FASTAUTO_MODE = 4,
@ -205,7 +205,7 @@ enum {
#define PWRMODE_RX_OFFSET 4 #define PWRMODE_RX_OFFSET 4
/* PA TX/RX Frequency Series */ /* PA TX/RX Frequency Series */
enum { enum ufs_hs_gear_rate {
PA_HS_MODE_A = 1, PA_HS_MODE_A = 1,
PA_HS_MODE_B = 2, PA_HS_MODE_B = 2,
}; };