File Index
Files and directories
Sign in
FILE

wx_mbx.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/wangxun/libwx/wx_mbx.c C
  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 **/
 15static 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
 36static 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 **/
 54int 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 **/
 71int 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 **/
 90int 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 **/
131int 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 **/
164int 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
178static 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
188static 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 **/
200static 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
214static 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 **/
229static 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 **/
241int 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 **/
253int 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 **/
267static 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 **/
282static 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 **/
300int 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 **/
321int 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 **/
342int 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 **/
380int 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
404int 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}
419EXPORT_SYMBOL(wx_init_mbx_params_vf);
~/ Read-only file preview.