]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: ufs: core: Support Updating UIC Command Timeout
authorBao D. Nguyen <quic_nguyenb@quicinc.com>
Wed, 24 Jul 2024 03:49:32 +0000 (20:49 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 3 Aug 2024 01:42:08 +0000 (21:42 -0400)
The default UIC command timeout still remains 500ms.  Allow platform
drivers to override the UIC command timeout if desired.

In a real product, the 500ms timeout value is probably good enough.
However, during the product development where there are a lot of logging
and debug messages being printed to the UART console, interrupt starvations
happen occasionally because the UART may print long debug messages from
different modules in the system.  While printing, the UART may have
interrupts disabled for more than 500ms, causing UIC command timeout.  The
UIC command timeout would trigger more printing from the UFS driver, and
eventually a watchdog timeout may occur unnecessarily.

Add support for overriding the UIC command timeout value with the newly
created uic_cmd_timeout kernel module parameter.  Default value is
500ms. Supported values range from 500ms to 2 seconds.

Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
Link: https://lore.kernel.org/r/e4e1c87f3f867f270a3d4b5d57a00139ff0e9741.1721792309.git.quic_nguyenb@quicinc.com
Suggested-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ufs/core/ufshcd.c

index dc757ba47522b0997815e4159366282c7798076a..0dd26059f5d7e00513ee05e4cc42319ad24cc815 100644 (file)
 
 
 /* UIC command timeout, unit: ms */
-#define UIC_CMD_TIMEOUT        500
-
+enum {
+       UIC_CMD_TIMEOUT_DEFAULT = 500,
+       UIC_CMD_TIMEOUT_MAX     = 2000,
+};
 /* NOP OUT retries waiting for NOP IN response */
 #define NOP_OUT_RETRIES    10
 /* Timeout after 50 msecs if NOP OUT hangs without response */
@@ -116,6 +118,23 @@ static bool is_mcq_supported(struct ufs_hba *hba)
 module_param(use_mcq_mode, bool, 0644);
 MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default");
 
+static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_DEFAULT;
+
+static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp)
+{
+       return param_set_uint_minmax(val, kp, UIC_CMD_TIMEOUT_DEFAULT,
+                                    UIC_CMD_TIMEOUT_MAX);
+}
+
+static const struct kernel_param_ops uic_cmd_timeout_ops = {
+       .set = uic_cmd_timeout_set,
+       .get = param_get_uint,
+};
+
+module_param_cb(uic_cmd_timeout, &uic_cmd_timeout_ops, &uic_cmd_timeout, 0644);
+MODULE_PARM_DESC(uic_cmd_timeout,
+                "UFS UIC command timeout in milliseconds. Defaults to 500ms. Supported values range from 500ms to 2 seconds inclusively");
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)                           \
        ({                                                              \
                int _ret;                                               \
@@ -2438,7 +2457,7 @@ static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
 {
        u32 val;
        int ret = read_poll_timeout(ufshcd_readl, val, val & UIC_COMMAND_READY,
-                                   500, UIC_CMD_TIMEOUT * 1000, false, hba,
+                                   500, uic_cmd_timeout * 1000, false, hba,
                                    REG_CONTROLLER_STATUS);
        return ret == 0;
 }
@@ -2498,7 +2517,7 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
        lockdep_assert_held(&hba->uic_cmd_mutex);
 
        if (wait_for_completion_timeout(&uic_cmd->done,
-                                       msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
+                                       msecs_to_jiffies(uic_cmd_timeout))) {
                ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
        } else {
                ret = -ETIMEDOUT;
@@ -4266,7 +4285,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
        }
 
        if (!wait_for_completion_timeout(hba->uic_async_done,
-                                        msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
+                                        msecs_to_jiffies(uic_cmd_timeout))) {
                dev_err(hba->dev,
                        "pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
                        cmd->command, cmd->argument3);