xref: /linux/drivers/net/ethernet/wangxun/libwx/wx_mbx.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
3 
4 #include <linux/pci.h>
5 #include "wx_type.h"
6 #include "wx_mbx.h"
7 
8 /**
9  *  wx_obtain_mbx_lock_pf - obtain mailbox lock
10  *  @wx: pointer to the HW structure
11  *  @vf: the VF index
12  *
13  *  Return: return 0 on success and -EBUSY on failure
14  **/
wx_obtain_mbx_lock_pf(struct wx * wx,u16 vf)15 static int wx_obtain_mbx_lock_pf(struct wx *wx, u16 vf)
16 {
17 	int count = 5;
18 	u32 mailbox;
19 
20 	while (count--) {
21 		/* Take ownership of the buffer */
22 		wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_PFU);
23 
24 		/* reserve mailbox for vf use */
25 		mailbox = rd32(wx, WX_PXMAILBOX(vf));
26 		if (mailbox & WX_PXMAILBOX_PFU)
27 			return 0;
28 		else if (count)
29 			udelay(10);
30 	}
31 	wx_err(wx, "Failed to obtain mailbox lock for PF%d", vf);
32 
33 	return -EBUSY;
34 }
35 
wx_check_for_bit_pf(struct wx * wx,u32 mask,int index)36 static int wx_check_for_bit_pf(struct wx *wx, u32 mask, int index)
37 {
38 	u32 mbvficr = rd32(wx, WX_MBVFICR(index));
39 
40 	if (!(mbvficr & mask))
41 		return -EBUSY;
42 	wr32(wx, WX_MBVFICR(index), mask);
43 
44 	return 0;
45 }
46 
47 /**
48  *  wx_check_for_ack_pf - checks to see if the VF has acked
49  *  @wx: pointer to the HW structure
50  *  @vf: the VF index
51  *
52  *  Return: return 0 if the VF has set the status bit or else -EBUSY
53  **/
wx_check_for_ack_pf(struct wx * wx,u16 vf)54 int wx_check_for_ack_pf(struct wx *wx, u16 vf)
55 {
56 	u32 index = vf / 16, vf_bit = vf % 16;
57 
58 	return wx_check_for_bit_pf(wx,
59 				   FIELD_PREP(WX_MBVFICR_VFACK_MASK,
60 					      BIT(vf_bit)),
61 				   index);
62 }
63 
64 /**
65  *  wx_check_for_msg_pf - checks to see if the VF has sent mail
66  *  @wx: pointer to the HW structure
67  *  @vf: the VF index
68  *
69  *  Return: return 0 if the VF has got req bit or else -EBUSY
70  **/
wx_check_for_msg_pf(struct wx * wx,u16 vf)71 int wx_check_for_msg_pf(struct wx *wx, u16 vf)
72 {
73 	u32 index = vf / 16, vf_bit = vf % 16;
74 
75 	return wx_check_for_bit_pf(wx,
76 				   FIELD_PREP(WX_MBVFICR_VFREQ_MASK,
77 					      BIT(vf_bit)),
78 				   index);
79 }
80 
81 /**
82  *  wx_write_mbx_pf - Places a message in the mailbox
83  *  @wx: pointer to the HW structure
84  *  @msg: The message buffer
85  *  @size: Length of buffer
86  *  @vf: the VF index
87  *
88  *  Return: return 0 on success and -EINVAL/-EBUSY on failure
89  **/
wx_write_mbx_pf(struct wx * wx,u32 * msg,u16 size,u16 vf)90 int wx_write_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf)
91 {
92 	struct wx_mbx_info *mbx = &wx->mbx;
93 	int ret, i;
94 
95 	/* mbx->size is up to 15 */
96 	if (size > mbx->size) {
97 		wx_err(wx, "Invalid mailbox message size %d", size);
98 		return -EINVAL;
99 	}
100 
101 	/* lock the mailbox to prevent pf/vf race condition */
102 	ret = wx_obtain_mbx_lock_pf(wx, vf);
103 	if (ret)
104 		return ret;
105 
106 	/* flush msg and acks as we are overwriting the message buffer */
107 	wx_check_for_msg_pf(wx, vf);
108 	wx_check_for_ack_pf(wx, vf);
109 
110 	/* copy the caller specified message to the mailbox memory buffer */
111 	for (i = 0; i < size; i++)
112 		wr32a(wx, WX_PXMBMEM(vf), i, msg[i]);
113 
114 	/* Interrupt VF to tell it a message has been sent and release buffer */
115 	/* set mirrored mailbox flags */
116 	wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_STS);
117 	wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_STS);
118 
119 	return 0;
120 }
121 
122 /**
123  *  wx_read_mbx_pf - Read a message from the mailbox
124  *  @wx: pointer to the HW structure
125  *  @msg: The message buffer
126  *  @size: Length of buffer
127  *  @vf: the VF index
128  *
129  *  Return: return 0 on success and -EBUSY on failure
130  **/
wx_read_mbx_pf(struct wx * wx,u32 * msg,u16 size,u16 vf)131 int wx_read_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf)
132 {
133 	struct wx_mbx_info *mbx = &wx->mbx;
134 	int ret;
135 	u16 i;
136 
137 	/* limit read to size of mailbox and mbx->size is up to 15 */
138 	if (size > mbx->size)
139 		size = mbx->size;
140 
141 	/* lock the mailbox to prevent pf/vf race condition */
142 	ret = wx_obtain_mbx_lock_pf(wx, vf);
143 	if (ret)
144 		return ret;
145 
146 	for (i = 0; i < size; i++)
147 		msg[i] = rd32a(wx, WX_PXMBMEM(vf), i);
148 
149 	/* Acknowledge the message and release buffer */
150 	/* set mirrored mailbox flags */
151 	wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_ACK);
152 	wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_ACK);
153 
154 	return 0;
155 }
156 
157 /**
158  *  wx_check_for_rst_pf - checks to see if the VF has reset
159  *  @wx: pointer to the HW structure
160  *  @vf: the VF index
161  *
162  *  Return: return 0 on success and -EBUSY on failure
163  **/
wx_check_for_rst_pf(struct wx * wx,u16 vf)164 int wx_check_for_rst_pf(struct wx *wx, u16 vf)
165 {
166 	u32 reg_offset = WX_VF_REG_OFFSET(vf);
167 	u32 vf_shift = WX_VF_IND_SHIFT(vf);
168 	u32 vflre = 0;
169 
170 	vflre = rd32(wx, WX_VFLRE(reg_offset));
171 	if (!(vflre & BIT(vf_shift)))
172 		return -EBUSY;
173 	wr32(wx, WX_VFLREC(reg_offset), BIT(vf_shift));
174 
175 	return 0;
176 }
177 
wx_read_v2p_mailbox(struct wx * wx)178 static u32 wx_read_v2p_mailbox(struct wx *wx)
179 {
180 	u32 mailbox = rd32(wx, WX_VXMAILBOX);
181 
182 	mailbox |= wx->mbx.mailbox;
183 	wx->mbx.mailbox |= mailbox & WX_VXMAILBOX_R2C_BITS;
184 
185 	return mailbox;
186 }
187 
wx_mailbox_get_lock_vf(struct wx * wx)188 static u32 wx_mailbox_get_lock_vf(struct wx *wx)
189 {
190 	wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_VFU);
191 	return wx_read_v2p_mailbox(wx);
192 }
193 
194 /**
195  *  wx_obtain_mbx_lock_vf - obtain mailbox lock
196  *  @wx: pointer to the HW structure
197  *
198  *  Return: return 0 on success and -EBUSY on failure
199  **/
wx_obtain_mbx_lock_vf(struct wx * wx)200 static int wx_obtain_mbx_lock_vf(struct wx *wx)
201 {
202 	int count = 5, ret;
203 	u32 mailbox;
204 
205 	ret = readx_poll_timeout_atomic(wx_mailbox_get_lock_vf, wx, mailbox,
206 					(mailbox & WX_VXMAILBOX_VFU),
207 					1, count);
208 	if (ret)
209 		wx_err(wx, "Failed to obtain mailbox lock for VF.\n");
210 
211 	return ret;
212 }
213 
wx_check_for_bit_vf(struct wx * wx,u32 mask)214 static int wx_check_for_bit_vf(struct wx *wx, u32 mask)
215 {
216 	u32 mailbox = wx_read_v2p_mailbox(wx);
217 
218 	wx->mbx.mailbox &= ~mask;
219 
220 	return (mailbox & mask ? 0 : -EBUSY);
221 }
222 
223 /**
224  *  wx_check_for_ack_vf - checks to see if the PF has ACK'd
225  *  @wx: pointer to the HW structure
226  *
227  *  Return: return 0 if the PF has set the status bit or else -EBUSY
228  **/
wx_check_for_ack_vf(struct wx * wx)229 static int wx_check_for_ack_vf(struct wx *wx)
230 {
231 	/* read clear the pf ack bit */
232 	return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFACK);
233 }
234 
235 /**
236  *  wx_check_for_msg_vf - checks to see if the PF has sent mail
237  *  @wx: pointer to the HW structure
238  *
239  *  Return: return 0 if the PF has got req bit or else -EBUSY
240  **/
wx_check_for_msg_vf(struct wx * wx)241 int wx_check_for_msg_vf(struct wx *wx)
242 {
243 	/* read clear the pf sts bit */
244 	return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFSTS);
245 }
246 
247 /**
248  *  wx_check_for_rst_vf - checks to see if the PF has reset
249  *  @wx: pointer to the HW structure
250  *
251  *  Return: return 0 if the PF has set the reset done and -EBUSY on failure
252  **/
wx_check_for_rst_vf(struct wx * wx)253 int wx_check_for_rst_vf(struct wx *wx)
254 {
255 	/* read clear the pf reset done bit */
256 	return wx_check_for_bit_vf(wx,
257 				   WX_VXMAILBOX_RSTD |
258 				   WX_VXMAILBOX_RSTI);
259 }
260 
261 /**
262  *  wx_poll_for_msg - Wait for message notification
263  *  @wx: pointer to the HW structure
264  *
265  *  Return: return 0 if the VF has successfully received a message notification
266  **/
wx_poll_for_msg(struct wx * wx)267 static int wx_poll_for_msg(struct wx *wx)
268 {
269 	struct wx_mbx_info *mbx = &wx->mbx;
270 	u32 val;
271 
272 	return readx_poll_timeout_atomic(wx_check_for_msg_vf, wx, val,
273 					 (val == 0), mbx->udelay, mbx->timeout);
274 }
275 
276 /**
277  *  wx_poll_for_ack - Wait for message acknowledgment
278  *  @wx: pointer to the HW structure
279  *
280  *  Return: return 0 if the VF has successfully received a message ack
281  **/
wx_poll_for_ack(struct wx * wx)282 static int wx_poll_for_ack(struct wx *wx)
283 {
284 	struct wx_mbx_info *mbx = &wx->mbx;
285 	u32 val;
286 
287 	return readx_poll_timeout_atomic(wx_check_for_ack_vf, wx, val,
288 					 (val == 0), mbx->udelay, mbx->timeout);
289 }
290 
291 /**
292  *  wx_read_posted_mbx - Wait for message notification and receive message
293  *  @wx: pointer to the HW structure
294  *  @msg: The message buffer
295  *  @size: Length of buffer
296  *
297  *  Return: returns 0 if it successfully received a message notification and
298  *  copied it into the receive buffer.
299  **/
wx_read_posted_mbx(struct wx * wx,u32 * msg,u16 size)300 int wx_read_posted_mbx(struct wx *wx, u32 *msg, u16 size)
301 {
302 	int ret;
303 
304 	ret = wx_poll_for_msg(wx);
305 	/* if ack received read message, otherwise we timed out */
306 	if (ret)
307 		return ret;
308 
309 	return wx_read_mbx_vf(wx, msg, size);
310 }
311 
312 /**
313  *  wx_write_posted_mbx - Write a message to the mailbox, wait for ack
314  *  @wx: pointer to the HW structure
315  *  @msg: The message buffer
316  *  @size: Length of buffer
317  *
318  *  Return: returns 0 if it successfully copied message into the buffer and
319  *  received an ack to that message within delay * timeout period
320  **/
wx_write_posted_mbx(struct wx * wx,u32 * msg,u16 size)321 int wx_write_posted_mbx(struct wx *wx, u32 *msg, u16 size)
322 {
323 	int ret;
324 
325 	/* send msg */
326 	ret = wx_write_mbx_vf(wx, msg, size);
327 	/* if msg sent wait until we receive an ack */
328 	if (ret)
329 		return ret;
330 
331 	return wx_poll_for_ack(wx);
332 }
333 
334 /**
335  *  wx_write_mbx_vf - Write a message to the mailbox
336  *  @wx: pointer to the HW structure
337  *  @msg: The message buffer
338  *  @size: Length of buffer
339  *
340  *  Return: returns 0 if it successfully copied message into the buffer
341  **/
wx_write_mbx_vf(struct wx * wx,u32 * msg,u16 size)342 int wx_write_mbx_vf(struct wx *wx, u32 *msg, u16 size)
343 {
344 	struct wx_mbx_info *mbx = &wx->mbx;
345 	int ret, i;
346 
347 	/* mbx->size is up to 15 */
348 	if (size > mbx->size) {
349 		wx_err(wx, "Invalid mailbox message size %d", size);
350 		return -EINVAL;
351 	}
352 
353 	/* lock the mailbox to prevent pf/vf race condition */
354 	ret = wx_obtain_mbx_lock_vf(wx);
355 	if (ret)
356 		return ret;
357 
358 	/* flush msg and acks as we are overwriting the message buffer */
359 	wx_check_for_msg_vf(wx);
360 	wx_check_for_ack_vf(wx);
361 
362 	/* copy the caller specified message to the mailbox memory buffer */
363 	for (i = 0; i < size; i++)
364 		wr32a(wx, WX_VXMBMEM, i, msg[i]);
365 
366 	/* Drop VFU and interrupt the PF to tell it a message has been sent */
367 	wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_REQ);
368 
369 	return 0;
370 }
371 
372 /**
373  *  wx_read_mbx_vf - Reads a message from the inbox intended for vf
374  *  @wx: pointer to the HW structure
375  *  @msg: The message buffer
376  *  @size: Length of buffer
377  *
378  *  Return: returns 0 if it successfully copied message into the buffer
379  **/
wx_read_mbx_vf(struct wx * wx,u32 * msg,u16 size)380 int wx_read_mbx_vf(struct wx *wx, u32 *msg, u16 size)
381 {
382 	struct wx_mbx_info *mbx = &wx->mbx;
383 	int ret, i;
384 
385 	/* limit read to size of mailbox and mbx->size is up to 15 */
386 	if (size > mbx->size)
387 		size = mbx->size;
388 
389 	/* lock the mailbox to prevent pf/vf race condition */
390 	ret = wx_obtain_mbx_lock_vf(wx);
391 	if (ret)
392 		return ret;
393 
394 	/* copy the message from the mailbox memory buffer */
395 	for (i = 0; i < size; i++)
396 		msg[i] = rd32a(wx, WX_VXMBMEM, i);
397 
398 	/* Acknowledge receipt and release mailbox, then we're done */
399 	wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_ACK);
400 
401 	return 0;
402 }
403 
wx_init_mbx_params_vf(struct wx * wx)404 int wx_init_mbx_params_vf(struct wx *wx)
405 {
406 	wx->vfinfo = kzalloc(sizeof(struct vf_data_storage),
407 			     GFP_KERNEL);
408 	if (!wx->vfinfo)
409 		return -ENOMEM;
410 
411 	/* Initialize mailbox parameters */
412 	wx->mbx.size = WX_VXMAILBOX_SIZE;
413 	wx->mbx.mailbox = WX_VXMAILBOX;
414 	wx->mbx.udelay = 10;
415 	wx->mbx.timeout = 1000;
416 
417 	return 0;
418 }
419 EXPORT_SYMBOL(wx_init_mbx_params_vf);
420