mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
scsi: ufs: core: Introduce function ufshcd_query_attr_qword()
Introduce a new generic function ufshcd_query_attr_qword() to handle quad-word (64-bit) UFS attribute operations. This consolidates the handling of 64-bit attributes which was previously scattered across multiple specialized functions. Reviewed-by: Peter Wang <peter.wang@mediatek.com> Signed-off-by: Can Guo <can.guo@oss.qualcomm.com> Reviewed-by: Bean Huo <beanhuo@micron.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Link: https://patch.msgid.link/20260424151420.111675-2-can.guo@oss.qualcomm.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
254f49634e
commit
f2cb7c01f4
|
|
@ -594,8 +594,13 @@ static ssize_t device_lvl_exception_id_show(struct device *dev,
|
|||
u64 exception_id;
|
||||
int err;
|
||||
|
||||
if (hba->dev_info.wspecversion < 0x410)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ufshcd_rpm_get_sync(hba);
|
||||
err = ufshcd_read_device_lvl_exception_id(hba, &exception_id);
|
||||
err = ufshcd_query_attr_qword(hba, UPIU_QUERY_OPCODE_READ_ATTR,
|
||||
QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID,
|
||||
0, 0, &exception_id);
|
||||
ufshcd_rpm_put_sync(hba);
|
||||
|
||||
if (err)
|
||||
|
|
@ -1670,6 +1675,12 @@ static inline bool ufshcd_is_wb_attrs(enum attr_idn idn)
|
|||
idn <= QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE;
|
||||
}
|
||||
|
||||
static inline bool ufshcd_is_qword_attr(enum attr_idn idn)
|
||||
{
|
||||
return idn == QUERY_ATTR_IDN_TIMESTAMP ||
|
||||
idn == QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID;
|
||||
}
|
||||
|
||||
static int wb_read_resize_attrs(struct ufs_hba *hba,
|
||||
enum attr_idn idn, u32 *attr_val)
|
||||
{
|
||||
|
|
@ -1736,6 +1747,7 @@ static ssize_t _name##_show(struct device *dev, \
|
|||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev); \
|
||||
u64 qword_value; \
|
||||
u32 value; \
|
||||
int ret; \
|
||||
u8 index = 0; \
|
||||
|
|
@ -1748,14 +1760,24 @@ static ssize_t _name##_show(struct device *dev, \
|
|||
if (ufshcd_is_wb_attrs(QUERY_ATTR_IDN##_uname)) \
|
||||
index = ufshcd_wb_get_query_index(hba); \
|
||||
ufshcd_rpm_get_sync(hba); \
|
||||
ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
|
||||
QUERY_ATTR_IDN##_uname, index, 0, &value); \
|
||||
if (ufshcd_is_qword_attr(QUERY_ATTR_IDN##_uname)) \
|
||||
ret = ufshcd_query_attr_qword(hba, \
|
||||
UPIU_QUERY_OPCODE_READ_ATTR, \
|
||||
QUERY_ATTR_IDN##_uname, \
|
||||
index, 0, &qword_value); \
|
||||
else \
|
||||
ret = ufshcd_query_attr(hba, \
|
||||
UPIU_QUERY_OPCODE_READ_ATTR, \
|
||||
QUERY_ATTR_IDN##_uname, index, 0, &value); \
|
||||
ufshcd_rpm_put_sync(hba); \
|
||||
if (ret) { \
|
||||
ret = -EINVAL; \
|
||||
goto out; \
|
||||
} \
|
||||
ret = sysfs_emit(buf, "0x%08X\n", value); \
|
||||
if (ufshcd_is_qword_attr(QUERY_ATTR_IDN##_uname)) \
|
||||
ret = sysfs_emit(buf, "0x%016llX\n", qword_value); \
|
||||
else \
|
||||
ret = sysfs_emit(buf, "0x%08X\n", value); \
|
||||
out: \
|
||||
up(&hba->host_sem); \
|
||||
return ret; \
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ int ufshcd_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode,
|
|||
u32 *attr_val);
|
||||
int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
|
||||
enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
|
||||
int ufshcd_query_attr_qword(struct ufs_hba *hba, enum query_opcode opcode,
|
||||
enum attr_idn idn, u8 index, u8 sel, u64 *attr_val);
|
||||
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
||||
enum flag_idn idn, u8 index, bool *flag_res);
|
||||
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
|
||||
|
|
@ -106,7 +108,6 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
|
|||
enum query_opcode desc_op);
|
||||
|
||||
int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable);
|
||||
int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id);
|
||||
|
||||
int ufshcd_uic_tx_eqtr(struct ufs_hba *hba, int gear);
|
||||
void ufshcd_apply_valid_tx_eq_settings(struct ufs_hba *hba);
|
||||
|
|
|
|||
|
|
@ -3611,6 +3611,67 @@ int ufshcd_query_attr_retry(struct ufs_hba *hba,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_query_attr_qword - Function of sending query requests for quad-word attributes
|
||||
* @hba: per-adapter instance
|
||||
* @opcode: attribute opcode
|
||||
* @idn: attribute idn to access
|
||||
* @index: index field
|
||||
* @sel: selector field
|
||||
* @attr_val: the attribute value after the query request completes
|
||||
*
|
||||
* Return: 0 for success, non-zero in case of failure.
|
||||
*/
|
||||
int ufshcd_query_attr_qword(struct ufs_hba *hba, enum query_opcode opcode,
|
||||
enum attr_idn idn, u8 index, u8 sel, u64 *attr_val)
|
||||
{
|
||||
struct utp_upiu_query_v4_0 *upiu_req;
|
||||
struct utp_upiu_query_v4_0 *upiu_resp;
|
||||
struct ufs_query_req *request = NULL;
|
||||
struct ufs_query_res *response = NULL;
|
||||
int err;
|
||||
|
||||
if (!attr_val) {
|
||||
dev_err(hba->dev, "%s: attribute value required for opcode 0x%x\n",
|
||||
__func__, opcode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ufshcd_dev_man_lock(hba);
|
||||
|
||||
ufshcd_init_query(hba, &request, &response, opcode, idn, index, sel);
|
||||
|
||||
switch (opcode) {
|
||||
case UPIU_QUERY_OPCODE_WRITE_ATTR:
|
||||
request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
|
||||
upiu_req = (struct utp_upiu_query_v4_0 *)&request->upiu_req;
|
||||
put_unaligned_be64(*attr_val, &upiu_req->osf3);
|
||||
break;
|
||||
case UPIU_QUERY_OPCODE_READ_ATTR:
|
||||
request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
|
||||
break;
|
||||
default:
|
||||
dev_err(hba->dev, "%s: Expected query attr opcode but got = 0x%.2x\n",
|
||||
__func__, opcode);
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, dev_cmd_timeout);
|
||||
if (err) {
|
||||
dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, index %d, selector %d, err = %d\n",
|
||||
__func__, opcode, idn, index, sel, err);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
upiu_resp = (struct utp_upiu_query_v4_0 *)response;
|
||||
*attr_val = get_unaligned_be64(&upiu_resp->osf3);
|
||||
|
||||
out_unlock:
|
||||
ufshcd_dev_man_unlock(hba);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
||||
* < 0 if another error occurred.
|
||||
|
|
@ -6224,46 +6285,6 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
|
|||
__func__, err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
||||
* < 0 if another error occurred.
|
||||
*/
|
||||
int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id)
|
||||
{
|
||||
struct utp_upiu_query_v4_0 *upiu_resp;
|
||||
struct ufs_query_req *request = NULL;
|
||||
struct ufs_query_res *response = NULL;
|
||||
int err;
|
||||
|
||||
if (hba->dev_info.wspecversion < 0x410)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ufshcd_hold(hba);
|
||||
mutex_lock(&hba->dev_cmd.lock);
|
||||
|
||||
ufshcd_init_query(hba, &request, &response,
|
||||
UPIU_QUERY_OPCODE_READ_ATTR,
|
||||
QUERY_ATTR_IDN_DEV_LVL_EXCEPTION_ID, 0, 0);
|
||||
|
||||
request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
|
||||
|
||||
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, dev_cmd_timeout);
|
||||
|
||||
if (err) {
|
||||
dev_err(hba->dev, "%s: failed to read device level exception %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
upiu_resp = (struct utp_upiu_query_v4_0 *)response;
|
||||
*exception_id = get_unaligned_be64(&upiu_resp->osf3);
|
||||
out:
|
||||
mutex_unlock(&hba->dev_cmd.lock);
|
||||
ufshcd_release(hba);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn)
|
||||
{
|
||||
u8 index;
|
||||
|
|
@ -9113,35 +9134,20 @@ static int ufshcd_device_params_init(struct ufs_hba *hba)
|
|||
|
||||
static void ufshcd_set_timestamp_attr(struct ufs_hba *hba)
|
||||
{
|
||||
int err;
|
||||
struct ufs_query_req *request = NULL;
|
||||
struct ufs_query_res *response = NULL;
|
||||
struct ufs_dev_info *dev_info = &hba->dev_info;
|
||||
struct utp_upiu_query_v4_0 *upiu_data;
|
||||
u64 ts_ns;
|
||||
int err;
|
||||
|
||||
if (dev_info->wspecversion < 0x400 ||
|
||||
hba->dev_quirks & UFS_DEVICE_QUIRK_NO_TIMESTAMP_SUPPORT)
|
||||
return;
|
||||
|
||||
ufshcd_dev_man_lock(hba);
|
||||
|
||||
ufshcd_init_query(hba, &request, &response,
|
||||
UPIU_QUERY_OPCODE_WRITE_ATTR,
|
||||
QUERY_ATTR_IDN_TIMESTAMP, 0, 0);
|
||||
|
||||
request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
|
||||
|
||||
upiu_data = (struct utp_upiu_query_v4_0 *)&request->upiu_req;
|
||||
|
||||
put_unaligned_be64(ktime_get_real_ns(), &upiu_data->osf3);
|
||||
|
||||
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, dev_cmd_timeout);
|
||||
|
||||
ts_ns = ktime_get_real_ns();
|
||||
err = ufshcd_query_attr_qword(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
|
||||
QUERY_ATTR_IDN_TIMESTAMP, 0, 0, &ts_ns);
|
||||
if (err)
|
||||
dev_err(hba->dev, "%s: failed to set timestamp %d\n",
|
||||
__func__, err);
|
||||
|
||||
ufshcd_dev_man_unlock(hba);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user