diff mbox series

[RFC,v1,021/256] cl8k: add bus/pci/msg_pci.c

Message ID 20210617160223.160998-22-viktor.barna@celeno.com
State New
Headers show
Series wireless: cl8k driver for Celeno IEEE 802.11ax devices | expand

Commit Message

Viktor Barna June 17, 2021, 3:58 p.m. UTC
From: Viktor Barna <viktor.barna@celeno.com>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@celeno.com>
---
 .../wireless/celeno/cl8k/bus/pci/msg_pci.c    | 101 ++++++++++++++++++
 1 file changed, 101 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/bus/pci/msg_pci.c

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/bus/pci/msg_pci.c b/drivers/net/wireless/celeno/cl8k/bus/pci/msg_pci.c
new file mode 100644
index 000000000000..4ddc060940c1
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/bus/pci/msg_pci.c
@@ -0,0 +1,101 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "chip.h"
+#include "hw.h"
+#include "bus/pci/ipc.h"
+#include "fw/fw_msg.h"
+#include "fw/msg_cfm.h"
+#ifdef TRACE_SUPPORT
+#include "trace.h"
+#endif
+
+static void cl_msg_pci_fw_push(struct cl_hw *cl_hw, void *msg_buf, u16 len)
+{
+       /* Send a message to the embedded side */
+       int i;
+       u32 *src;
+       u32 *dst;
+       struct cl_ipc_host_env *ipc_env = cl_hw->ipc_env;
+
+       /* Copy the message into the IPC MSG buffer */
+       src = (u32 *)msg_buf;
+       dst = (u32 *)&ipc_env->shared->a2e_msg_buf;
+
+       /*
+        * Move the destination pointer forward by one word
+        * (due to the format of the firmware kernel messages)
+        */
+       dst++;
+
+       /* Align length of message to 4 */
+       len = ALIGN(len, sizeof(u32));
+
+       /* Copy the message in the IPC queue */
+       for (i = 0; i < len; i += sizeof(u32))
+               *dst++ = cpu_to_le32(*src++);
+
+       /* Trigger the irq to send the message to EMB */
+       cl_hw->ipc_host2xmac_trigger_set(cl_hw->chip, IPC_IRQ_A2E_MSG);
+}
+
+int cl_msg_pci_msg_fw_send(struct cl_hw *cl_hw, const void *msg_params,
+                          bool background)
+{
+       struct fw_msg *msg = container_of((void *)msg_params, struct fw_msg, param);
+       u16 req_id = msg->msg_id;
+       u16 cfm_bit = cl_msg_cfm_set_bit(req_id);
+       int length = sizeof(struct fw_msg) + msg->param_len;
+       int error = 0;
+
+       if (!cl_hw->fw_active) {
+               cl_dbg_verbose(cl_hw, "Bypass %s (firmware not loaded)\n", MSG_ID_STR(req_id));
+               /* Free the message */
+               kfree(msg);
+               return -EBUSY;
+       }
+
+       if (test_bit(CL_DEV_FW_ERROR, &cl_hw->drv_flags)) {
+               cl_dbg_verbose(cl_hw, "Bypass %s (CL_DEV_FW_ERROR is set)\n", MSG_ID_STR(req_id));
+               /* Free the message */
+               kfree(msg);
+               return -EBUSY;
+       }
+
+       if (!test_bit(CL_DEV_STARTED, &cl_hw->drv_flags) &&
+           msg->msg_id != MM_RESET_REQ &&
+           msg->msg_id != MM_START_REQ) {
+               cl_dbg_verbose(cl_hw, "Bypass %s (CL_DEV_STARTED not set)\n", MSG_ID_STR(req_id));
+               /* Free the message */
+               kfree(msg);
+               return -EBUSY;
+       }
+
+       /* Lock msg tx of the correct msg buffer. */
+       error = mutex_lock_interruptible(&cl_hw->msg_tx_mutex);
+       if (error != 0) {
+               cl_dbg_verbose(cl_hw, "Bypass %s (mutex error %d)\n", MSG_ID_STR(req_id), error);
+               /* Free the message */
+               kfree(msg);
+               return error;
+       }
+
+       cl_hw->msg_background = background;
+
+       CFM_SET_BIT(cfm_bit, &cl_hw->cfm_flags);
+
+       cl_dbg_trace(cl_hw, "%s\n", MSG_ID_STR(req_id));
+
+       /* Push the message in the IPC */
+       cl_msg_pci_fw_push(cl_hw, msg, length);
+
+       /* Free the message */
+       kfree(msg);
+
+#ifdef TRACE_SUPPORT
+       trace_cl_trace_cl_msg_fw_send(cl_hw->idx, (int)req_id);
+#endif
+
+       return cl_msg_cfm_wait(cl_hw, cfm_bit, req_id);
+}
+