File Index
Files and directories
Sign in
FILE

wx_vf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/wangxun/libwx/wx_vf.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
  3
  4#include <linux/etherdevice.h>
  5#include <linux/pci.h>
  6
  7#include "wx_type.h"
  8#include "wx_hw.h"
  9#include "wx_mbx.h"
 10#include "wx_vf.h"
 11
 12static void wx_virt_clr_reg(struct wx *wx)
 13{
 14	u32 vfsrrctl, i;
 15
 16	/* VRSRRCTL default values (BSIZEPACKET = 2048, BSIZEHEADER = 256) */
 17	vfsrrctl = WX_VXRXDCTL_HDRSZ(wx_hdr_sz(WX_RX_HDR_SIZE));
 18	vfsrrctl |= WX_VXRXDCTL_BUFSZ(wx_buf_sz(WX_RX_BUF_SIZE));
 19
 20	/* clear all rxd ctl */
 21	for (i = 0; i < WX_VF_MAX_RING_NUMS; i++)
 22		wr32m(wx, WX_VXRXDCTL(i),
 23		      WX_VXRXDCTL_HDRSZ_MASK | WX_VXRXDCTL_BUFSZ_MASK,
 24		      vfsrrctl);
 25
 26	rd32(wx, WX_VXSTATUS);
 27}
 28
 29/**
 30 *  wx_init_hw_vf - virtual function hardware initialization
 31 *  @wx: pointer to hardware structure
 32 *
 33 *  Initialize the mac address
 34 **/
 35void wx_init_hw_vf(struct wx *wx)
 36{
 37	wx_get_mac_addr_vf(wx, wx->mac.addr);
 38}
 39EXPORT_SYMBOL(wx_init_hw_vf);
 40
 41static int wx_mbx_write_and_read_reply(struct wx *wx, u32 *req_buf,
 42				       u32 *resp_buf, u16 size)
 43{
 44	int ret;
 45
 46	ret = wx_write_posted_mbx(wx, req_buf, size);
 47	if (ret)
 48		return ret;
 49
 50	return wx_read_posted_mbx(wx, resp_buf, size);
 51}
 52
 53/**
 54 *  wx_reset_hw_vf - Performs hardware reset
 55 *  @wx: pointer to hardware structure
 56 *
 57 *  Resets the hardware by resetting the transmit and receive units, masks and
 58 *  clears all interrupts.
 59 *
 60 *  Return: returns 0 on success, negative error code on failure
 61 **/
 62int wx_reset_hw_vf(struct wx *wx)
 63{
 64	struct wx_mbx_info *mbx = &wx->mbx;
 65	u32 msgbuf[4] = {WX_VF_RESET};
 66	u8 *addr = (u8 *)(&msgbuf[1]);
 67	u32 b4_buf[16] = {0};
 68	u32 timeout = 200;
 69	int ret;
 70	u32 i;
 71
 72	/* Call wx stop to disable tx/rx and clear interrupts */
 73	wx_stop_adapter_vf(wx);
 74
 75	/* reset the api version */
 76	wx->vfinfo->vf_api = wx_mbox_api_null;
 77
 78	/* backup msix vectors */
 79	if (wx->b4_addr) {
 80		for (i = 0; i < 16; i++)
 81			b4_buf[i] = readl(wx->b4_addr + i * 4);
 82	}
 83
 84	wr32m(wx, WX_VXCTRL, WX_VXCTRL_RST, WX_VXCTRL_RST);
 85	rd32(wx, WX_VXSTATUS);
 86
 87	/* we cannot reset while the RSTI / RSTD bits are asserted */
 88	while (!wx_check_for_rst_vf(wx) && timeout) {
 89		timeout--;
 90		udelay(5);
 91	}
 92
 93	/* restore msix vectors */
 94	if (wx->b4_addr) {
 95		for (i = 0; i < 16; i++)
 96			writel(b4_buf[i], wx->b4_addr + i * 4);
 97	}
 98
 99	/* amlite: bme */
100	if (wx->mac.type == wx_mac_aml || wx->mac.type == wx_mac_aml40)
101		wr32(wx, WX_VX_PF_BME, WX_VF_BME_ENABLE);
102
103	if (!timeout)
104		return -EBUSY;
105
106	/* Reset VF registers to initial values */
107	wx_virt_clr_reg(wx);
108
109	/* mailbox timeout can now become active */
110	mbx->timeout = 2000;
111
112	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
113					  ARRAY_SIZE(msgbuf));
114	if (ret)
115		return ret;
116
117	if (msgbuf[0] != (WX_VF_RESET | WX_VT_MSGTYPE_ACK) &&
118	    msgbuf[0] != (WX_VF_RESET | WX_VT_MSGTYPE_NACK))
119		return -EINVAL;
120
121	if (msgbuf[0] == (WX_VF_RESET | WX_VT_MSGTYPE_ACK))
122		ether_addr_copy(wx->mac.perm_addr, addr);
123
124	wx->mac.mc_filter_type = msgbuf[3];
125
126	return 0;
127}
128EXPORT_SYMBOL(wx_reset_hw_vf);
129
130/**
131 *  wx_stop_adapter_vf - Generic stop Tx/Rx units
132 *  @wx: pointer to hardware structure
133 *
134 *  Clears interrupts, disables transmit and receive units.
135 **/
136void wx_stop_adapter_vf(struct wx *wx)
137{
138	u32 reg_val;
139	u16 i;
140
141	/* Clear interrupt mask to stop from interrupts being generated */
142	wr32(wx, WX_VXIMS, WX_VF_IRQ_CLEAR_MASK);
143
144	/* Clear any pending interrupts, flush previous writes */
145	wr32(wx, WX_VXICR, U32_MAX);
146
147	/* Disable the transmit unit.  Each queue must be disabled. */
148	for (i = 0; i < wx->mac.max_tx_queues; i++)
149		wr32(wx, WX_VXTXDCTL(i), WX_VXTXDCTL_FLUSH);
150
151	/* Disable the receive unit by stopping each queue */
152	for (i = 0; i < wx->mac.max_rx_queues; i++) {
153		reg_val = rd32(wx, WX_VXRXDCTL(i));
154		reg_val &= ~WX_VXRXDCTL_ENABLE;
155		wr32(wx, WX_VXRXDCTL(i), reg_val);
156	}
157	/* Clear packet split and pool config */
158	wr32(wx, WX_VXMRQC, 0);
159
160	/* flush all queues disables */
161	rd32(wx, WX_VXSTATUS);
162}
163EXPORT_SYMBOL(wx_stop_adapter_vf);
164
165/**
166 *  wx_set_rar_vf - set device MAC address
167 *  @wx: pointer to hardware structure
168 *  @index: Receive address register to write
169 *  @addr: Address to put into receive address register
170 *  @enable_addr: set flag that address is active
171 *
172 *  Return: returns 0 on success, negative error code on failure
173 **/
174int wx_set_rar_vf(struct wx *wx, u32 index, u8 *addr, u32 enable_addr)
175{
176	u32 msgbuf[3] = {WX_VF_SET_MAC_ADDR};
177	u8 *msg_addr = (u8 *)(&msgbuf[1]);
178	int ret;
179
180	memcpy(msg_addr, addr, ETH_ALEN);
181
182	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
183					  ARRAY_SIZE(msgbuf));
184	if (ret)
185		return ret;
186	msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;
187
188	/* if nacked the address was rejected, use "perm_addr" */
189	if (msgbuf[0] == (WX_VF_SET_MAC_ADDR | WX_VT_MSGTYPE_NACK)) {
190		wx_get_mac_addr_vf(wx, wx->mac.addr);
191		return -EINVAL;
192	}
193
194	return 0;
195}
196EXPORT_SYMBOL(wx_set_rar_vf);
197
198/**
199 *  wx_update_mc_addr_list_vf - Update Multicast addresses
200 *  @wx: pointer to the HW structure
201 *  @netdev: pointer to the net device structure
202 *
203 *  Updates the Multicast Table Array.
204 *
205 *  Return: returns 0 on success, negative error code on failure
206 **/
207int wx_update_mc_addr_list_vf(struct wx *wx, struct net_device *netdev)
208{
209	u32 msgbuf[WX_VXMAILBOX_SIZE] = {WX_VF_SET_MULTICAST};
210	u16 *vector_l = (u16 *)&msgbuf[1];
211	struct netdev_hw_addr *ha;
212	u32 cnt, i;
213
214	cnt = netdev_mc_count(netdev);
215	if (cnt > 28)
216		cnt = 28;
217	msgbuf[0] |= cnt << WX_VT_MSGINFO_SHIFT;
218
219	i = 0;
220	netdev_for_each_mc_addr(ha, netdev) {
221		if (i == cnt)
222			break;
223		if (is_link_local_ether_addr(ha->addr))
224			continue;
225
226		vector_l[i++] = wx_mta_vector(wx, ha->addr);
227	}
228
229	return wx_write_posted_mbx(wx, msgbuf, ARRAY_SIZE(msgbuf));
230}
231EXPORT_SYMBOL(wx_update_mc_addr_list_vf);
232
233/**
234 *  wx_update_xcast_mode_vf - Update Multicast mode
235 *  @wx: pointer to the HW structure
236 *  @xcast_mode: new multicast mode
237 *
238 *  Updates the Multicast Mode of VF.
239 *
240 *  Return: returns 0 on success, negative error code on failure
241 **/
242int wx_update_xcast_mode_vf(struct wx *wx, int xcast_mode)
243{
244	u32 msgbuf[2] = {WX_VF_UPDATE_XCAST_MODE, xcast_mode};
245	int ret = 0;
246
247	if (wx->vfinfo->vf_api < wx_mbox_api_13)
248		return -EINVAL;
249
250	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
251					  ARRAY_SIZE(msgbuf));
252	if (ret)
253		return ret;
254
255	msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;
256	if (msgbuf[0] == (WX_VF_UPDATE_XCAST_MODE | WX_VT_MSGTYPE_NACK))
257		return -EINVAL;
258
259	return 0;
260}
261EXPORT_SYMBOL(wx_update_xcast_mode_vf);
262
263/**
264 * wx_get_link_state_vf - Get VF link state from PF
265 * @wx: pointer to the HW structure
266 * @link_state: link state storage
267 *
268 * Return: return state of the operation error or success.
269 **/
270int wx_get_link_state_vf(struct wx *wx, u16 *link_state)
271{
272	u32 msgbuf[2] = {WX_VF_GET_LINK_STATE};
273	int ret;
274
275	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
276					  ARRAY_SIZE(msgbuf));
277	if (ret)
278		return ret;
279
280	if (msgbuf[0] & WX_VT_MSGTYPE_NACK)
281		return -EINVAL;
282
283	*link_state = msgbuf[1];
284
285	return 0;
286}
287EXPORT_SYMBOL(wx_get_link_state_vf);
288
289/**
290 *  wx_set_vfta_vf - Set/Unset vlan filter table address
291 *  @wx: pointer to the HW structure
292 *  @vlan: 12 bit VLAN ID
293 *  @vind: unused by VF drivers
294 *  @vlan_on: if true then set bit, else clear bit
295 *  @vlvf_bypass: boolean flag indicating updating default pool is okay
296 *
297 *  Turn on/off specified VLAN in the VLAN filter table.
298 *
299 *  Return: returns 0 on success, negative error code on failure
300 **/
301int wx_set_vfta_vf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on,
302		   bool vlvf_bypass)
303{
304	u32 msgbuf[2] = {WX_VF_SET_VLAN, vlan};
305	bool vlan_offload = false;
306	int ret;
307
308	/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
309	msgbuf[0] |= vlan_on << WX_VT_MSGINFO_SHIFT;
310	/* if vf vlan offload is disabled, allow to create vlan under pf port vlan */
311	msgbuf[0] |= BIT(vlan_offload);
312
313	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
314					  ARRAY_SIZE(msgbuf));
315	if (ret)
316		return ret;
317
318	if (msgbuf[0] & WX_VT_MSGTYPE_ACK)
319		return 0;
320
321	return msgbuf[0] & WX_VT_MSGTYPE_NACK;
322}
323EXPORT_SYMBOL(wx_set_vfta_vf);
324
325void wx_get_mac_addr_vf(struct wx *wx, u8 *mac_addr)
326{
327	ether_addr_copy(mac_addr, wx->mac.perm_addr);
328}
329EXPORT_SYMBOL(wx_get_mac_addr_vf);
330
331int wx_get_fw_version_vf(struct wx *wx)
332{
333	u32 msgbuf[2] = {WX_VF_GET_FW_VERSION};
334	int ret;
335
336	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
337					  ARRAY_SIZE(msgbuf));
338	if (ret)
339		return ret;
340
341	if (msgbuf[0] & WX_VT_MSGTYPE_NACK)
342		return -EINVAL;
343	snprintf(wx->eeprom_id, 32, "0x%08x", msgbuf[1]);
344
345	return 0;
346}
347EXPORT_SYMBOL(wx_get_fw_version_vf);
348
349int wx_set_uc_addr_vf(struct wx *wx, u32 index, u8 *addr)
350{
351	u32 msgbuf[3] = {WX_VF_SET_MACVLAN};
352	u8 *msg_addr = (u8 *)(&msgbuf[1]);
353	int ret;
354
355	/* If index is one then this is the start of a new list and needs
356	 * indication to the PF so it can do it's own list management.
357	 * If it is zero then that tells the PF to just clear all of
358	 * this VF's macvlans and there is no new list.
359	 */
360	msgbuf[0] |= index << WX_VT_MSGINFO_SHIFT;
361	if (addr)
362		memcpy(msg_addr, addr, 6);
363	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
364					  ARRAY_SIZE(msgbuf));
365	if (ret)
366		return ret;
367
368	msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;
369
370	if (msgbuf[0] == (WX_VF_SET_MACVLAN | WX_VT_MSGTYPE_NACK))
371		return -EINVAL;
372
373	return 0;
374}
375EXPORT_SYMBOL(wx_set_uc_addr_vf);
376
377/**
378 *  wx_rlpml_set_vf - Set the maximum receive packet length
379 *  @wx: pointer to the HW structure
380 *  @max_size: value to assign to max frame size
381 *
382 *  Return: returns 0 on success, negative error code on failure
383 **/
384int wx_rlpml_set_vf(struct wx *wx, u16 max_size)
385{
386	u32 msgbuf[2] = {WX_VF_SET_LPE, max_size};
387	int ret;
388
389	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
390					  ARRAY_SIZE(msgbuf));
391	if (ret)
392		return ret;
393	if ((msgbuf[0] & WX_VF_SET_LPE) &&
394	    (msgbuf[0] & WX_VT_MSGTYPE_NACK))
395		return -EINVAL;
396
397	return 0;
398}
399EXPORT_SYMBOL(wx_rlpml_set_vf);
400
401/**
402 *  wx_negotiate_api_version - Negotiate supported API version
403 *  @wx: pointer to the HW structure
404 *  @api: integer containing requested API version
405 *
406 *  Return: returns 0 on success, negative error code on failure
407 **/
408int wx_negotiate_api_version(struct wx *wx, int api)
409{
410	u32 msgbuf[2] = {WX_VF_API_NEGOTIATE, api};
411	int ret;
412
413	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
414					  ARRAY_SIZE(msgbuf));
415	if (ret)
416		return ret;
417
418	msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;
419
420	/* Store value and return 0 on success */
421	if (msgbuf[0] == (WX_VF_API_NEGOTIATE | WX_VT_MSGTYPE_NACK))
422		return -EINVAL;
423	wx->vfinfo->vf_api = api;
424
425	return 0;
426}
427EXPORT_SYMBOL(wx_negotiate_api_version);
428
429int wx_get_queues_vf(struct wx *wx, u32 *num_tcs, u32 *default_tc)
430{
431	u32 msgbuf[5] = {WX_VF_GET_QUEUES};
432	int ret;
433
434	/* do nothing if API doesn't support wx_get_queues */
435	if (wx->vfinfo->vf_api < wx_mbox_api_13)
436		return -EINVAL;
437
438	/* Fetch queue configuration from the PF */
439	ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
440					  ARRAY_SIZE(msgbuf));
441	if (ret)
442		return ret;
443	msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;
444
445	/* if we didn't get an ACK there must have been
446	 * some sort of mailbox error so we should treat it
447	 * as such
448	 */
449	if (msgbuf[0] != (WX_VF_GET_QUEUES | WX_VT_MSGTYPE_ACK))
450		return -EINVAL;
451	/* record and validate values from message */
452	wx->mac.max_tx_queues = msgbuf[WX_VF_TX_QUEUES];
453	if (wx->mac.max_tx_queues == 0 ||
454	    wx->mac.max_tx_queues > WX_VF_MAX_TX_QUEUES)
455		wx->mac.max_tx_queues = WX_VF_MAX_TX_QUEUES;
456
457	wx->mac.max_rx_queues = msgbuf[WX_VF_RX_QUEUES];
458	if (wx->mac.max_rx_queues == 0 ||
459	    wx->mac.max_rx_queues > WX_VF_MAX_RX_QUEUES)
460		wx->mac.max_rx_queues = WX_VF_MAX_RX_QUEUES;
461
462	*num_tcs = msgbuf[WX_VF_TRANS_VLAN];
463	/* in case of unknown state assume we cannot tag frames */
464	if (*num_tcs > wx->mac.max_rx_queues)
465		*num_tcs = 1;
466	*default_tc = msgbuf[WX_VF_DEF_QUEUE];
467	/* default to queue 0 on out-of-bounds queue number */
468	if (*default_tc >= wx->mac.max_tx_queues)
469		*default_tc = 0;
470
471	return 0;
472}
473EXPORT_SYMBOL(wx_get_queues_vf);
474
475static int wx_get_link_status_from_pf(struct wx *wx, u32 *msgbuf)
476{
477	u32 links_reg = msgbuf[1];
478
479	if (msgbuf[1] & WX_PF_NOFITY_VF_NET_NOT_RUNNING)
480		wx->notify_down = true;
481	else
482		wx->notify_down = false;
483
484	if (wx->notify_down) {
485		wx->link = false;
486		wx->speed = SPEED_UNKNOWN;
487		return 0;
488	}
489
490	wx->link = WX_PFLINK_STATUS(links_reg);
491	wx->speed = WX_PFLINK_SPEED(links_reg);
492
493	return 0;
494}
495
496static int wx_pf_ping_vf(struct wx *wx, u32 *msgbuf)
497{
498	if (!(msgbuf[0] & WX_VT_MSGTYPE_CTS))
499		/* msg is not CTS, we need to do reset */
500		return -EINVAL;
501
502	return 0;
503}
504
505static struct wx_link_reg_fields wx_speed_lookup_vf[] = {
506	{wx_mac_unknown},
507	{wx_mac_sp, SPEED_10000, SPEED_1000, SPEED_100, SPEED_UNKNOWN, SPEED_UNKNOWN},
508	{wx_mac_em, SPEED_1000,  SPEED_100, SPEED_10, SPEED_UNKNOWN, SPEED_UNKNOWN},
509	{wx_mac_aml, SPEED_40000, SPEED_25000, SPEED_10000, SPEED_1000, SPEED_UNKNOWN},
510	{wx_mac_aml40, SPEED_40000, SPEED_25000, SPEED_10000, SPEED_1000, SPEED_UNKNOWN},
511};
512
513static void wx_check_physical_link(struct wx *wx)
514{
515	u32 val, link_val;
516	int ret;
517
518	/* get link status from hw status reg
519	 * for SFP+ modules and DA cables, it can take up to 500usecs
520	 * before the link status is correct
521	 */
522	if (wx->mac.type == wx_mac_em)
523		ret = read_poll_timeout_atomic(rd32, val, val & GENMASK(4, 1),
524					       100, 500, false, wx, WX_VXSTATUS);
525	else
526		ret = read_poll_timeout_atomic(rd32, val, val & BIT(0), 100,
527					       500, false, wx, WX_VXSTATUS);
528	if (ret) {
529		wx->speed = SPEED_UNKNOWN;
530		wx->link = false;
531		return;
532	}
533
534	wx->link = true;
535	link_val = WX_VXSTATUS_SPEED(val);
536
537	if (link_val & BIT(0))
538		wx->speed = wx_speed_lookup_vf[wx->mac.type].bit0_f;
539	else if (link_val & BIT(1))
540		wx->speed = wx_speed_lookup_vf[wx->mac.type].bit1_f;
541	else if (link_val & BIT(2))
542		wx->speed = wx_speed_lookup_vf[wx->mac.type].bit2_f;
543	else if (link_val & BIT(3))
544		wx->speed = wx_speed_lookup_vf[wx->mac.type].bit3_f;
545	else
546		wx->speed = SPEED_UNKNOWN;
547}
548
549int wx_check_mac_link_vf(struct wx *wx)
550{
551	struct wx_mbx_info *mbx = &wx->mbx;
552	u32 msgbuf[2] = {0};
553	int ret = 0;
554
555	if (!mbx->timeout)
556		goto out;
557
558	wx_check_for_rst_vf(wx);
559	if (!wx_check_for_msg_vf(wx))
560		ret = wx_read_mbx_vf(wx, msgbuf, 2);
561	if (ret)
562		goto out;
563
564	switch (msgbuf[0] & GENMASK(8, 0)) {
565	case WX_PF_NOFITY_VF_LINK_STATUS | WX_PF_CONTROL_MSG:
566		ret = wx_get_link_status_from_pf(wx, msgbuf);
567		goto out;
568	case WX_PF_CONTROL_MSG:
569		ret = wx_pf_ping_vf(wx, msgbuf);
570		goto out;
571	case 0:
572		if (msgbuf[0] & WX_VT_MSGTYPE_NACK) {
573			/* msg is NACK, we must have lost CTS status */
574			ret = -EBUSY;
575			goto out;
576		}
577		/* no message, check link status */
578		wx_check_physical_link(wx);
579		goto out;
580	default:
581		break;
582	}
583
584	if (!(msgbuf[0] & WX_VT_MSGTYPE_CTS)) {
585		/* msg is not CTS and is NACK we must have lost CTS status */
586		if (msgbuf[0] & WX_VT_MSGTYPE_NACK)
587			ret = -EBUSY;
588		goto out;
589	}
590
591	/* the pf is talking, if we timed out in the past we reinit */
592	if (!mbx->timeout) {
593		ret = -EBUSY;
594		goto out;
595	}
596
597out:
598	return ret;
599}
~/ Read-only file preview.