1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (C) 2025 Intel Corporation */ 3 4 #include "ixd.h" 5 #include "ixd_ctlq.h" 6 #include "ixd_virtchnl.h" 7 8 #define IXD_CTLQ_RX_TASK_DELAY_JIFFIES msecs_to_jiffies(300) 9 10 /** 11 * ixd_ctlq_clean_sq - Clean the send control queue after sending the message 12 * @adapter: The adapter that sent the messages 13 * @force: Clean regardless of send status 14 * 15 * Free the libie send resources after sending the message and handling 16 * the response. 17 */ 18 void ixd_ctlq_clean_sq(struct ixd_adapter *adapter, bool force) 19 { 20 libie_ctlq_xn_send_clean(adapter->asq, kfree, force); 21 } 22 23 /** 24 * ixd_ctlq_init_sparams - Initialize control queue send parameters 25 * @adapter: The adapter with initialized mailbox 26 * @sparams: Parameters to initialize 27 * @msg_buf: DMA-mappable pointer to the message being sent 28 * @msg_size: Message size 29 */ 30 static void ixd_ctlq_init_sparams(struct ixd_adapter *adapter, 31 struct libie_ctlq_xn_send_params *sparams, 32 void *msg_buf, size_t msg_size) 33 { 34 *sparams = (struct libie_ctlq_xn_send_params) { 35 .rel_tx_buf = kfree, 36 .xnm = adapter->xnm, 37 .ctlq = adapter->asq, 38 .timeout_ms = IXD_CTLQ_TIMEOUT, 39 .send_buf = (struct kvec) { 40 .iov_base = msg_buf, 41 .iov_len = msg_size, 42 }, 43 }; 44 } 45 46 /** 47 * ixd_ctlq_do_req - Perform a standard virtchnl request 48 * @adapter: The adapter with initialized mailbox 49 * @req: virtchnl request description 50 * 51 * Return: %0 if a message was sent and received a response 52 * that was successfully handled by the custom callback, 53 * negative error otherwise. 54 */ 55 int ixd_ctlq_do_req(struct ixd_adapter *adapter, const struct ixd_ctlq_req *req) 56 { 57 u8 onstack_send_buff[LIBIE_CP_TX_COPYBREAK] __aligned_largest = {}; 58 struct libie_ctlq_xn_send_params send_params = {}; 59 struct kvec *recv_mem; 60 void *send_buff; 61 int err; 62 63 send_buff = libie_cp_can_send_onstack(req->send_size) ? 64 &onstack_send_buff : kzalloc(req->send_size, GFP_KERNEL); 65 if (!send_buff) 66 return -ENOMEM; 67 68 ixd_ctlq_init_sparams(adapter, &send_params, send_buff, 69 req->send_size); 70 71 send_params.chnl_opcode = req->opcode; 72 73 if (req->send_buff_init) 74 req->send_buff_init(adapter, send_buff, req->ctx); 75 76 ixd_ctlq_clean_sq(adapter, false); 77 err = libie_ctlq_xn_send(&send_params); 78 if (err) 79 return err; 80 81 recv_mem = &send_params.recv_mem; 82 if (req->recv_process) 83 err = req->recv_process(adapter, recv_mem->iov_base, 84 recv_mem->iov_len, req->ctx); 85 86 libie_ctlq_release_rx_buf(recv_mem); 87 88 return err; 89 } 90 91 /** 92 * ixd_ctlq_handle_msg - Default control queue message handler 93 * @ctx: Control plane communication context 94 * @msg: Message received 95 */ 96 static void ixd_ctlq_handle_msg(struct libie_ctlq_ctx *ctx, 97 struct libie_ctlq_msg *msg) 98 { 99 struct ixd_adapter *adapter = pci_get_drvdata(ctx->mmio_info.pdev); 100 101 if (ixd_vc_can_handle_msg(msg)) 102 ixd_vc_recv_event_msg(adapter, msg); 103 else 104 dev_dbg_ratelimited(ixd_to_dev(adapter), 105 "Received an unsupported opcode 0x%x from the CP\n", 106 msg->chnl_opcode); 107 108 libie_ctlq_release_rx_buf(&msg->recv_mem); 109 } 110 111 /** 112 * ixd_ctlq_recv_mb_msg - Receive a potential message over mailbox periodically 113 * @adapter: The adapter with initialized mailbox 114 */ 115 static void ixd_ctlq_recv_mb_msg(struct ixd_adapter *adapter) 116 { 117 struct libie_ctlq_xn_recv_params xn_params = { 118 .xnm = adapter->xnm, 119 .ctlq = adapter->arq, 120 .ctlq_msg_handler = ixd_ctlq_handle_msg, 121 .budget = LIBIE_CTLQ_MAX_XN_ENTRIES, 122 }; 123 124 libie_ctlq_xn_recv(&xn_params); 125 } 126 127 /** 128 * ixd_ctlq_rx_task - Periodically check for mailbox responses and events 129 * @work: work handle 130 */ 131 void ixd_ctlq_rx_task(struct work_struct *work) 132 { 133 struct ixd_adapter *adapter; 134 135 adapter = container_of(work, struct ixd_adapter, mbx_task.work); 136 137 queue_delayed_work(system_dfl_wq, &adapter->mbx_task, 138 IXD_CTLQ_RX_TASK_DELAY_JIFFIES); 139 140 ixd_ctlq_recv_mb_msg(adapter); 141 } 142