Add asynchronous messaging (message which doesn't wait for response)
using message control block.

Signed-off-by: Lijo Lazar <[email protected]>
---
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  3 +-
 drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c        | 37 +++++++++++++++++--
 drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h        |  2 +
 3 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h 
b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 41f27fb4af4b..e98a1e765f1c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -554,7 +554,8 @@ struct cmn2asic_mapping {
 #define SMU_MSG_MAX_ARGS 4
 
 /* Message flags for smu_msg_args */
-#define SMU_MSG_FLAG_NO_WAIT BIT(0) /* Skip post-poll (for split send/wait) */
+#define SMU_MSG_FLAG_ASYNC     BIT(0) /* Async send - skip post-poll */
+#define SMU_MSG_FLAG_LOCK_HELD BIT(1) /* Caller holds ctl->lock */
 
 struct smu_msg_ctl;
 /**
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 1e6a8623a300..3561b388de7b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -640,6 +640,7 @@ static int smu_msg_v1_send_msg(struct smu_msg_ctl *ctl,
        u32 reg, msg_flags;
        int ret, index;
        bool skip_pre_poll = false;
+       bool lock_held = args->flags & SMU_MSG_FLAG_LOCK_HELD;
 
        /* Early exit if no HW access */
        if (adev->no_hw_access)
@@ -660,7 +661,8 @@ static int smu_msg_v1_send_msg(struct smu_msg_ctl *ctl,
        if (amdgpu_sriov_vf(adev) && !(msg_flags & SMU_MSG_VF_FLAG))
                return 0;
 
-       mutex_lock(&ctl->lock);
+       if (!lock_held)
+               mutex_lock(&ctl->lock);
 
        /* RAS priority filter */
        ret = __smu_msg_v1_ras_filter(ctl, args->msg, msg_flags,
@@ -692,8 +694,8 @@ static int smu_msg_v1_send_msg(struct smu_msg_ctl *ctl,
        /* Send message */
        __smu_msg_v1_send(ctl, (u16)index, args->args[0]);
 
-       /* Post-poll (skip if NO_WAIT) */
-       if (args->flags & SMU_MSG_FLAG_NO_WAIT) {
+       /* Post-poll (skip if ASYNC) */
+       if (args->flags & SMU_MSG_FLAG_ASYNC) {
                ret = 0;
                goto out;
        }
@@ -731,7 +733,8 @@ static int smu_msg_v1_send_msg(struct smu_msg_ctl *ctl,
                WARN_ON(1);
        }
 
-       mutex_unlock(&ctl->lock);
+       if (!lock_held)
+               mutex_unlock(&ctl->lock);
        return ret;
 }
 
@@ -768,6 +771,32 @@ int smu_msg_wait_response(struct smu_msg_ctl *ctl, u32 
timeout_us)
        return ctl->ops->wait_response(ctl, timeout_us);
 }
 
+/**
+ * smu_msg_send_async_locked - Send message asynchronously, caller holds lock
+ * @ctl: Message control block
+ * @msg: Message type
+ * @param: Message parameter
+ *
+ * Send an SMU message without waiting for response. Caller must hold ctl->lock
+ * and call smu_msg_wait_response() later to get the result.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int smu_msg_send_async_locked(struct smu_msg_ctl *ctl,
+                             enum smu_message_type msg, u32 param)
+{
+       struct smu_msg_args args = {
+               .msg = msg,
+               .args[0] = param,
+               .num_args = 1,
+               .num_out_args = 0,
+               .flags = SMU_MSG_FLAG_ASYNC | SMU_MSG_FLAG_LOCK_HELD,
+               .timeout = 0,
+       };
+
+       return ctl->ops->send_msg(ctl, &args);
+}
+
 int smu_cmn_to_asic_specific_index(struct smu_context *smu,
                                   enum smu_cmn2asic_mapping_type type,
                                   uint32_t index)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h 
b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index 6ba62180e544..fba813e46f7b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -28,6 +28,8 @@
 extern const struct smu_msg_ops smu_msg_v1_ops;
 
 int smu_msg_wait_response(struct smu_msg_ctl *ctl, u32 timeout_us);
+int smu_msg_send_async_locked(struct smu_msg_ctl *ctl,
+                             enum smu_message_type msg, u32 param);
 
 #if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || 
defined(SWSMU_CODE_LAYER_L4)
 
-- 
2.49.0

Reply via email to