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

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

[NET]: Fix drivers to handle napi_disable() disabling interrupts.



When we add the generic napi_disable_pending() breakout
logic to net_rx_action() it means that napi_disable()
can cause NAPI poll interrupt events to be disabled.

And this is exactly what we want.  If a napi_disable()
is pending, and we are looping in the ->poll(), we want
->poll() event interrupts to stay disabled and we want
to complete the NAPI poll ASAP.

When ->poll() break out during device down was being handled on a
per-driver basis, often these drivers would turn interrupts back on
when '!netif_running()' was detected.

And this would just cause a reschedule of the NAPI ->poll() in the
interrupt handler before the napi_disable() could get in there and
grab the NAPI_STATE_SCHED bit.

The vast majority of drivers don't care if napi_disable() might have
the side effect of disabling NAPI ->poll() event interrupts.  In all
such cases, when a napi_disable() is performed, the driver just
disabled interrupts or is about to.

However there were three exceptions to this in PCNET32, R8169, and
SKY2.  To fix those cases, at the subsequent napi_enable() points, I
added code to ensure that the ->poll() interrupt events are enabled in
the hardware.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Acked-by: default avatarDon Fry <pcnet32@verizon.net>
parent 1706287f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -455,9 +455,14 @@ static void pcnet32_netif_start(struct net_device *dev)
{
#ifdef CONFIG_PCNET32_NAPI
	struct pcnet32_private *lp = netdev_priv(dev);
	ulong ioaddr = dev->base_addr;
	u16 val;
#endif
	netif_wake_queue(dev);
#ifdef CONFIG_PCNET32_NAPI
	val = lp->a.read_csr(ioaddr, CSR3);
	val &= 0x00ff;
	lp->a.write_csr(ioaddr, CSR3, val);
	napi_enable(&lp->napi);
#endif
}
+2 −0
Original line number Diff line number Diff line
@@ -2398,6 +2398,8 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
	rtl8169_irq_mask_and_ack(ioaddr);

#ifdef CONFIG_R8169_NAPI
	tp->intr_mask = 0xffff;
	RTL_W16(IntrMask, tp->intr_event);
	napi_enable(&tp->napi);
#endif
}
+3 −0
Original line number Diff line number Diff line
@@ -1168,6 +1168,7 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
			     TX_VLAN_TAG_OFF);
	}

	sky2_read32(hw, B0_Y2_SP_LISR);
	napi_enable(&hw->napi);
	netif_tx_unlock_bh(dev);
}
@@ -2043,6 +2044,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
	err = sky2_rx_start(sky2);
	sky2_write32(hw, B0_IMSK, imask);

	sky2_read32(hw, B0_Y2_SP_LISR);
	napi_enable(&hw->napi);

	if (err)
@@ -3861,6 +3863,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
		   last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
		   sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));

	sky2_read32(hw, B0_Y2_SP_LISR);
	napi_enable(&hw->napi);
	return 0;
}