]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: wangxun: schedule hardware stats update in watchdog
authorJiawen Wu <jiawenwu@trustnetic.com>
Tue, 7 Apr 2026 02:56:14 +0000 (10:56 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 15:42:28 +0000 (08:42 -0700)
Hardware statistics should be updated periodically in the watchdog to
prevent 32-bit registers from overflowing. This is also required for the
upcoming pause frame accounting logic, which relies on regular statistics
sampling.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20260407025616.33652-8-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ethernet/wangxun/libwx/wx_type.h
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c

index 05731a50d85ffbeeeef5d052a551f48cc0a9b3ab..31259f69c0e2ff325423467c2bc25013f92f25e5 100644 (file)
@@ -2513,6 +2513,7 @@ int wx_sw_init(struct wx *wx)
                return -ENOMEM;
        }
 
+       spin_lock_init(&wx->hw_stats_lock);
        mutex_init(&wx->reset_lock);
        bitmap_zero(wx->state, WX_STATE_NBITS);
        bitmap_zero(wx->flags, WX_PF_FLAGS_NBITS);
@@ -2845,6 +2846,12 @@ void wx_update_stats(struct wx *wx)
        u64 restart_queue = 0, tx_busy = 0;
        u32 i;
 
+       if (!netif_running(wx->netdev) ||
+           test_bit(WX_STATE_RESETTING, wx->state))
+               return;
+
+       spin_lock(&wx->hw_stats_lock);
+
        /* gather some stats to the wx struct that are per queue */
        for (i = 0; i < wx->num_rx_queues; i++) {
                struct wx_ring *rx_ring = wx->rx_ring[i];
@@ -2913,6 +2920,8 @@ void wx_update_stats(struct wx *wx)
        for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
             i < wx->mac.max_rx_queues; i++)
                hwstats->qmprc += rd32(wx, WX_PX_MPRC(i));
+
+       spin_unlock(&wx->hw_stats_lock);
 }
 EXPORT_SYMBOL(wx_update_stats);
 
index 0fbdda63b1419cbfe9f9c40474ae72be6e5ba94f..7831c5035be88124a21545cf2295821f022c407b 100644 (file)
@@ -1354,6 +1354,7 @@ struct wx {
        bool default_up;
 
        struct wx_hw_stats stats;
+       spinlock_t hw_stats_lock; /* spinlock for accessing to hw stats */
        u64 tx_busy;
        u64 non_eop_descs;
        u64 restart_queue;
index 8c9d505721b17f47ddd1b8a94ffa1f7dd3e8bc9a..d8e3827a8b1f24266d18eedd44272416ae64d673 100644 (file)
@@ -138,6 +138,26 @@ static int ngbe_sw_init(struct wx *wx)
        return 0;
 }
 
+/**
+ * ngbe_service_task - manages and runs subtasks
+ * @work: pointer to work_struct containing our data
+ **/
+static void ngbe_service_task(struct work_struct *work)
+{
+       struct wx *wx = container_of(work, struct wx, service_task);
+
+       wx_update_stats(wx);
+
+       wx_service_event_complete(wx);
+}
+
+static void ngbe_init_service(struct wx *wx)
+{
+       timer_setup(&wx->service_timer, wx_service_timer, 0);
+       INIT_WORK(&wx->service_task, ngbe_service_task);
+       clear_bit(WX_STATE_SERVICE_SCHED, wx->state);
+}
+
 /**
  * ngbe_irq_enable - Enable default interrupt generation settings
  * @wx: board private structure
@@ -368,6 +388,10 @@ static void ngbe_disable_device(struct wx *wx)
        wx_napi_disable_all(wx);
        netif_tx_stop_all_queues(netdev);
        netif_tx_disable(netdev);
+
+       timer_delete_sync(&wx->service_timer);
+       cancel_work_sync(&wx->service_task);
+
        if (wx->gpio_ctrl)
                ngbe_sfp_modules_txrx_powerctl(wx, false);
        wx_irq_disable(wx);
@@ -407,6 +431,7 @@ void ngbe_up(struct wx *wx)
        wx_napi_enable_all(wx);
        /* enable transmits */
        netif_tx_start_all_queues(wx->netdev);
+       mod_timer(&wx->service_timer, jiffies);
 
        /* clear any pending interrupts, may auto mask */
        rd32(wx, WX_PX_IC(0));
@@ -770,9 +795,11 @@ static int ngbe_probe(struct pci_dev *pdev,
        eth_hw_addr_set(netdev, wx->mac.perm_addr);
        wx_mac_set_default_filter(wx, wx->mac.perm_addr);
 
+       ngbe_init_service(wx);
+
        err = wx_init_interrupt_scheme(wx);
        if (err)
-               goto err_free_mac_table;
+               goto err_cancel_service;
 
        /* phy Interface Configuration */
        err = ngbe_mdio_init(wx);
@@ -792,6 +819,9 @@ err_register:
        wx_control_hw(wx, false);
 err_clear_interrupt_scheme:
        wx_clear_interrupt_scheme(wx);
+err_cancel_service:
+       timer_delete_sync(&wx->service_timer);
+       cancel_work_sync(&wx->service_task);
 err_free_mac_table:
        kfree(wx->rss_key);
        kfree(wx->mac_table);
@@ -820,6 +850,10 @@ static void ngbe_remove(struct pci_dev *pdev)
        netdev = wx->netdev;
        wx_disable_sriov(wx);
        unregister_netdev(netdev);
+
+       timer_shutdown_sync(&wx->service_timer);
+       cancel_work_sync(&wx->service_task);
+
        phylink_destroy(wx->phylink);
        pci_release_selected_regions(pdev,
                                     pci_select_bars(pdev, IORESOURCE_MEM));
index 0dd128aa18da949fc6e609457481629ecf63caf5..ec32a5f422f2d83571445576e8f7ff81906a7b52 100644 (file)
@@ -130,6 +130,7 @@ static void txgbe_service_task(struct work_struct *work)
 
        txgbe_module_detection_subtask(wx);
        txgbe_link_config_subtask(wx);
+       wx_update_stats(wx);
 
        wx_service_event_complete(wx);
 }