diff options
author | David S. Miller <davem@davemloft.net> | 2008-01-07 23:53:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-09 02:30:12 -0500 |
commit | d1d08d1265810ef1f165864850416dcbc9725ee7 (patch) | |
tree | 9c053e8822e33ff719da72df620f1335207ab73d /drivers/net/sky2.c | |
parent | 1706287f6eb58726a9a0e5cbbde87f49757615e3 (diff) |
[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: David S. Miller <davem@davemloft.net>
Acked-by: Don Fry <pcnet32@verizon.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a74fc11a6482..52ec89b82f64 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1168,6 +1168,7 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp | |||
1168 | TX_VLAN_TAG_OFF); | 1168 | TX_VLAN_TAG_OFF); |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | sky2_read32(hw, B0_Y2_SP_LISR); | ||
1171 | napi_enable(&hw->napi); | 1172 | napi_enable(&hw->napi); |
1172 | netif_tx_unlock_bh(dev); | 1173 | netif_tx_unlock_bh(dev); |
1173 | } | 1174 | } |
@@ -2043,6 +2044,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
2043 | err = sky2_rx_start(sky2); | 2044 | err = sky2_rx_start(sky2); |
2044 | sky2_write32(hw, B0_IMSK, imask); | 2045 | sky2_write32(hw, B0_IMSK, imask); |
2045 | 2046 | ||
2047 | sky2_read32(hw, B0_Y2_SP_LISR); | ||
2046 | napi_enable(&hw->napi); | 2048 | napi_enable(&hw->napi); |
2047 | 2049 | ||
2048 | if (err) | 2050 | if (err) |
@@ -3861,6 +3863,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v) | |||
3861 | last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), | 3863 | last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), |
3862 | sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); | 3864 | sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); |
3863 | 3865 | ||
3866 | sky2_read32(hw, B0_Y2_SP_LISR); | ||
3864 | napi_enable(&hw->napi); | 3867 | napi_enable(&hw->napi); |
3865 | return 0; | 3868 | return 0; |
3866 | } | 3869 | } |