diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-03-30 22:08:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-01 21:41:35 -0400 |
commit | 630b943c182d1aed69f244405131902fbcba7ec6 (patch) | |
tree | 8681938a3c4922405e8df6a61b7152bfd1e96ea4 /drivers | |
parent | 5d944c640b4ae5f37c537acf491c2f0eb89fa0d6 (diff) |
r8169: Fix rtl8169_rx_interrupt()
In case a reset is performed, rtl8169_rx_interrupt() is called from
process context instead of softirq context. Special care must be taken
to call appropriate network core services (netif_rx() instead of
netif_receive_skb()). VLAN handling also corrected.
Reported-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Tested-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Diagnosed-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/r8169.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 964305c7f9f1..f7ffa5d8ffeb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -1054,14 +1054,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, | |||
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | 1056 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, |
1057 | struct sk_buff *skb) | 1057 | struct sk_buff *skb, int polling) |
1058 | { | 1058 | { |
1059 | u32 opts2 = le32_to_cpu(desc->opts2); | 1059 | u32 opts2 = le32_to_cpu(desc->opts2); |
1060 | struct vlan_group *vlgrp = tp->vlgrp; | 1060 | struct vlan_group *vlgrp = tp->vlgrp; |
1061 | int ret; | 1061 | int ret; |
1062 | 1062 | ||
1063 | if (vlgrp && (opts2 & RxVlanTag)) { | 1063 | if (vlgrp && (opts2 & RxVlanTag)) { |
1064 | vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); | 1064 | __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); |
1065 | ret = 0; | 1065 | ret = 0; |
1066 | } else | 1066 | } else |
1067 | ret = -1; | 1067 | ret = -1; |
@@ -1078,7 +1078,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, | |||
1078 | } | 1078 | } |
1079 | 1079 | ||
1080 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | 1080 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, |
1081 | struct sk_buff *skb) | 1081 | struct sk_buff *skb, int polling) |
1082 | { | 1082 | { |
1083 | return -1; | 1083 | return -1; |
1084 | } | 1084 | } |
@@ -4467,12 +4467,20 @@ out: | |||
4467 | return done; | 4467 | return done; |
4468 | } | 4468 | } |
4469 | 4469 | ||
4470 | /* | ||
4471 | * Warning : rtl8169_rx_interrupt() might be called : | ||
4472 | * 1) from NAPI (softirq) context | ||
4473 | * (polling = 1 : we should call netif_receive_skb()) | ||
4474 | * 2) from process context (rtl8169_reset_task()) | ||
4475 | * (polling = 0 : we must call netif_rx() instead) | ||
4476 | */ | ||
4470 | static int rtl8169_rx_interrupt(struct net_device *dev, | 4477 | static int rtl8169_rx_interrupt(struct net_device *dev, |
4471 | struct rtl8169_private *tp, | 4478 | struct rtl8169_private *tp, |
4472 | void __iomem *ioaddr, u32 budget) | 4479 | void __iomem *ioaddr, u32 budget) |
4473 | { | 4480 | { |
4474 | unsigned int cur_rx, rx_left; | 4481 | unsigned int cur_rx, rx_left; |
4475 | unsigned int delta, count; | 4482 | unsigned int delta, count; |
4483 | int polling = (budget != ~(u32)0) ? 1 : 0; | ||
4476 | 4484 | ||
4477 | cur_rx = tp->cur_rx; | 4485 | cur_rx = tp->cur_rx; |
4478 | rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; | 4486 | rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; |
@@ -4534,8 +4542,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, | |||
4534 | skb_put(skb, pkt_size); | 4542 | skb_put(skb, pkt_size); |
4535 | skb->protocol = eth_type_trans(skb, dev); | 4543 | skb->protocol = eth_type_trans(skb, dev); |
4536 | 4544 | ||
4537 | if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) | 4545 | if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { |
4538 | netif_receive_skb(skb); | 4546 | if (likely(polling)) |
4547 | netif_receive_skb(skb); | ||
4548 | else | ||
4549 | netif_rx(skb); | ||
4550 | } | ||
4539 | 4551 | ||
4540 | dev->stats.rx_bytes += pkt_size; | 4552 | dev->stats.rx_bytes += pkt_size; |
4541 | dev->stats.rx_packets++; | 4553 | dev->stats.rx_packets++; |