]> Git Repo - J-linux.git/commitdiff
scsi: ufs: core: Add ufshcd_send_bsg_uic_cmd() for UFS BSG
authorZiqi Chen <[email protected]>
Tue, 19 Nov 2024 09:56:04 +0000 (17:56 +0800)
committerMartin K. Petersen <[email protected]>
Thu, 21 Nov 2024 02:59:45 +0000 (21:59 -0500)
User layer applications can send UIC GET/SET commands via the BSG
framework, and if the user layer application sends a UIC SET command to the
PA_PWRMODE attribute, a power mode change shall be initiated in UniPro and
two interrupts shall be triggered if the power mode is successfully
changed, i.e., UIC Command Completion interrupt and UIC Power Mode
interrupt.

The current UFS BSG code calls ufshcd_send_uic_cmd() directly, with which
the second interrupt, i.e., UIC Power Mode interrupt, shall be treated as
unhandled interrupt. In addition, after the UIC command is completed, user
layer application has to poll UniPro and/or M-PHY state machine to confirm
the power mode change is finished.

Add a new wrapper function ufshcd_send_bsg_uic_cmd() and call it from
ufs_bsg_request() so that if a UIC SET command is targeting the PA_PWRMODE
attribute it can be redirected to ufshcd_uic_pwr_ctrl().

Fixes: e77044c5a842 ("scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()")
Co-developed-by: Can Guo <[email protected]>
Signed-off-by: Can Guo <[email protected]>
Signed-off-by: Ziqi Chen <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Reviewed-by: Bean Huo <[email protected]>
Reviewed-by: Avri Altman <[email protected]>
Reviewed-by: Peter Wang <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
drivers/ufs/core/ufs_bsg.c
drivers/ufs/core/ufshcd-priv.h
drivers/ufs/core/ufshcd.c

index 433d0480391ea633c005aee741b1bd89b1e44db9..6c09d97ae00658333b491dc2d4a6bcd21dceb6a1 100644 (file)
@@ -170,7 +170,7 @@ static int ufs_bsg_request(struct bsg_job *job)
                break;
        case UPIU_TRANSACTION_UIC_CMD:
                memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE);
-               ret = ufshcd_send_uic_cmd(hba, &uc);
+               ret = ufshcd_send_bsg_uic_cmd(hba, &uc);
                if (ret)
                        dev_err(hba->dev, "send uic cmd: error code %d\n", ret);
 
index 7aea8fbaeee8822290686567401e502e9365e853..9ffd94ddf8c7ce947fa722362abb1b3be81f81df 100644 (file)
@@ -84,6 +84,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
                            u8 **buf, bool ascii);
 
 int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
+int ufshcd_send_bsg_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
 
 int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
                             struct utp_upiu_req *req_upiu,
index 8135a6dad7c6fad7942f04540d1949588228d8d9..dd31aa7c6785658f882f6421d0ab88b0441d1544 100644 (file)
@@ -4319,6 +4319,42 @@ out_unlock:
        return ret;
 }
 
+/**
+ * ufshcd_send_bsg_uic_cmd - Send UIC commands requested via BSG layer and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Return: 0 only if success.
+ */
+int ufshcd_send_bsg_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+       int ret;
+
+       if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD)
+               return 0;
+
+       ufshcd_hold(hba);
+
+       if (uic_cmd->argument1 == UIC_ARG_MIB(PA_PWRMODE) &&
+           uic_cmd->command == UIC_CMD_DME_SET) {
+               ret = ufshcd_uic_pwr_ctrl(hba, uic_cmd);
+               goto out;
+       }
+
+       mutex_lock(&hba->uic_cmd_mutex);
+       ufshcd_add_delay_before_dme_cmd(hba);
+
+       ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+       if (!ret)
+               ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+       mutex_unlock(&hba->uic_cmd_mutex);
+
+out:
+       ufshcd_release(hba);
+       return ret;
+}
+
 /**
  * ufshcd_uic_change_pwr_mode - Perform the UIC power mode chage
  *                             using DME_SET primitives.
This page took 0.065656 seconds and 4 git commands to generate.