Skip to content

Commit 8f28e7c

Browse files
committed
net: stmmac: fix oops when split header is enabled
For GMAC4, when split header is enabled, in some rare cases, the hardware does not fill buf2 of the first descriptor with payload. Thus we cannot assume buf2 is always fully filled if it is not the last descriptor. Otherwise, the length of buf2 of the second descriptor will be calculated wrong and cause an oops: Unable to handle kernel paging request at virtual address ffff00019246bfc0 Mem abort info: ESR = 0x0000000096000145 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x05: level 1 translation fault Data abort info: ISV = 0, ISS = 0x00000145, ISS2 = 0x00000000 CM = 1, WnR = 1, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000090d8b000 [ffff00019246bfc0] pgd=180000009dfff403, p4d=180000009dfff403, pud=0000000000000000 Internal error: Oops: 0000000096000145 [#1] SMP Modules linked in: CPU: 0 UID: 0 PID: 157 Comm: iperf3 Not tainted 6.18.0-rc6 #1 PREEMPT Hardware name: ADI 64-bit SC598 SOM EZ Kit (DT) pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : dcache_inval_poc+0x28/0x58 lr : arch_sync_dma_for_cpu+0x28/0x34 sp : ffff800080dcbc40 x29: ffff800080dcbc40 x28: 0000000000000008 x27: ffff000091c50980 x26: ffff000091c50980 x25: 0000000000000000 x24: ffff000092a5fb00 x23: ffff000092768f28 x22: 000000009246c000 x21: 0000000000000002 x20: 00000000ffffffdc x19: ffff000091844c10 x18: 0000000000000000 x17: ffff80001d308000 x16: ffff800080dc8000 x15: ffff0000929fb034 x14: 70f709157374dd21 x13: ffff000092812ec0 x12: 0000000000000000 x11: 000000000000dd86 x10: 0000000000000040 x9 : 0000000000000600 x8 : ffff000092a5fbac x7 : 0000000000000001 x6 : 0000000000004240 x5 : 000000009246c000 x4 : ffff000091844c10 x3 : 000000000000003f x2 : 0000000000000040 x1 : ffff00019246bfc0 x0 : ffff00009246c000 Call trace: dcache_inval_poc+0x28/0x58 (P) dma_direct_sync_single_for_cpu+0x38/0x6c __dma_sync_single_for_cpu+0x34/0x6c stmmac_napi_poll_rx+0x8f0/0xb60 __napi_poll.constprop.0+0x30/0x144 net_rx_action+0x160/0x274 handle_softirqs+0x1b8/0x1fc __do_softirq+0x10/0x18 ____do_softirq+0xc/0x14 call_on_irq_stack+0x30/0x48 do_softirq_own_stack+0x18/0x20 __irq_exit_rcu+0x64/0xe8 irq_exit_rcu+0xc/0x14 el1_interrupt+0x3c/0x58 el1h_64_irq_handler+0x14/0x1c el1h_64_irq+0x6c/0x70 __arch_copy_to_user+0xbc/0x240 (P) simple_copy_to_iter+0x28/0x30 __skb_datagram_iter+0x1bc/0x268 skb_copy_datagram_iter+0x1c/0x24 tcp_recvmsg_locked+0x3ec/0x778 tcp_recvmsg+0x10c/0x194 inet_recvmsg+0x64/0xa0 sock_recvmsg_nosec+0x1c/0x24 sock_read_iter+0x8c/0xdc vfs_read+0x144/0x1a0 ksys_read+0x74/0xdc __arm64_sys_read+0x14/0x1c invoke_syscall+0x60/0xe4 el0_svc_common.constprop.0+0xb0/0xcc do_el0_svc+0x18/0x20 el0_svc+0x80/0xc8 el0t_64_sync_handler+0x58/0x134 el0t_64_sync+0x170/0x174 Code: d1000443 ea03003f 8a230021 54000040 (d50b7e21) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Oops: Fatal exception in interrupt Kernel Offset: disabled CPU features: 0x080000,00008000,08006281,0400520b Memory Limit: none ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]--- To fix this, the PL bit-field in RDES3 register is used for all descriptors, whether it is the last descriptor or not. Signed-off-by: Jie Zhang <jie.zhang@analog.com>
1 parent e484297 commit 8f28e7c

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4884,13 +4884,26 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv,
48844884
if (!priv->sph)
48854885
return 0;
48864886

4887-
/* Not last descriptor */
4888-
if (status & rx_not_ls)
4887+
/* For GMAC4, when split header is enabled, in some rare cases, the
4888+
* hardware does not fill buf2 of the first descriptor with payload.
4889+
* Thus we cannot assume buf2 is always fully filled if it is not
4890+
* the last descriptor. Otherwise, the length of buf2 of the second
4891+
* descriptor will be calculated wrong and cause an oops.
4892+
*
4893+
* If this is the last descriptor, PLEN is the length of the received
4894+
* packet that was transferred to system memory. Otherwise, it is the
4895+
* accumulated number of bytes that have been transferred for the
4896+
* current packet.
4897+
*
4898+
* Thus (PLEN - LEN) always gives the correct length of buf2.
4899+
*/
4900+
if (!priv->plat->has_gmac4 &&
4901+
/* Not last descriptor */
4902+
(status & rx_not_ls))
48894903
return priv->dma_conf.dma_buf_sz;
48904904

48914905
plen = stmmac_get_rx_frame_len(priv, p, coe);
48924906

4893-
/* Last descriptor */
48944907
return plen - len;
48954908
}
48964909

0 commit comments

Comments
 (0)