Skip to content

Commit c213eae

Browse files
Michael Chandavem330
authored andcommitted
bnxt_en: Improve VF/PF link change logic.
Link status query firmware messages originating from the VFs are forwarded to the PF. The driver handles these interactions in a workqueue for the VF and PF. The VF driver waits for the response from the PF in the workqueue. If the PF and VF driver are running on the same host and the work for both PF and VF are queued on the same workqueue, the VF driver may not get the response if the PF work item is queued behind it on the same workqueue. This will lead to the VF link query message timing out. To prevent this, we create a private workqueue for PFs instead of using the common workqueue. The VF query and PF response will never be on the same workqueue. Fixes: c0c050c ("bnxt_en: New Broadcom ethernet driver.") Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3efc93c commit c213eae

File tree

1 file changed

+53
-13
lines changed
  • drivers/net/ethernet/broadcom/bnxt

1 file changed

+53
-13
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ static const u16 bnxt_async_events_arr[] = {
214214
ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
215215
};
216216

217+
static struct workqueue_struct *bnxt_pf_wq;
218+
217219
static bool bnxt_vf_pciid(enum board_idx idx)
218220
{
219221
return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF);
@@ -1024,12 +1026,28 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_napi *bnapi,
10241026
return 0;
10251027
}
10261028

1029+
static void bnxt_queue_sp_work(struct bnxt *bp)
1030+
{
1031+
if (BNXT_PF(bp))
1032+
queue_work(bnxt_pf_wq, &bp->sp_task);
1033+
else
1034+
schedule_work(&bp->sp_task);
1035+
}
1036+
1037+
static void bnxt_cancel_sp_work(struct bnxt *bp)
1038+
{
1039+
if (BNXT_PF(bp))
1040+
flush_workqueue(bnxt_pf_wq);
1041+
else
1042+
cancel_work_sync(&bp->sp_task);
1043+
}
1044+
10271045
static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
10281046
{
10291047
if (!rxr->bnapi->in_reset) {
10301048
rxr->bnapi->in_reset = true;
10311049
set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
1032-
schedule_work(&bp->sp_task);
1050+
bnxt_queue_sp_work(bp);
10331051
}
10341052
rxr->rx_next_cons = 0xffff;
10351053
}
@@ -1717,7 +1735,7 @@ static int bnxt_async_event_process(struct bnxt *bp,
17171735
default:
17181736
goto async_event_process_exit;
17191737
}
1720-
schedule_work(&bp->sp_task);
1738+
bnxt_queue_sp_work(bp);
17211739
async_event_process_exit:
17221740
bnxt_ulp_async_events(bp, cmpl);
17231741
return 0;
@@ -1751,7 +1769,7 @@ static int bnxt_hwrm_handler(struct bnxt *bp, struct tx_cmp *txcmp)
17511769

17521770
set_bit(vf_id - bp->pf.first_vf_id, bp->pf.vf_event_bmap);
17531771
set_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event);
1754-
schedule_work(&bp->sp_task);
1772+
bnxt_queue_sp_work(bp);
17551773
break;
17561774

17571775
case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT:
@@ -6647,7 +6665,7 @@ static void bnxt_set_rx_mode(struct net_device *dev)
66476665
vnic->rx_mask = mask;
66486666

66496667
set_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event);
6650-
schedule_work(&bp->sp_task);
6668+
bnxt_queue_sp_work(bp);
66516669
}
66526670
}
66536671

@@ -6920,7 +6938,7 @@ static void bnxt_tx_timeout(struct net_device *dev)
69206938

69216939
netdev_err(bp->dev, "TX timeout detected, starting reset task!\n");
69226940
set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
6923-
schedule_work(&bp->sp_task);
6941+
bnxt_queue_sp_work(bp);
69246942
}
69256943

69266944
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -6952,7 +6970,7 @@ static void bnxt_timer(unsigned long data)
69526970
if (bp->link_info.link_up && (bp->flags & BNXT_FLAG_PORT_STATS) &&
69536971
bp->stats_coal_ticks) {
69546972
set_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event);
6955-
schedule_work(&bp->sp_task);
6973+
bnxt_queue_sp_work(bp);
69566974
}
69576975
bnxt_restart_timer:
69586976
mod_timer(&bp->timer, jiffies + bp->current_interval);
@@ -7433,7 +7451,7 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
74337451
spin_unlock_bh(&bp->ntp_fltr_lock);
74347452

74357453
set_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event);
7436-
schedule_work(&bp->sp_task);
7454+
bnxt_queue_sp_work(bp);
74377455

74387456
return new_fltr->sw_id;
74397457

@@ -7516,7 +7534,7 @@ static void bnxt_udp_tunnel_add(struct net_device *dev,
75167534
if (bp->vxlan_port_cnt == 1) {
75177535
bp->vxlan_port = ti->port;
75187536
set_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event);
7519-
schedule_work(&bp->sp_task);
7537+
bnxt_queue_sp_work(bp);
75207538
}
75217539
break;
75227540
case UDP_TUNNEL_TYPE_GENEVE:
@@ -7533,7 +7551,7 @@ static void bnxt_udp_tunnel_add(struct net_device *dev,
75337551
return;
75347552
}
75357553

7536-
schedule_work(&bp->sp_task);
7554+
bnxt_queue_sp_work(bp);
75377555
}
75387556

75397557
static void bnxt_udp_tunnel_del(struct net_device *dev,
@@ -7572,7 +7590,7 @@ static void bnxt_udp_tunnel_del(struct net_device *dev,
75727590
return;
75737591
}
75747592

7575-
schedule_work(&bp->sp_task);
7593+
bnxt_queue_sp_work(bp);
75767594
}
75777595

75787596
static int bnxt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
@@ -7720,7 +7738,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
77207738
pci_disable_pcie_error_reporting(pdev);
77217739
unregister_netdev(dev);
77227740
bnxt_shutdown_tc(bp);
7723-
cancel_work_sync(&bp->sp_task);
7741+
bnxt_cancel_sp_work(bp);
77247742
bp->sp_event = 0;
77257743

77267744
bnxt_clear_int_mode(bp);
@@ -8138,8 +8156,17 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
81388156
else
81398157
device_set_wakeup_capable(&pdev->dev, false);
81408158

8141-
if (BNXT_PF(bp))
8159+
if (BNXT_PF(bp)) {
8160+
if (!bnxt_pf_wq) {
8161+
bnxt_pf_wq =
8162+
create_singlethread_workqueue("bnxt_pf_wq");
8163+
if (!bnxt_pf_wq) {
8164+
dev_err(&pdev->dev, "Unable to create workqueue.\n");
8165+
goto init_err_pci_clean;
8166+
}
8167+
}
81428168
bnxt_init_tc(bp);
8169+
}
81438170

81448171
rc = register_netdev(dev);
81458172
if (rc)
@@ -8375,4 +8402,17 @@ static struct pci_driver bnxt_pci_driver = {
83758402
#endif
83768403
};
83778404

8378-
module_pci_driver(bnxt_pci_driver);
8405+
static int __init bnxt_init(void)
8406+
{
8407+
return pci_register_driver(&bnxt_pci_driver);
8408+
}
8409+
8410+
static void __exit bnxt_exit(void)
8411+
{
8412+
pci_unregister_driver(&bnxt_pci_driver);
8413+
if (bnxt_pf_wq)
8414+
destroy_workqueue(bnxt_pf_wq);
8415+
}
8416+
8417+
module_init(bnxt_init);
8418+
module_exit(bnxt_exit);

0 commit comments

Comments
 (0)