Subject: Re: skb allocation from interrupt handler?

From: Murali Karicheri <[email-masked]>
Date: Wed, 9 Aug 2017 12:04:57 -0400

On 08/08/2017 06:29 PM, Matteo Croce wrote:
> netdev_alloc_skb() passes GFP_ATOMIC to alloc_skb() so it should work
> in an interrupt handler too.

I will provide more background on my work as response to your next 
response. This is running RT Linux kernel. I have CONFIG_IRQ_FORCED_THREADING
enabled. So my understanding is that the irq handler will be executed as
part of a kernel thread. So it is not actually from a hard irq context.
Correct? 

So what why does the following trace complains?

root@am57xx-evm:~# [  108.745031] BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:987
[  108.745035] in_atomic(): 1, irqs_disabled(): 128, pid: 0, name: swapper/0
[  108.745038] no locks held by swapper/0/0.
[  108.745040] irq event stamp: 292222
[  108.745054] hardirqs last  enabled at (292221): [<c0208eb0>] arch_cpu_idle+0x20/0x3c
[  108.745060] hardirqs last disabled at (292222): [<c020c8ac>] __irq_svc+0x4c/0xa8
[  108.745063] softirqs last  enabled at (0): [<  (null)>]   (null)
[  108.745066] softirqs last disabled at (0): [<  (null)>]   (null)
[  108.745076] Preemption disabled at:
[  108.745077] [<c0936f24>] schedule_preempt_disabled+0x1c/0x20
[  108.745084] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.9.38-rt23-02686-gc7fcc4e7-dirty #4
[  108.745087] Hardware name: Generic DRA74X (Flattened Device Tree)
[  108.745100] [<c021007c>] (unwind_backtrace) from [<c020bdcc>] (show_stack+0x10/0x14)
[  108.745111] [<c020bdcc>] (show_stack) from [<c0517780>] (dump_stack+0x98/0xc4)
[  108.745122] [<c0517780>] (dump_stack) from [<c0256a70>] (___might_sleep+0x1b8/0x2a4)
[  108.745133] [<c0256a70>] (___might_sleep) from [<c0939e80>] (rt_spin_lock+0x24/0x5c)
[  108.745143] [<c0939e80>] (rt_spin_lock) from [<c07d827c>] (__netdev_alloc_skb+0xd0/0x254)
[  108.745166] [<c07d827c>] (__netdev_alloc_skb) from [<bf23a544>] (emac_rx_hardirq+0x374/0x554 [prueth])
[  108.745212] [<bf23a544>] (emac_rx_hardirq [prueth]) from [<c02925dc>] (__handle_irq_event_percpu+0x9c/0x128)
[  108.745221] [<c02925dc>] (__handle_irq_event_percpu) from [<c02926b0>] (handle_irq_event_percpu+0x48/0x84)
[  108.745229] [<c02926b0>] (handle_irq_event_percpu) from [<c0292724>] (handle_irq_event+0x38/0x5c)
[  108.745238] [<c0292724>] (handle_irq_event) from [<c0295b1c>] (handle_level_irq+0xc4/0x16c)
[  108.745246] [<c0295b1c>] (handle_level_irq) from [<c0291880>] (generic_handle_irq+0x24/0x34)
[  108.745257] [<c0291880>] (generic_handle_irq) from [<bf214244>] (pruss_intc_irq_handler+0xdc/0x130 [pruss_intc])
[  108.745270] [<bf214244>] (pruss_intc_irq_handler [pruss_intc]) from [<c0291880>] (generic_handle_irq+0x24/0x34)
[  108.745277] [<c0291880>] (generic_handle_irq) from [<c0291de0>] (__handle_domain_irq+0x7c/0xec)
[  108.745284] [<c0291de0>] (__handle_domain_irq) from [<c020154c>] (gic_handle_irq+0x48/0x8c)
[  108.745290] [<c020154c>] (gic_handle_irq) from [<c020c8bc>] (__irq_svc+0x5c/0xa8)

Here is the code snippet. This is part of an experiment, that I will explain in
the next message where you have talked about NAPI.

	skb = netdev_alloc_skb(ndev, pkt_info.length + 2);
	if (!skb) {
		if (netif_msg_rx_err(emac) && net_ratelimit())
			netdev_err(ndev, "failed rx buffer alloc\n");
		return -ENOMEM;
	}

        <====== Code to get the packet from the firmware FIFO =====>
	/* send packet up the stack */
	skb_put(skb, pkt_info.length);
	skb->protocol = eth_type_trans(skb, ndev);
	netif_rx(skb);

	/* update stats */
	ndev->stats.rx_bytes += pkt_info.length;
	ndev->stats.rx_packets++;

Also want to know if there is a real SKB alloc function that can be used from
hard irq context.

-- 
Murali Karicheri
Linux Kernel, Keystone