Skip to content

Commit 71947f0

Browse files
committed
Merge branch 'mediatek-tx-bugs'
Sean Wang says: ==================== mediatek: Fix crash caused by reporting inconsistent skb->len to BQL Changes since v1: - fix inconsistent enumeration which easily causes the potential bug The series fixes kernel BUG caused by inconsistent SKB length reported into BQL. The reason for inconsistent length comes from hardware BUG which results in different port number carried on the TXD within the lifecycle of SKB. So patch 2) is proposed for use a software way to track which port the SKB involving instead of hardware way. And patch 1) is given for another issue I found which causes TXD and SKB inconsistency that is not expected in the initial logic, so it is also being corrected it in the series. The log for the kernel BUG caused by the issue is posted as below. [ 120.825955] kernel BUG at ... lib/dynamic_queue_limits.c:26! [ 120.837684] Internal error: Oops - BUG: 0 [#1] SMP ARM [ 120.842778] Modules linked in: [ 120.845811] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.11.0-rc1-191576-gdbcef47 #35 [ 120.853488] Hardware name: Mediatek Cortex-A7 (Device Tree) [ 120.859012] task: c1007480 task.stack: c1000000 [ 120.863510] PC is at dql_completed+0x108/0x17c [ 120.867915] LR is at 0x46 [ 120.870512] pc : [<c03c19c8>] lr : [<00000046>] psr: 80000113 [ 120.870512] sp : c1001d58 ip : c1001d80 fp : c1001d7c [ 120.881895] r10: 0000003e r9 : df6b3400 r8 : 0ed86506 [ 120.887075] r7 : 00000001 r6 : 00000001 r5 : 0ed8654c r4 : df0135d8 [ 120.893546] r3 : 00000001 r2 : df016800 r1 : 0000fece r0 : df6b3480 [ 120.900018] Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none [ 120.907093] Control: 10c5387d Table: 9e27806a DAC: 00000051 [ 120.912789] Process swapper/0 (pid: 0, stack limit = 0xc1000218) [ 120.918744] Stack: (0xc1001d58 to 0xc1002000) .... 121.085331] 1fc0: 00000000 c0a52a28 00000000 c10855d4 c1003c58 c0a52a24 c100885c 8000406 [ 121.093444] 1fe0: 410fc073 00000000 00000000 c1001ff8 8000807c c0a009cc 00000000 00000000 [ 121.101575] [<c03c19c8>] (dql_completed) from [<c04cb010>] (mtk_napi_tx+0x1d0/0x37c) [ 121.109263] [<c04cb010>] (mtk_napi_tx) from [<c05e28cc>] (net_rx_action+0x24c/0x3b8) [ 121.116951] [<c05e28cc>] (net_rx_action) from [<c010152c>] (__do_softirq+0xe4/0x35c) [ 121.124638] [<c010152c>] (__do_softirq) from [<c012a624>] (irq_exit+0xe8/0x150) [ 121.131895] [<c012a624>] (irq_exit) from [<c017750c>] (__handle_domain_irq+0x70/0xc4) [ 121.139666] [<c017750c>] (__handle_domain_irq) from [<c0101404>] (gic_handle_irq+0x58/0x9c) [ 121.147953] [<c0101404>] (gic_handle_irq) from [<c010e18c>] (__irq_svc+0x6c/0x90) [ 121.155373] Exception stack(0xc1001ef8 to 0xc1001f40) ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents bfe7244 + 134d215 commit 71947f0

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

drivers/net/ethernet/mediatek/mtk_eth_soc.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
613613
struct mtk_mac *mac = netdev_priv(dev);
614614
struct mtk_eth *eth = mac->hw;
615615
struct mtk_tx_dma *itxd, *txd;
616-
struct mtk_tx_buf *tx_buf;
616+
struct mtk_tx_buf *itx_buf, *tx_buf;
617617
dma_addr_t mapped_addr;
618618
unsigned int nr_frags;
619619
int i, n_desc = 1;
@@ -627,8 +627,8 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
627627
fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
628628
txd4 |= fport;
629629

630-
tx_buf = mtk_desc_to_tx_buf(ring, itxd);
631-
memset(tx_buf, 0, sizeof(*tx_buf));
630+
itx_buf = mtk_desc_to_tx_buf(ring, itxd);
631+
memset(itx_buf, 0, sizeof(*itx_buf));
632632

633633
if (gso)
634634
txd4 |= TX_DMA_TSO;
@@ -647,9 +647,11 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
647647
return -ENOMEM;
648648

649649
WRITE_ONCE(itxd->txd1, mapped_addr);
650-
tx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
651-
dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
652-
dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb));
650+
itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
651+
itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
652+
MTK_TX_FLAGS_FPORT1;
653+
dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr);
654+
dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb));
653655

654656
/* TX SG offload */
655657
txd = itxd;
@@ -685,11 +687,13 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
685687
last_frag * TX_DMA_LS0));
686688
WRITE_ONCE(txd->txd4, fport);
687689

688-
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
689690
tx_buf = mtk_desc_to_tx_buf(ring, txd);
690691
memset(tx_buf, 0, sizeof(*tx_buf));
691-
692+
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
692693
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
694+
tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
695+
MTK_TX_FLAGS_FPORT1;
696+
693697
dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
694698
dma_unmap_len_set(tx_buf, dma_len0, frag_map_size);
695699
frag_size -= frag_map_size;
@@ -698,7 +702,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
698702
}
699703

700704
/* store skb to cleanup */
701-
tx_buf->skb = skb;
705+
itx_buf->skb = skb;
702706

703707
WRITE_ONCE(itxd->txd4, txd4);
704708
WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
@@ -1012,17 +1016,16 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
10121016

10131017
while ((cpu != dma) && budget) {
10141018
u32 next_cpu = desc->txd2;
1015-
int mac;
1019+
int mac = 0;
10161020

10171021
desc = mtk_qdma_phys_to_virt(ring, desc->txd2);
10181022
if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0)
10191023
break;
10201024

1021-
mac = (desc->txd4 >> TX_DMA_FPORT_SHIFT) &
1022-
TX_DMA_FPORT_MASK;
1023-
mac--;
1024-
10251025
tx_buf = mtk_desc_to_tx_buf(ring, desc);
1026+
if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
1027+
mac = 1;
1028+
10261029
skb = tx_buf->skb;
10271030
if (!skb) {
10281031
condition = 1;

drivers/net/ethernet/mediatek/mtk_eth_soc.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,18 @@ struct mtk_hw_stats {
406406
struct u64_stats_sync syncp;
407407
};
408408

409-
/* PDMA descriptor can point at 1-2 segments. This enum allows us to track how
410-
* memory was allocated so that it can be freed properly
411-
*/
412409
enum mtk_tx_flags {
410+
/* PDMA descriptor can point at 1-2 segments. This enum allows us to
411+
* track how memory was allocated so that it can be freed properly.
412+
*/
413413
MTK_TX_FLAGS_SINGLE0 = 0x01,
414414
MTK_TX_FLAGS_PAGE0 = 0x02,
415+
416+
/* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted
417+
* SKB out instead of looking up through hardware TX descriptor.
418+
*/
419+
MTK_TX_FLAGS_FPORT0 = 0x04,
420+
MTK_TX_FLAGS_FPORT1 = 0x08,
415421
};
416422

417423
/* This enum allows us to identify how the clock is defined on the array of the

0 commit comments

Comments
 (0)