xref: /linux/drivers/net/ethernet/wangxun/libwx/wx_vf.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
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 
wx_virt_clr_reg(struct wx * wx)12 static 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  **/
wx_init_hw_vf(struct wx * wx)35 void wx_init_hw_vf(struct wx *wx)
36 {
37 	wx_get_mac_addr_vf(wx, wx->mac.addr);
38 }
39 EXPORT_SYMBOL(wx_init_hw_vf);
40 
wx_mbx_write_and_read_reply(struct wx * wx,u32 * req_buf,u32 * resp_buf,u16 size)41 static 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  **/
wx_reset_hw_vf(struct wx * wx)62 int 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 }
128 EXPORT_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  **/
wx_stop_adapter_vf(struct wx * wx)136 void 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 }
163 EXPORT_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  **/
wx_set_rar_vf(struct wx * wx,u32 index,u8 * addr,u32 enable_addr)174 int 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 }
196 EXPORT_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  **/
wx_update_mc_addr_list_vf(struct wx * wx,struct net_device * netdev)207 int 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 }
231 EXPORT_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  **/
wx_update_xcast_mode_vf(struct wx * wx,int xcast_mode)242 int 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 }
261 EXPORT_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  **/
wx_get_link_state_vf(struct wx * wx,u16 * link_state)270 int 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 }
287 EXPORT_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  **/
wx_set_vfta_vf(struct wx * wx,u32 vlan,u32 vind,bool vlan_on,bool vlvf_bypass)301 int 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 }
323 EXPORT_SYMBOL(wx_set_vfta_vf);
324 
wx_get_mac_addr_vf(struct wx * wx,u8 * mac_addr)325 void wx_get_mac_addr_vf(struct wx *wx, u8 *mac_addr)
326 {
327 	ether_addr_copy(mac_addr, wx->mac.perm_addr);
328 }
329 EXPORT_SYMBOL(wx_get_mac_addr_vf);
330 
wx_get_fw_version_vf(struct wx * wx)331 int 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 }
347 EXPORT_SYMBOL(wx_get_fw_version_vf);
348 
wx_set_uc_addr_vf(struct wx * wx,u32 index,u8 * addr)349 int 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 }
375 EXPORT_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  **/
wx_rlpml_set_vf(struct wx * wx,u16 max_size)384 int 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 }
399 EXPORT_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  **/
wx_negotiate_api_version(struct wx * wx,int api)408 int 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 }
427 EXPORT_SYMBOL(wx_negotiate_api_version);
428 
wx_get_queues_vf(struct wx * wx,u32 * num_tcs,u32 * default_tc)429 int 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 }
473 EXPORT_SYMBOL(wx_get_queues_vf);
474 
wx_get_link_status_from_pf(struct wx * wx,u32 * msgbuf)475 static 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 
wx_pf_ping_vf(struct wx * wx,u32 * msgbuf)496 static 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 
505 static 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 
wx_check_physical_link(struct wx * wx)513 static 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 
wx_check_mac_link_vf(struct wx * wx)549 int 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 
597 out:
598 	return ret;
599 }
600