xref: /linux/drivers/net/ethernet/intel/ixd/ixd_ctlq.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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  */
ixd_ctlq_clean_sq(struct ixd_adapter * adapter,bool force)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  */
ixd_ctlq_init_sparams(struct ixd_adapter * adapter,struct libie_ctlq_xn_send_params * sparams,void * msg_buf,size_t msg_size)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  */
ixd_ctlq_do_req(struct ixd_adapter * adapter,const struct ixd_ctlq_req * req)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  */
ixd_ctlq_handle_msg(struct libie_ctlq_ctx * ctx,struct libie_ctlq_msg * msg)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  */
ixd_ctlq_recv_mb_msg(struct ixd_adapter * adapter)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  */
ixd_ctlq_rx_task(struct work_struct * work)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