Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3578b0c8 authored by David S. Miller's avatar David S. Miller
Browse files

Revert "net: remove zap_completion_queue"



This reverts commit 15e83ed7.

As explained by Johannes Berg, the optimization made here is
invalid.  Or, at best, incomplete.

Not only destructor invocation, but conntract entry releasing
must be executed outside of hw IRQ context.

So just checking "skb->destructor" is insufficient.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a427615e
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -1591,9 +1591,7 @@ EXPORT_SYMBOL(__netif_schedule);

void dev_kfree_skb_irq(struct sk_buff *skb)
{
	if (!skb->destructor)
		dev_kfree_skb(skb);
	else if (atomic_dec_and_test(&skb->users)) {
	if (atomic_dec_and_test(&skb->users)) {
		struct softnet_data *sd;
		unsigned long flags;

+31 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ static atomic_t trapped;
		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
				sizeof(struct iphdr) + sizeof(struct ethhdr))

static void zap_completion_queue(void);
static void arp_reply(struct sk_buff *skb);

static unsigned int carrier_timeout = 4;
@@ -196,6 +197,7 @@ void netpoll_poll_dev(struct net_device *dev)

	service_arp_queue(dev->npinfo);

	zap_completion_queue();
}
EXPORT_SYMBOL(netpoll_poll_dev);

@@ -221,11 +223,40 @@ static void refill_skbs(void)
	spin_unlock_irqrestore(&skb_pool.lock, flags);
}

static void zap_completion_queue(void)
{
	unsigned long flags;
	struct softnet_data *sd = &get_cpu_var(softnet_data);

	if (sd->completion_queue) {
		struct sk_buff *clist;

		local_irq_save(flags);
		clist = sd->completion_queue;
		sd->completion_queue = NULL;
		local_irq_restore(flags);

		while (clist != NULL) {
			struct sk_buff *skb = clist;
			clist = clist->next;
			if (skb->destructor) {
				atomic_inc(&skb->users);
				dev_kfree_skb_any(skb); /* put this one back */
			} else {
				__kfree_skb(skb);
			}
		}
	}

	put_cpu_var(softnet_data);
}

static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
{
	int count = 0;
	struct sk_buff *skb;

	zap_completion_queue();
	refill_skbs();
repeat: