@@ -63,6 +63,55 @@ static int ufs_bsg_verify_query_size(unsigned int request_len,
return 0;
}
+static int ufs_bsg_exec_uic_cmd(struct uic_command *uc)
+{
+ u32 attr_sel = uc->argument1;
+ u8 attr_set = (uc->argument2 >> 16) & 0xff;
+ u32 mib_val = uc->argument3;
+ int cmd = uc->command;
+ int ret = 0;
+
+ switch (cmd) {
+ case UIC_CMD_DME_GET:
+ ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ &mib_val, DME_LOCAL);
+ break;
+ case UIC_CMD_DME_SET:
+ ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_LOCAL);
+ break;
+ case UIC_CMD_DME_PEER_GET:
+ ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ &mib_val, DME_PEER);
+ break;
+ case UIC_CMD_DME_PEER_SET:
+ ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_PEER);
+ break;
+ case UIC_CMD_DME_POWERON:
+ case UIC_CMD_DME_POWEROFF:
+ case UIC_CMD_DME_ENABLE:
+ case UIC_CMD_DME_RESET:
+ case UIC_CMD_DME_END_PT_RST:
+ case UIC_CMD_DME_LINK_STARTUP:
+ case UIC_CMD_DME_HIBER_ENTER:
+ case UIC_CMD_DME_HIBER_EXIT:
+ case UIC_CMD_DME_TEST_MODE:
+ ret = -ENOTSUPP;
+ pr_err("%s unsupported command 0x%x\n", __func__, cmd);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ pr_err("%s error in command 0x%x\n", __func__, cmd);
+
+ uc->argument3 = mib_val;
+
+ return ret;
+}
+
static int ufs_bsg_request(struct bsg_job *job)
{
struct ufs_bsg_request *bsg_request = job->request;
@@ -70,6 +119,7 @@ static int ufs_bsg_request(struct bsg_job *job)
unsigned int request_len = job->request_len;
unsigned int reply_len = job->reply_len;
struct utp_upiu_query *qr;
+ struct uic_command uc = {0};
__be32 *req_upiu = NULL;
__be32 *rsp_upiu = NULL;
int msgcode;
@@ -124,7 +174,11 @@ static int ufs_bsg_request(struct bsg_job *job)
break;
case UPIU_TRANSACTION_UIC_CMD:
- /* later */
+ memcpy(&uc, &bsg_request->tsf.uc, UIC_CMD_SIZE);
+ ret = ufs_bsg_exec_uic_cmd(&uc);
+ memcpy(&bsg_reply->tsf.uc, &uc, UIC_CMD_SIZE);
+
+ break;
case UPIU_TRANSACTION_COMMAND:
case UPIU_TRANSACTION_DATA_OUT:
not_supported:
@@ -15,6 +15,7 @@
#define UFS_BSG_NOP (-1)
#define UPIU_TRANSACTION_UIC_CMD 0x1F
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
enum {
REQ_UPIU_SIZE_DWORDS = 8,
Add support to those uic commands, that are currently supported by ufshcd api: the variants of dme_{peer}_{set_get}. At this point better not to add any new api, as careless uic command may turn the device into a brick. Signed-off-by: Avri Altman <avri.altman@wdc.com> --- drivers/scsi/ufs/ufs_bsg.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufs_bsg.h | 1 + 2 files changed, 56 insertions(+), 1 deletion(-)