Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,30 @@ static void mtk_stats_update(struct mtk_eth *eth)
}
}

/* MTK_GDM1_AF and MTK_GDM2_AF describe a two-GDM frame engine and are the
* only trigger the driver has for draining the counters from the hot path.
* On NETSYS v3 that trigger does not fire, so drain them on a timer as well.
*/
static void mtk_stats_work(struct work_struct *work)
{
struct delayed_work *del_work = to_delayed_work(work);
struct mtk_eth *eth = container_of(del_work, struct mtk_eth,
stats_work);

if (test_bit(MTK_HW_INIT, &eth->state) &&
!test_bit(MTK_RESETTING, &eth->state)) {
/* mtk_stats_update() is written for the NAPI path and takes
* stats_lock with spin_trylock(). Keep the lock out of two
* different contexts.
*/
local_bh_disable();
mtk_stats_update(eth);
local_bh_enable();
}

schedule_delayed_work(&eth->stats_work, MTK_STATS_DRAIN_TIMEOUT);
}

static void mtk_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *storage)
{
Expand Down Expand Up @@ -5078,6 +5102,7 @@ static int mtk_cleanup(struct mtk_eth *eth)
mtk_free_dev(eth);
cancel_work_sync(&eth->pending_work);
cancel_delayed_work_sync(&eth->reset.monitor_work);
cancel_delayed_work_sync(&eth->stats_work);

return 0;
}
Expand Down Expand Up @@ -6134,6 +6159,7 @@ static int mtk_probe(struct platform_device *pdev)
INIT_WORK(&eth->rx_dim.work, mtk_dim_rx);
atomic_set(&eth->reset.force, 0);
INIT_DELAYED_WORK(&eth->reset.monitor_work, mtk_hw_reset_monitor_work);
INIT_DELAYED_WORK(&eth->stats_work, mtk_stats_work);

eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
INIT_WORK(&eth->tx_dim.work, mtk_dim_tx);
Expand Down Expand Up @@ -6465,6 +6491,7 @@ static int mtk_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, eth);
schedule_delayed_work(&eth->reset.monitor_work,
MTK_DMA_MONITOR_TIMEOUT);
schedule_delayed_work(&eth->stats_work, MTK_STATS_DRAIN_TIMEOUT);

return 0;

Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,12 @@ struct mtk_soc_data {

#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000)

/* The GDM MIB counters are clear-on-read and the packet counters are only
* 32 bits wide, so they have to be drained on a schedule rather than only
* when something asks for statistics.
*/
#define MTK_STATS_DRAIN_TIMEOUT msecs_to_jiffies(1000)

/* currently no SoC has more than 3 macs */
#define MTK_MAX_DEVS 3

Expand Down Expand Up @@ -1570,6 +1576,9 @@ struct mtk_eth {

const struct mtk_soc_data *soc;

/* periodic drain of the clear-on-read GDM MIB counters */
struct delayed_work stats_work;

spinlock_t dim_lock;

u32 rx_events;
Expand Down