diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-09-19 11:28:51 +0200 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-09-19 11:28:51 +0200 |
| commit | a1d1eb2f57501b2e7e2076ce89b3f3a666ddbfdd (patch) | |
| tree | 375d5bd69b2fc2610648b649eff32aa6582af4e2 /drivers/ufs/core/ufs-sysfs.c | |
| parent | 726e2d0cf2bbc14e3bf38491cddda1a56fe18663 (diff) | |
| parent | cff06a799dbe81f3a697ae7c805eaf88d30c2308 (diff) | |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"Updates to the usual drivers (ufs, smartpqi, NCR5380, mac_scsi, lpfc,
mpi3mr).
There are no user visible core changes and a whole series of minor
updates and fixes. The largest core change is probably the
simplification of the workqueue allocation path"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (86 commits)
scsi: smartpqi: update driver version to 2.1.30-031
scsi: smartpqi: fix volume size updates
scsi: smartpqi: fix rare system hang during LUN reset
scsi: smartpqi: add new controller PCI IDs
scsi: smartpqi: add counter for parity write stream requests
scsi: smartpqi: correct stream detection
scsi: smartpqi: Add fw log to kdump
scsi: bnx2fc: Remove some unused fields in struct bnx2fc_rport
scsi: qla2xxx: Remove the unused 'del_list_entry' field in struct fc_port
scsi: ufs: core: Remove ufshcd_urgent_bkops()
scsi: core: Remove obsoleted declaration for scsi_driverbyte_string()
scsi: bnx2i: Remove unused declarations
scsi: core: Simplify an alloc_workqueue() invocation
scsi: ufs: Simplify alloc*_workqueue() invocation
scsi: stex: Simplify an alloc_ordered_workqueue() invocation
scsi: scsi_transport_fc: Simplify alloc_workqueue() invocations
scsi: snic: Simplify alloc_workqueue() invocations
scsi: qedi: Simplify an alloc_workqueue() invocation
scsi: qedf: Simplify alloc_workqueue() invocations
scsi: myrs: Simplify an alloc_ordered_workqueue() invocation
...
Diffstat (limited to 'drivers/ufs/core/ufs-sysfs.c')
| -rw-r--r-- | drivers/ufs/core/ufs-sysfs.c | 91 |
1 files changed, 75 insertions, 16 deletions
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c index e80a32421a8c..fe313800aed0 100644 --- a/drivers/ufs/core/ufs-sysfs.c +++ b/drivers/ufs/core/ufs-sysfs.c @@ -198,6 +198,24 @@ static u32 ufshcd_us_to_ahit(unsigned int timer) FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale); } +static int ufshcd_read_hci_reg(struct ufs_hba *hba, u32 *val, unsigned int reg) +{ + down(&hba->host_sem); + if (!ufshcd_is_user_access_allowed(hba)) { + up(&hba->host_sem); + return -EBUSY; + } + + ufshcd_rpm_get_sync(hba); + ufshcd_hold(hba); + *val = ufshcd_readl(hba, reg); + ufshcd_release(hba); + ufshcd_rpm_put_sync(hba); + + up(&hba->host_sem); + return 0; +} + static ssize_t auto_hibern8_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -208,23 +226,11 @@ static ssize_t auto_hibern8_show(struct device *dev, if (!ufshcd_is_auto_hibern8_supported(hba)) return -EOPNOTSUPP; - down(&hba->host_sem); - if (!ufshcd_is_user_access_allowed(hba)) { - ret = -EBUSY; - goto out; - } - - pm_runtime_get_sync(hba->dev); - ufshcd_hold(hba); - ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); - ufshcd_release(hba); - pm_runtime_put_sync(hba->dev); - - ret = sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit)); + ret = ufshcd_read_hci_reg(hba, &ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); + if (ret) + return ret; -out: - up(&hba->host_sem); - return ret; + return sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit)); } static ssize_t auto_hibern8_store(struct device *dev, @@ -519,6 +525,58 @@ static const struct attribute_group ufs_sysfs_capabilities_group = { .attrs = ufs_sysfs_capabilities_attrs, }; +static ssize_t version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%x\n", hba->ufs_version); +} + +static ssize_t product_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + u32 val; + struct ufs_hba *hba = dev_get_drvdata(dev); + + ret = ufshcd_read_hci_reg(hba, &val, REG_CONTROLLER_PID); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%x\n", val); +} + +static ssize_t man_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + u32 val; + struct ufs_hba *hba = dev_get_drvdata(dev); + + ret = ufshcd_read_hci_reg(hba, &val, REG_CONTROLLER_MID); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%x\n", val); +} + +static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RO(product_id); +static DEVICE_ATTR_RO(man_id); + +static struct attribute *ufs_sysfs_ufshci_cap_attrs[] = { + &dev_attr_version.attr, + &dev_attr_product_id.attr, + &dev_attr_man_id.attr, + NULL +}; + +static const struct attribute_group ufs_sysfs_ufshci_group = { + .name = "ufshci_capabilities", + .attrs = ufs_sysfs_ufshci_cap_attrs, +}; + static ssize_t monitor_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1502,6 +1560,7 @@ static const struct attribute_group ufs_sysfs_attributes_group = { static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_capabilities_group, + &ufs_sysfs_ufshci_group, &ufs_sysfs_monitor_group, &ufs_sysfs_power_info_group, &ufs_sysfs_device_descriptor_group, |