Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Can Guo and committed by
Martin K. Petersen
4f6dd2a4 2aee050c

+171 -2
+49
Documentation/ABI/testing/sysfs-driver-ufs
··· 1223 1223 1224 1224 The file is read only. 1225 1225 1226 + What: /sys/bus/platform/drivers/ufshcd/*/power_info/lane 1227 + What: /sys/bus/platform/devices/*.ufs/power_info/lane 1228 + Date: September 2023 1229 + Contact: Can Guo <quic_cang@quicinc.com> 1230 + Description: This file shows how many lanes are enabled on the UFS link, 1231 + i.e., an output 2 means UFS link is operating with 2 lanes. 1232 + 1233 + The file is read only. 1234 + 1235 + What: /sys/bus/platform/drivers/ufshcd/*/power_info/mode 1236 + What: /sys/bus/platform/devices/*.ufs/power_info/mode 1237 + Date: September 2023 1238 + Contact: Can Guo <quic_cang@quicinc.com> 1239 + Description: This file shows the PA power mode of UFS. 1240 + 1241 + The file is read only. 1242 + 1243 + What: /sys/bus/platform/drivers/ufshcd/*/power_info/rate 1244 + What: /sys/bus/platform/devices/*.ufs/power_info/rate 1245 + Date: September 2023 1246 + Contact: Can Guo <quic_cang@quicinc.com> 1247 + Description: This file shows the speed rate of UFS link. 1248 + 1249 + The file is read only. 1250 + 1251 + What: /sys/bus/platform/drivers/ufshcd/*/power_info/gear 1252 + What: /sys/bus/platform/devices/*.ufs/power_info/gear 1253 + Date: September 2023 1254 + Contact: Can Guo <quic_cang@quicinc.com> 1255 + Description: This file shows the gear of UFS link. 1256 + 1257 + The file is read only. 1258 + 1259 + What: /sys/bus/platform/drivers/ufshcd/*/power_info/dev_pm 1260 + What: /sys/bus/platform/devices/*.ufs/power_info/dev_pm 1261 + Date: September 2023 1262 + Contact: Can Guo <quic_cang@quicinc.com> 1263 + Description: This file shows the UFS device power mode. 1264 + 1265 + The file is read only. 1266 + 1267 + What: /sys/bus/platform/drivers/ufshcd/*/power_info/link_state 1268 + What: /sys/bus/platform/devices/*.ufs/power_info/link_state 1269 + Date: September 2023 1270 + Contact: Can Guo <quic_cang@quicinc.com> 1271 + Description: This file shows the state of UFS link. 1272 + 1273 + The file is read only. 1274 + 1226 1275 What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en 1227 1276 What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en 1228 1277 Date: June 2020
+120
drivers/ufs/core/ufs-sysfs.c
··· 7 7 #include <asm/unaligned.h> 8 8 9 9 #include <ufs/ufs.h> 10 + #include <ufs/unipro.h> 10 11 #include "ufs-sysfs.h" 11 12 #include "ufshcd-priv.h" 13 + 14 + static const char *ufs_pa_pwr_mode_to_string(enum ufs_pa_pwr_mode mode) 15 + { 16 + switch (mode) { 17 + case FAST_MODE: return "FAST_MODE"; 18 + case SLOW_MODE: return "SLOW_MODE"; 19 + case FASTAUTO_MODE: return "FASTAUTO_MODE"; 20 + case SLOWAUTO_MODE: return "SLOWAUTO_MODE"; 21 + default: return "UNKNOWN"; 22 + } 23 + } 24 + 25 + static const char *ufs_hs_gear_rate_to_string(enum ufs_hs_gear_rate rate) 26 + { 27 + switch (rate) { 28 + case PA_HS_MODE_A: return "HS_RATE_A"; 29 + case PA_HS_MODE_B: return "HS_RATE_B"; 30 + default: return "UNKNOWN"; 31 + } 32 + } 33 + 34 + static const char *ufs_pwm_gear_to_string(enum ufs_pwm_gear_tag gear) 35 + { 36 + switch (gear) { 37 + case UFS_PWM_G1: return "PWM_GEAR1"; 38 + case UFS_PWM_G2: return "PWM_GEAR2"; 39 + case UFS_PWM_G3: return "PWM_GEAR3"; 40 + case UFS_PWM_G4: return "PWM_GEAR4"; 41 + case UFS_PWM_G5: return "PWM_GEAR5"; 42 + case UFS_PWM_G6: return "PWM_GEAR6"; 43 + case UFS_PWM_G7: return "PWM_GEAR7"; 44 + default: return "UNKNOWN"; 45 + } 46 + } 47 + 48 + static const char *ufs_hs_gear_to_string(enum ufs_hs_gear_tag gear) 49 + { 50 + switch (gear) { 51 + case UFS_HS_G1: return "HS_GEAR1"; 52 + case UFS_HS_G2: return "HS_GEAR2"; 53 + case UFS_HS_G3: return "HS_GEAR3"; 54 + case UFS_HS_G4: return "HS_GEAR4"; 55 + case UFS_HS_G5: return "HS_GEAR5"; 56 + default: return "UNKNOWN"; 57 + } 58 + } 12 59 13 60 static const char *ufshcd_uic_link_state_to_string( 14 61 enum uic_link_state state) ··· 675 628 .attrs = ufs_sysfs_monitor_attrs, 676 629 }; 677 630 631 + static ssize_t lane_show(struct device *dev, struct device_attribute *attr, 632 + char *buf) 633 + { 634 + struct ufs_hba *hba = dev_get_drvdata(dev); 635 + 636 + return sysfs_emit(buf, "%u\n", hba->pwr_info.lane_rx); 637 + } 638 + 639 + static ssize_t mode_show(struct device *dev, struct device_attribute *attr, 640 + char *buf) 641 + { 642 + struct ufs_hba *hba = dev_get_drvdata(dev); 643 + 644 + return sysfs_emit(buf, "%s\n", ufs_pa_pwr_mode_to_string(hba->pwr_info.pwr_rx)); 645 + } 646 + 647 + static ssize_t rate_show(struct device *dev, struct device_attribute *attr, 648 + char *buf) 649 + { 650 + struct ufs_hba *hba = dev_get_drvdata(dev); 651 + 652 + return sysfs_emit(buf, "%s\n", ufs_hs_gear_rate_to_string(hba->pwr_info.hs_rate)); 653 + } 654 + 655 + static ssize_t gear_show(struct device *dev, struct device_attribute *attr, 656 + char *buf) 657 + { 658 + struct ufs_hba *hba = dev_get_drvdata(dev); 659 + 660 + return sysfs_emit(buf, "%s\n", hba->pwr_info.hs_rate ? 661 + ufs_hs_gear_to_string(hba->pwr_info.gear_rx) : 662 + ufs_pwm_gear_to_string(hba->pwr_info.gear_rx)); 663 + } 664 + 665 + static ssize_t dev_pm_show(struct device *dev, struct device_attribute *attr, 666 + char *buf) 667 + { 668 + struct ufs_hba *hba = dev_get_drvdata(dev); 669 + 670 + return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(hba->curr_dev_pwr_mode)); 671 + } 672 + 673 + static ssize_t link_state_show(struct device *dev, 674 + struct device_attribute *attr, char *buf) 675 + { 676 + struct ufs_hba *hba = dev_get_drvdata(dev); 677 + 678 + return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(hba->uic_link_state)); 679 + } 680 + 681 + static DEVICE_ATTR_RO(lane); 682 + static DEVICE_ATTR_RO(mode); 683 + static DEVICE_ATTR_RO(rate); 684 + static DEVICE_ATTR_RO(gear); 685 + static DEVICE_ATTR_RO(dev_pm); 686 + static DEVICE_ATTR_RO(link_state); 687 + 688 + static struct attribute *ufs_power_info_attrs[] = { 689 + &dev_attr_lane.attr, 690 + &dev_attr_mode.attr, 691 + &dev_attr_rate.attr, 692 + &dev_attr_gear.attr, 693 + &dev_attr_dev_pm.attr, 694 + &dev_attr_link_state.attr, 695 + NULL 696 + }; 697 + 698 + static const struct attribute_group ufs_sysfs_power_info_group = { 699 + .name = "power_info", 700 + .attrs = ufs_power_info_attrs, 701 + }; 702 + 678 703 static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba, 679 704 enum desc_idn desc_id, 680 705 u8 desc_index, ··· 1352 1233 &ufs_sysfs_default_group, 1353 1234 &ufs_sysfs_capabilities_group, 1354 1235 &ufs_sysfs_monitor_group, 1236 + &ufs_sysfs_power_info_group, 1355 1237 &ufs_sysfs_device_descriptor_group, 1356 1238 &ufs_sysfs_interconnect_descriptor_group, 1357 1239 &ufs_sysfs_geometry_descriptor_group,
+2 -2
include/ufs/unipro.h
··· 193 193 #define DME_LocalAFC0ReqTimeOutVal 0xD043 194 194 195 195 /* PA power modes */ 196 - enum { 196 + enum ufs_pa_pwr_mode { 197 197 FAST_MODE = 1, 198 198 SLOW_MODE = 2, 199 199 FASTAUTO_MODE = 4, ··· 205 205 #define PWRMODE_RX_OFFSET 4 206 206 207 207 /* PA TX/RX Frequency Series */ 208 - enum { 208 + enum ufs_hs_gear_rate { 209 209 PA_HS_MODE_A = 1, 210 210 PA_HS_MODE_B = 2, 211 211 };