Skip to content

Commit 2c632ad

Browse files
Vadim Lomovtsevdavem330
authored andcommitted
net: thunderx: move link state polling function to VF
Move the link change polling task to VF side in order to prevent races between VF and PF while sending link change message(s). This commit is to implement link change request to be initiated by VF. Signed-off-by: Vadim Lomovtsev <vlomovtsev@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 609ea65 commit 2c632ad

File tree

3 files changed

+74
-19
lines changed

3 files changed

+74
-19
lines changed

drivers/net/ethernet/cavium/thunder/nic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ struct nicvf {
331331
struct workqueue_struct *nicvf_rx_mode_wq;
332332
/* mutex to protect VF's mailbox contents from concurrent access */
333333
struct mutex rx_mode_mtx;
334-
334+
struct delayed_work link_change_work;
335335
/* PTP timestamp */
336336
struct cavium_ptp *ptp_clock;
337337
/* Inbound timestamping is on */

drivers/net/ethernet/cavium/thunder/nic_main.c

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,35 @@ static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
929929
nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
930930
}
931931

932+
static void nic_link_status_get(struct nicpf *nic, u8 vf)
933+
{
934+
union nic_mbx mbx = {};
935+
struct bgx_link_status link;
936+
u8 bgx, lmac;
937+
938+
mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
939+
940+
/* Get BGX, LMAC indices for the VF */
941+
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
942+
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
943+
944+
/* Get interface link status */
945+
bgx_get_lmac_link_state(nic->node, bgx, lmac, &link);
946+
947+
nic->link[vf] = link.link_up;
948+
nic->duplex[vf] = link.duplex;
949+
nic->speed[vf] = link.speed;
950+
951+
/* Send a mbox message to VF with current link status */
952+
mbx.link_status.link_up = link.link_up;
953+
mbx.link_status.duplex = link.duplex;
954+
mbx.link_status.speed = link.speed;
955+
mbx.link_status.mac_type = link.mac_type;
956+
957+
/* reply with link status */
958+
nic_send_msg_to_vf(nic, vf, &mbx);
959+
}
960+
932961
/* Interrupt handler to handle mailbox messages from VFs */
933962
static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
934963
{
@@ -1108,6 +1137,13 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
11081137
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
11091138
bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.mode);
11101139
break;
1140+
case NIC_MBOX_MSG_BGX_LINK_CHANGE:
1141+
if (vf >= nic->num_vf_en) {
1142+
ret = -1; /* NACK */
1143+
break;
1144+
}
1145+
nic_link_status_get(nic, vf);
1146+
goto unlock;
11111147
default:
11121148
dev_err(&nic->pdev->dev,
11131149
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
@@ -1419,9 +1455,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
14191455
goto err_disable_sriov;
14201456
}
14211457

1422-
INIT_DELAYED_WORK(&nic->dwork, nic_poll_for_link);
1423-
queue_delayed_work(nic->check_link, &nic->dwork, 0);
1424-
14251458
return 0;
14261459

14271460
err_disable_sriov:

drivers/net/ethernet/cavium/thunder/nicvf_main.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -242,21 +242,24 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
242242
break;
243243
case NIC_MBOX_MSG_BGX_LINK_CHANGE:
244244
nic->pf_acked = true;
245-
nic->link_up = mbx.link_status.link_up;
246-
nic->duplex = mbx.link_status.duplex;
247-
nic->speed = mbx.link_status.speed;
248-
nic->mac_type = mbx.link_status.mac_type;
249-
if (nic->link_up) {
250-
netdev_info(nic->netdev, "Link is Up %d Mbps %s duplex\n",
251-
nic->speed,
252-
nic->duplex == DUPLEX_FULL ?
253-
"Full" : "Half");
254-
netif_carrier_on(nic->netdev);
255-
netif_tx_start_all_queues(nic->netdev);
256-
} else {
257-
netdev_info(nic->netdev, "Link is Down\n");
258-
netif_carrier_off(nic->netdev);
259-
netif_tx_stop_all_queues(nic->netdev);
245+
if (nic->link_up != mbx.link_status.link_up) {
246+
nic->link_up = mbx.link_status.link_up;
247+
nic->duplex = mbx.link_status.duplex;
248+
nic->speed = mbx.link_status.speed;
249+
nic->mac_type = mbx.link_status.mac_type;
250+
if (nic->link_up) {
251+
netdev_info(nic->netdev,
252+
"Link is Up %d Mbps %s duplex\n",
253+
nic->speed,
254+
nic->duplex == DUPLEX_FULL ?
255+
"Full" : "Half");
256+
netif_carrier_on(nic->netdev);
257+
netif_tx_start_all_queues(nic->netdev);
258+
} else {
259+
netdev_info(nic->netdev, "Link is Down\n");
260+
netif_carrier_off(nic->netdev);
261+
netif_tx_stop_all_queues(nic->netdev);
262+
}
260263
}
261264
break;
262265
case NIC_MBOX_MSG_ALLOC_SQS:
@@ -1325,6 +1328,8 @@ int nicvf_stop(struct net_device *netdev)
13251328
struct nicvf_cq_poll *cq_poll = NULL;
13261329
union nic_mbx mbx = {};
13271330

1331+
cancel_delayed_work_sync(&nic->link_change_work);
1332+
13281333
/* wait till all queued set_rx_mode tasks completes */
13291334
drain_workqueue(nic->nicvf_rx_mode_wq);
13301335

@@ -1427,6 +1432,18 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
14271432
return nicvf_send_msg_to_pf(nic, &mbx);
14281433
}
14291434

1435+
static void nicvf_link_status_check_task(struct work_struct *work_arg)
1436+
{
1437+
struct nicvf *nic = container_of(work_arg,
1438+
struct nicvf,
1439+
link_change_work.work);
1440+
union nic_mbx mbx = {};
1441+
mbx.msg.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
1442+
nicvf_send_msg_to_pf(nic, &mbx);
1443+
queue_delayed_work(nic->nicvf_rx_mode_wq,
1444+
&nic->link_change_work, 2 * HZ);
1445+
}
1446+
14301447
int nicvf_open(struct net_device *netdev)
14311448
{
14321449
int cpu, err, qidx;
@@ -1533,6 +1550,11 @@ int nicvf_open(struct net_device *netdev)
15331550
/* Send VF config done msg to PF */
15341551
nicvf_send_cfg_done(nic);
15351552

1553+
INIT_DELAYED_WORK(&nic->link_change_work,
1554+
nicvf_link_status_check_task);
1555+
queue_delayed_work(nic->nicvf_rx_mode_wq,
1556+
&nic->link_change_work, 0);
1557+
15361558
return 0;
15371559
cleanup:
15381560
nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);

0 commit comments

Comments
 (0)