mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
bng_en: add per-PF workqueue, timer, and slow-path task
Add a dedicated single-thread workqueue and a timer for each PF to drive deferred slow-path work such as link event handling and stats collection. The timer is stopped via timer_delete_sync() when interrupts are disabled and restarted on open. While the close path stops the timer to prevent new tasks from being scheduled, the sp_task and workqueue are preserved to maintain state continuity. Final draining and destruction of the workqueue are handled during PCI remove. Signed-off-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com> Reviewed-by: Vikas Gupta <vikas.gupta@broadcom.com> Reviewed-by: Ajit Kumar Khaparde <ajit.khaparde@broadcom.com> Link: https://patch.msgid.link/20260406180420.279470-2-bhargava.marreddy@broadcom.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
05ed6c221e
commit
2095da2340
|
|
@ -101,6 +101,36 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void bnge_timer(struct timer_list *t)
|
||||
{
|
||||
struct bnge_net *bn = timer_container_of(bn, t, timer);
|
||||
struct bnge_dev *bd = bn->bd;
|
||||
|
||||
if (!netif_running(bn->netdev) ||
|
||||
!test_bit(BNGE_STATE_OPEN, &bd->state))
|
||||
return;
|
||||
|
||||
/* Periodic work added by later patches */
|
||||
|
||||
mod_timer(&bn->timer, jiffies + bn->current_interval);
|
||||
}
|
||||
|
||||
static void bnge_sp_task(struct work_struct *work)
|
||||
{
|
||||
struct bnge_net *bn = container_of(work, struct bnge_net, sp_task);
|
||||
struct bnge_dev *bd = bn->bd;
|
||||
|
||||
netdev_lock(bn->netdev);
|
||||
if (!test_bit(BNGE_STATE_OPEN, &bd->state)) {
|
||||
netdev_unlock(bn->netdev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Event handling work added by later patches */
|
||||
|
||||
netdev_unlock(bn->netdev);
|
||||
}
|
||||
|
||||
static void bnge_free_nq_desc_arr(struct bnge_nq_ring_info *nqr)
|
||||
{
|
||||
struct bnge_ring_struct *ring = &nqr->ring_struct;
|
||||
|
|
@ -2507,6 +2537,9 @@ static int bnge_open_core(struct bnge_net *bn)
|
|||
bnge_enable_int(bn);
|
||||
|
||||
bnge_tx_enable(bn);
|
||||
|
||||
mod_timer(&bn->timer, jiffies + bn->current_interval);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
|
|
@ -2542,6 +2575,8 @@ static void bnge_close_core(struct bnge_net *bn)
|
|||
bnge_tx_disable(bn);
|
||||
|
||||
clear_bit(BNGE_STATE_OPEN, &bd->state);
|
||||
|
||||
timer_delete_sync(&bn->timer);
|
||||
bnge_shutdown_nic(bn);
|
||||
bnge_disable_napi(bn);
|
||||
bnge_free_all_rings_bufs(bn);
|
||||
|
|
@ -2774,6 +2809,18 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
|
|||
if (bd->tso_max_segs)
|
||||
netif_set_tso_max_segs(netdev, bd->tso_max_segs);
|
||||
|
||||
INIT_WORK(&bn->sp_task, bnge_sp_task);
|
||||
timer_setup(&bn->timer, bnge_timer, 0);
|
||||
bn->current_interval = BNGE_TIMER_INTERVAL;
|
||||
|
||||
bn->bnge_pf_wq = alloc_ordered_workqueue("bnge_pf_wq-%s", 0,
|
||||
dev_name(bd->dev));
|
||||
if (!bn->bnge_pf_wq) {
|
||||
netdev_err(netdev, "Unable to create workqueue.\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_netdev;
|
||||
}
|
||||
|
||||
bn->rx_ring_size = BNGE_DEFAULT_RX_RING_SIZE;
|
||||
bn->tx_ring_size = BNGE_DEFAULT_TX_RING_SIZE;
|
||||
bn->rx_dir = DMA_FROM_DEVICE;
|
||||
|
|
@ -2789,11 +2836,13 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
|
|||
rc = register_netdev(netdev);
|
||||
if (rc) {
|
||||
dev_err(bd->dev, "Register netdev failed rc: %d\n", rc);
|
||||
goto err_netdev;
|
||||
goto err_free_workq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_workq:
|
||||
destroy_workqueue(bn->bnge_pf_wq);
|
||||
err_netdev:
|
||||
free_netdev(netdev);
|
||||
return rc;
|
||||
|
|
@ -2802,8 +2851,16 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
|
|||
void bnge_netdev_free(struct bnge_dev *bd)
|
||||
{
|
||||
struct net_device *netdev = bd->netdev;
|
||||
struct bnge_net *bn;
|
||||
|
||||
bn = netdev_priv(netdev);
|
||||
|
||||
unregister_netdev(netdev);
|
||||
|
||||
timer_shutdown_sync(&bn->timer);
|
||||
cancel_work_sync(&bn->sp_task);
|
||||
destroy_workqueue(bn->bnge_pf_wq);
|
||||
|
||||
free_netdev(netdev);
|
||||
bd->netdev = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,6 +224,12 @@ struct bnge_tpa_info {
|
|||
#define BNGE_NQ_HDL_TYPE(hdl) (((hdl) & BNGE_NQ_HDL_TYPE_MASK) >> \
|
||||
BNGE_NQ_HDL_TYPE_SHIFT)
|
||||
|
||||
enum bnge_net_state {
|
||||
BNGE_STATE_NAPI_DISABLED,
|
||||
};
|
||||
|
||||
#define BNGE_TIMER_INTERVAL HZ
|
||||
|
||||
struct bnge_net {
|
||||
struct bnge_dev *bd;
|
||||
struct net_device *netdev;
|
||||
|
|
@ -281,13 +287,17 @@ struct bnge_net {
|
|||
u32 stats_coal_ticks;
|
||||
|
||||
unsigned long state;
|
||||
#define BNGE_STATE_NAPI_DISABLED 0
|
||||
|
||||
u32 msg_enable;
|
||||
u16 max_tpa;
|
||||
__be16 vxlan_port;
|
||||
__be16 nge_port;
|
||||
__be16 vxlan_gpe_port;
|
||||
|
||||
unsigned int current_interval;
|
||||
struct timer_list timer;
|
||||
struct workqueue_struct *bnge_pf_wq;
|
||||
struct work_struct sp_task;
|
||||
};
|
||||
|
||||
#define BNGE_DEFAULT_RX_RING_SIZE 511
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user