This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

  • TI Thinks Resolved

Linux/AM5728: Kernel Page allocation failure while using the network subsytem

Prodigy 150 points

Replies: 1

Views: 1682

Part Number: AM5728

Tool/software: Linux

I am developing a driver for exchanging data by using psnap(skb buff) modules.But I am getting the following crash. My kernel version is 4.9.41.

 , *pmd=00000000[  125.914637] Internal error: Oops: 206 [#4] PREEMPT SMP ARM
[  125.920145] Modules linked in: sample_gadget(O) libcomposite(O) psnap(O) 
llc(O) bc_example(O) sha512_generic sha512_arm sha256_generic sha1_generic sha1)
[  126.000132] CPU: 1 PID: 500 Comm: systemd-logind Tainted: G      D    O    4.9.41-ge3a80a1c5c #1
[  126.008949] Hardware name: Generic DRA74X (Flattened Device Tree)
[  126.015064] task: ed210000 task.stack: ed31c000
[  126.019621] PC is at __kmalloc_track_caller+0xa8/0x1d8
[  126.019671] Unable to handle kernel paging request at virtual address 01092a85
[  126.019675] pgd = d57867c0
[  126.019681] [01092a85] *pgd=95795003, *pmd=00000000
[  126.039624] LR is at get_mem_cgroup_from_mm+0xd4/0x12c
[  126.044781] pc : [<c03209fc>]    lr : [<c0323414>]    psr: 200f0013
[  126.044781] sp : ed31dc78  ip : ed31dc30  fp : ed31dc9c
[  126.056303] r10: 00000000  r9 : 00001d1e  r8 : ed31dc78
[  126.061547] r7 : ed31c000  r6 : 01092a85  r5 : 025106c0  r4 : ee801c00
[  126.068098] r3 : 00000000  r2 : 2deda000  r1 : 00001d1e  r0 : ee801c00
[  126.074650] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
[  126.081812] Control: 30c5387d  Table: ad24bd80  DAC: 55555555
[  126.087578] Process systemd-logind (pid: 500, stack limit = 0xed31c210)

[  126.336637] Backtrace: 
[  126.339103] [<c0320954>] (__kmalloc_track_caller) from [<c079e308>] (__kmalloc_reserve.constprop.15+0x2c/0x78)
[  126.349144]  r9:0000000a r8:00000100 r7:c079fd74 r6:025004c0 r5:025004c0 r4:ed31dccf
[  126.356920] [<c079e2dc>] (__kmalloc_reserve.constprop.15) from [<c079fd74>] (__alloc_skb+0x60/0x144)
[  126.366088]  r9:0000000a r8:00000000 r7:ee801cc0 r6:025004c0 r5:0000000a r4:ca4da240
[  126.373864] [<c079fd14>] (__alloc_skb) from [<c079fea8>] (alloc_skb_with_frags+0x50/0x1d4)
[  126.382160]  r9:0000000a r8:00000003 r7:c026e1f8 r6:00000000 r5:7fffffff r4:ee01de40
[  126.389935] [<c079fe58>] (alloc_skb_with_frags) from [<c07968b8>] (sock_alloc_send_pskb+0x1f0/0x20c)
[  126.399104]  r10:00000000 r9:0000000a r8:ee01df84 r7:c026e1f8 r6:ed31c000 r5:7fffffff
[  126.406960]  r4:ee01de40
[  126.409505] [<c07966c8>] (sock_alloc_send_pskb) from [<c084d8b8>] (unix_dgram_sendmsg+0x138/0x648)
[  126.418500]  r10:00000016 r9:00000000 r8:0000000a r7:dff2b500 r6:ee01de40 r5:ed31df48
[  126.426356]  r4:00000000
[  126.428901] [<c084d780>] (unix_dgram_sendmsg) from [<c07942ac>] (sock_sendmsg+0x1c/0x2c)
[  126.437023]  r10:00004000 r9:00000000 r8:ed31de28 r7:dff2b500 r6:00000000 r5:00000000
[  126.444880]  r4:ed31df48
[  126.447423] [<c0794290>] (sock_sendmsg) from [<c0794808>] (___sys_sendmsg+0x1d8/0x1e8)
[  126.455371] [<c0794630>] (___sys_sendmsg) from [<c079553c>] (__sys_sendmsg+0x48/0x74)
[  126.463231]  r10:00000000 r9:ed31c000 r8:c0207d84 r7:00000128 r6:dff2b500 r5:00004000
[  126.471089]  r4:be80da10
[  126.473630] [<c07954f4>] (__sys_sendmsg) from [<c0795578>] (SyS_sendmsg+0x10/0x14)
[  126.481227]  r6:00000010 r5:be80dfa3 r4:be80da10
[  126.485864] [<c0795568>] (SyS_sendmsg) from [<c0207be0>] (ret_fast_syscall+0x0/0x34)

This is my sample code I used for sending data,

int tx_data(void *buf, uint16_t len) 
{ 
struct sk_buff *skb = NULL; 
uint16_t hdr_len; 

hdr_len = dll_dev->net_dev->hard_header_len + 8; 

skb = alloc_skb(hdr_len + len, GFP_ATOMIC); 
if (skb == NULL) 
return -ENOMEM; 

skb_reserve(skb, hdr_len); 
skb_reset_transport_header(skb); 
skb_reset_network_header(skb); 
skb->dev = dll_dev->net_dev; 

memcpy(skb->data, buf, len); 
skb_put(skb, len); 
dll_dev->proto->request(dll_dev->proto, skb, dll_dev->dmac); 

return 0; 
}

Usually The sk_buff is allocated by me on the send side through "alloc_skb" and given to the network. It's basically free'd by the network driver after send. But I am suspecting skb is not freeing by network driver. Is there a way to ensure the network driver is freeing skb properly.

  • Hi,

    See:
    www.linuxjournal.com/.../1312
    "kfree_skb() releases a buffer, and if skb->sk is set, it lowers the memory use counts of the socket (sk). It is up to the socket and protocol-level routines to increment these counts and to avoid freeing a socket with outstanding buffers. The memory counts are very important, as the kernel networking layers need to know how much memory is tied up by each connection in order to prevent remote machines or local processes from using too much memory"

    www.linuxjournal.com/.../1312
    "The very important line is skb->sk=sk. The sock_alloc_send_skb() has charged the memory for the buffer to the socket. By setting skb->sk, we tell the kernel that whoever does a kfree_skb() on the buffer should credit the memory for the buffer to the socket. Thus, when a device has sent a buffer and freed it, the user is able to send more."

    Also refer to the description of kfree_skb():
    www.cs.bham.ac.uk/.../r6776.html
    "Drop a reference to the buffer and free it if the usage count has hit zero."

    So you should monitor the usage count to see if the socket uses your buffer.

    Best Regards,
    Yordan

     


     Please make sure you read the forum guidelines first.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.