@@ -1366,6 +1366,75 @@ txgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev)
13661366 return ret ;
13671367}
13681368
1369+ /**
1370+ * txgbevf_get_pf_link_status - Get pf link/speed status
1371+ * @hw: pointer to hardware structure
1372+ *
1373+ * - PF notifies status via mailbox on change
1374+ * - VF sets its link state synchronously upon mailbox interrupt,
1375+ * skipping hardware link detection.
1376+ **/
1377+ static s32 txgbevf_get_pf_link_status (struct rte_eth_dev * dev )
1378+ {
1379+ struct txgbe_hw * hw = TXGBE_DEV_HW (dev );
1380+ struct txgbe_mbx_info * mbx = & hw -> mbx ;
1381+ struct rte_eth_link link ;
1382+ u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN ;
1383+ bool link_up = false;
1384+ u32 msgbuf [2 ];
1385+ s32 retval ;
1386+
1387+ retval = mbx -> read (hw , msgbuf , 2 , 0 );
1388+
1389+ /*
1390+ *if the read failed it could just be a mailbox collision, best wait
1391+ * until we are called again and don't report an error
1392+ */
1393+ if (retval )
1394+ return 0 ;
1395+
1396+ rte_eth_linkstatus_get (dev , & link );
1397+
1398+ link_up = msgbuf [1 ] & TXGBE_VFSTATUS_UP ;
1399+ link_speed = (msgbuf [1 ] & 0xFFF0 ) >> 1 ;
1400+
1401+ if (link_up == link .link_status && link_speed == link .link_speed )
1402+ return 0 ;
1403+
1404+ link .link_speed = link_speed ;
1405+ link .link_status = link_up ;
1406+
1407+ if (link_up )
1408+ link .link_duplex = RTE_ETH_LINK_FULL_DUPLEX ;
1409+ else
1410+ link .link_duplex = RTE_ETH_LINK_HALF_DUPLEX ;
1411+ /*
1412+ * Invoke the LSC interrupt callback to notify the upper app of a link
1413+ * status change, even though the change is detected via a mailbox interrupt
1414+ * instead of an LSC interrupt. This is because VF link status changes do
1415+ * not trigger LSC interrupts — they rely on PF notifications.
1416+ */
1417+ rte_eth_dev_callback_process (dev , RTE_ETH_EVENT_INTR_LSC ,
1418+ NULL );
1419+ return rte_eth_linkstatus_set (dev , & link );
1420+ }
1421+
1422+ static void txgbevf_check_link_for_intr (struct rte_eth_dev * dev )
1423+ {
1424+ struct rte_eth_link orig_link , new_link ;
1425+
1426+ rte_eth_linkstatus_get (dev , & orig_link );
1427+ txgbevf_dev_link_update (dev , 0 );
1428+ rte_eth_linkstatus_get (dev , & new_link );
1429+
1430+ PMD_DRV_LOG (INFO , "orig_link: %d, new_link: %d" ,
1431+ orig_link .link_status , new_link .link_status );
1432+
1433+ if (new_link .link_status != orig_link .link_status )
1434+ rte_eth_dev_callback_process (dev , RTE_ETH_EVENT_INTR_LSC ,
1435+ NULL );
1436+ }
1437+
13691438static void txgbevf_mbx_process (struct rte_eth_dev * dev )
13701439{
13711440 struct txgbe_hw * hw = TXGBE_DEV_HW (dev );
@@ -1375,12 +1444,15 @@ static void txgbevf_mbx_process(struct rte_eth_dev *dev)
13751444 in_msg = rd32 (hw , TXGBE_VFMBX );
13761445
13771446 /* PF reset VF event */
1378- if (in_msg == TXGBE_PF_CONTROL_MSG ) {
1379- /* dummy mbx read to ack pf */
1380- if (txgbe_read_mbx (hw , & in_msg , 1 , 0 ))
1381- return ;
1382- rte_eth_dev_callback_process (dev , RTE_ETH_EVENT_INTR_RESET ,
1383- NULL );
1447+ if (in_msg & TXGBE_PF_CONTROL_MSG ) {
1448+ if (in_msg & TXGBE_NOFITY_VF_LINK_STATUS ) {
1449+ txgbevf_get_pf_link_status (dev );
1450+ } else {
1451+ /* dummy mbx read to ack pf */
1452+ txgbe_read_mbx (hw , & in_msg , 1 , 0 );
1453+ /* check link status if pf ping vf */
1454+ txgbevf_check_link_for_intr (dev );
1455+ }
13841456 }
13851457}
13861458
0 commit comments