Skip to content

Commit 8070274

Browse files
xhackerustcPaolo Abeni
authored and
Paolo Abeni
committed
net: stmmac: fix incorrect rxq|txq_stats reference
commit 133466c ("net: stmmac: use per-queue 64 bit statistics where necessary") caused one regression as found by Uwe, the backtrace looks like: INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator. CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.5.0-rc1-00449-g133466c3bbe1-dirty #21 Hardware name: STM32 (Device Tree Support) unwind_backtrace from show_stack+0x18/0x1c show_stack from dump_stack_lvl+0x60/0x90 dump_stack_lvl from register_lock_class+0x98c/0x99c register_lock_class from __lock_acquire+0x74/0x293c __lock_acquire from lock_acquire+0x134/0x398 lock_acquire from stmmac_get_stats64+0x2ac/0x2fc stmmac_get_stats64 from dev_get_stats+0x44/0x130 dev_get_stats from rtnl_fill_stats+0x38/0x120 rtnl_fill_stats from rtnl_fill_ifinfo+0x834/0x17f4 rtnl_fill_ifinfo from rtmsg_ifinfo_build_skb+0xc0/0x144 rtmsg_ifinfo_build_skb from rtmsg_ifinfo+0x50/0x88 rtmsg_ifinfo from __dev_notify_flags+0xc0/0xec __dev_notify_flags from dev_change_flags+0x50/0x5c dev_change_flags from ip_auto_config+0x2f4/0x1260 ip_auto_config from do_one_initcall+0x70/0x35c do_one_initcall from kernel_init_freeable+0x2ac/0x308 kernel_init_freeable from kernel_init+0x1c/0x138 kernel_init from ret_from_fork+0x14/0x2c The reason is the rxq|txq_stats structures are not what expected because stmmac_open() -> __stmmac_open() the structure is overwritten by "memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf));" This causes the well initialized syncp member of rxq|txq_stats is overwritten unexpectedly as pointed out by Johannes and Uwe. Fix this issue by moving rxq|txq_stats back to stmmac_extra_stats. For SMP cache friendly, we also mark stmmac_txq_stats and stmmac_rxq_stats as ____cacheline_aligned_in_smp. Fixes: 133466c ("net: stmmac: use per-queue 64 bit statistics where necessary") Signed-off-by: Jisheng Zhang <jszhang@kernel.org> Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Tested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20230917165328.3403-1-jszhang@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 6dab9dd commit 8070274

File tree

8 files changed

+120
-110
lines changed

8 files changed

+120
-110
lines changed

drivers/net/ethernet/stmicro/stmmac/common.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct stmmac_txq_stats {
7070
u64 tx_tso_frames;
7171
u64 tx_tso_nfrags;
7272
struct u64_stats_sync syncp;
73-
};
73+
} ____cacheline_aligned_in_smp;
7474

7575
struct stmmac_rxq_stats {
7676
u64 rx_bytes;
@@ -79,7 +79,7 @@ struct stmmac_rxq_stats {
7979
u64 rx_normal_irq_n;
8080
u64 napi_poll;
8181
struct u64_stats_sync syncp;
82-
};
82+
} ____cacheline_aligned_in_smp;
8383

8484
/* Extra statistic and debug information exposed by ethtool */
8585
struct stmmac_extra_stats {
@@ -202,6 +202,9 @@ struct stmmac_extra_stats {
202202
unsigned long mtl_est_hlbf;
203203
unsigned long mtl_est_btre;
204204
unsigned long mtl_est_btrlm;
205+
/* per queue statistics */
206+
struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES];
207+
struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES];
205208
unsigned long rx_dropped;
206209
unsigned long rx_errors;
207210
unsigned long tx_dropped;

drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,8 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
441441
struct stmmac_extra_stats *x, u32 chan,
442442
u32 dir)
443443
{
444-
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
445-
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
444+
struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
445+
struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
446446
int ret = 0;
447447
u32 v;
448448

@@ -455,9 +455,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
455455

456456
if (v & EMAC_TX_INT) {
457457
ret |= handle_tx;
458-
u64_stats_update_begin(&tx_q->txq_stats.syncp);
459-
tx_q->txq_stats.tx_normal_irq_n++;
460-
u64_stats_update_end(&tx_q->txq_stats.syncp);
458+
u64_stats_update_begin(&txq_stats->syncp);
459+
txq_stats->tx_normal_irq_n++;
460+
u64_stats_update_end(&txq_stats->syncp);
461461
}
462462

463463
if (v & EMAC_TX_DMA_STOP_INT)
@@ -479,9 +479,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
479479

480480
if (v & EMAC_RX_INT) {
481481
ret |= handle_rx;
482-
u64_stats_update_begin(&rx_q->rxq_stats.syncp);
483-
rx_q->rxq_stats.rx_normal_irq_n++;
484-
u64_stats_update_end(&rx_q->rxq_stats.syncp);
482+
u64_stats_update_begin(&rxq_stats->syncp);
483+
rxq_stats->rx_normal_irq_n++;
484+
u64_stats_update_end(&rxq_stats->syncp);
485485
}
486486

487487
if (v & EMAC_RX_BUF_UA_INT)

drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
171171
const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
172172
u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
173173
u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
174-
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
175-
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
174+
struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
175+
struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
176176
int ret = 0;
177177

178178
if (dir == DMA_DIR_RX)
@@ -201,15 +201,15 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
201201
}
202202
/* TX/RX NORMAL interrupts */
203203
if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
204-
u64_stats_update_begin(&rx_q->rxq_stats.syncp);
205-
rx_q->rxq_stats.rx_normal_irq_n++;
206-
u64_stats_update_end(&rx_q->rxq_stats.syncp);
204+
u64_stats_update_begin(&rxq_stats->syncp);
205+
rxq_stats->rx_normal_irq_n++;
206+
u64_stats_update_end(&rxq_stats->syncp);
207207
ret |= handle_rx;
208208
}
209209
if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
210-
u64_stats_update_begin(&tx_q->txq_stats.syncp);
211-
tx_q->txq_stats.tx_normal_irq_n++;
212-
u64_stats_update_end(&tx_q->txq_stats.syncp);
210+
u64_stats_update_begin(&txq_stats->syncp);
211+
txq_stats->tx_normal_irq_n++;
212+
u64_stats_update_end(&txq_stats->syncp);
213213
ret |= handle_tx;
214214
}
215215

drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ static void show_rx_process_state(unsigned int status)
162162
int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
163163
struct stmmac_extra_stats *x, u32 chan, u32 dir)
164164
{
165-
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
166-
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
165+
struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
166+
struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
167167
int ret = 0;
168168
/* read the status register (CSR5) */
169169
u32 intr_status = readl(ioaddr + DMA_STATUS);
@@ -215,16 +215,16 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
215215
u32 value = readl(ioaddr + DMA_INTR_ENA);
216216
/* to schedule NAPI on real RIE event. */
217217
if (likely(value & DMA_INTR_ENA_RIE)) {
218-
u64_stats_update_begin(&rx_q->rxq_stats.syncp);
219-
rx_q->rxq_stats.rx_normal_irq_n++;
220-
u64_stats_update_end(&rx_q->rxq_stats.syncp);
218+
u64_stats_update_begin(&rxq_stats->syncp);
219+
rxq_stats->rx_normal_irq_n++;
220+
u64_stats_update_end(&rxq_stats->syncp);
221221
ret |= handle_rx;
222222
}
223223
}
224224
if (likely(intr_status & DMA_STATUS_TI)) {
225-
u64_stats_update_begin(&tx_q->txq_stats.syncp);
226-
tx_q->txq_stats.tx_normal_irq_n++;
227-
u64_stats_update_end(&tx_q->txq_stats.syncp);
225+
u64_stats_update_begin(&txq_stats->syncp);
226+
txq_stats->tx_normal_irq_n++;
227+
u64_stats_update_end(&txq_stats->syncp);
228228
ret |= handle_tx;
229229
}
230230
if (unlikely(intr_status & DMA_STATUS_ERI))

drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,8 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
337337
struct stmmac_extra_stats *x, u32 chan,
338338
u32 dir)
339339
{
340-
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
341-
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
340+
struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
341+
struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
342342
u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
343343
u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
344344
int ret = 0;
@@ -367,15 +367,15 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
367367
/* TX/RX NORMAL interrupts */
368368
if (likely(intr_status & XGMAC_NIS)) {
369369
if (likely(intr_status & XGMAC_RI)) {
370-
u64_stats_update_begin(&rx_q->rxq_stats.syncp);
371-
rx_q->rxq_stats.rx_normal_irq_n++;
372-
u64_stats_update_end(&rx_q->rxq_stats.syncp);
370+
u64_stats_update_begin(&rxq_stats->syncp);
371+
rxq_stats->rx_normal_irq_n++;
372+
u64_stats_update_end(&rxq_stats->syncp);
373373
ret |= handle_rx;
374374
}
375375
if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
376-
u64_stats_update_begin(&tx_q->txq_stats.syncp);
377-
tx_q->txq_stats.tx_normal_irq_n++;
378-
u64_stats_update_end(&tx_q->txq_stats.syncp);
376+
u64_stats_update_begin(&txq_stats->syncp);
377+
txq_stats->tx_normal_irq_n++;
378+
u64_stats_update_end(&txq_stats->syncp);
379379
ret |= handle_tx;
380380
}
381381
}

drivers/net/ethernet/stmicro/stmmac/stmmac.h

-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ struct stmmac_tx_queue {
7878
dma_addr_t dma_tx_phy;
7979
dma_addr_t tx_tail_addr;
8080
u32 mss;
81-
struct stmmac_txq_stats txq_stats;
8281
};
8382

8483
struct stmmac_rx_buffer {
@@ -123,7 +122,6 @@ struct stmmac_rx_queue {
123122
unsigned int len;
124123
unsigned int error;
125124
} state;
126-
struct stmmac_rxq_stats rxq_stats;
127125
};
128126

129127
struct stmmac_channel {

drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c

+16-16
Original file line numberDiff line numberDiff line change
@@ -548,14 +548,14 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
548548

549549
pos = data;
550550
for (q = 0; q < tx_cnt; q++) {
551-
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[q];
551+
struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q];
552552
struct stmmac_txq_stats snapshot;
553553

554554
data = pos;
555555
do {
556-
start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp);
557-
snapshot = tx_q->txq_stats;
558-
} while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start));
556+
start = u64_stats_fetch_begin(&txq_stats->syncp);
557+
snapshot = *txq_stats;
558+
} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
559559

560560
p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n);
561561
for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) {
@@ -566,14 +566,14 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
566566

567567
pos = data;
568568
for (q = 0; q < rx_cnt; q++) {
569-
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[q];
569+
struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q];
570570
struct stmmac_rxq_stats snapshot;
571571

572572
data = pos;
573573
do {
574-
start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp);
575-
snapshot = rx_q->rxq_stats;
576-
} while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start));
574+
start = u64_stats_fetch_begin(&rxq_stats->syncp);
575+
snapshot = *rxq_stats;
576+
} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
577577

578578
p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n);
579579
for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) {
@@ -637,14 +637,14 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
637637

638638
pos = j;
639639
for (i = 0; i < rx_queues_count; i++) {
640-
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[i];
640+
struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[i];
641641
struct stmmac_rxq_stats snapshot;
642642

643643
j = pos;
644644
do {
645-
start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp);
646-
snapshot = rx_q->rxq_stats;
647-
} while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start));
645+
start = u64_stats_fetch_begin(&rxq_stats->syncp);
646+
snapshot = *rxq_stats;
647+
} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
648648

649649
data[j++] += snapshot.rx_pkt_n;
650650
data[j++] += snapshot.rx_normal_irq_n;
@@ -654,14 +654,14 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
654654

655655
pos = j;
656656
for (i = 0; i < tx_queues_count; i++) {
657-
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[i];
657+
struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[i];
658658
struct stmmac_txq_stats snapshot;
659659

660660
j = pos;
661661
do {
662-
start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp);
663-
snapshot = tx_q->txq_stats;
664-
} while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start));
662+
start = u64_stats_fetch_begin(&txq_stats->syncp);
663+
snapshot = *txq_stats;
664+
} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
665665

666666
data[j++] += snapshot.tx_pkt_n;
667667
data[j++] += snapshot.tx_normal_irq_n;

0 commit comments

Comments
 (0)