diff options
Diffstat (limited to 'main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch')
-rw-r--r-- | main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch b/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch new file mode 100644 index 0000000000..fad2723284 --- /dev/null +++ b/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch @@ -0,0 +1,89 @@ +From 26654a966adb674afc30d285f7e79535d03c2492 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet <eric.dumazet@gmail.com> +Date: Wed, 31 Mar 2010 02:08:31 +0000 +Subject: [PATCH 07/18] 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> +(cherry picked from commit 630b943c182d1aed69f244405131902fbcba7ec6) +--- + 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 1484528..bed1d47 100644 +--- a/drivers/net/r8169.c ++++ b/drivers/net/r8169.c +@@ -1047,14 +1047,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, + } + + static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, +- struct sk_buff *skb) ++ struct sk_buff *skb, int polling) + { + u32 opts2 = le32_to_cpu(desc->opts2); + struct vlan_group *vlgrp = tp->vlgrp; + int ret; + + if (vlgrp && (opts2 & RxVlanTag)) { +- vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); ++ __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); + ret = 0; + } else + ret = -1; +@@ -1071,7 +1071,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, + } + + static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, +- struct sk_buff *skb) ++ struct sk_buff *skb, int polling) + { + return -1; + } +@@ -4480,12 +4480,20 @@ out: + return done; + } + ++/* ++ * Warning : rtl8169_rx_interrupt() might be called : ++ * 1) from NAPI (softirq) context ++ * (polling = 1 : we should call netif_receive_skb()) ++ * 2) from process context (rtl8169_reset_task()) ++ * (polling = 0 : we must call netif_rx() instead) ++ */ + static int rtl8169_rx_interrupt(struct net_device *dev, + struct rtl8169_private *tp, + void __iomem *ioaddr, u32 budget) + { + unsigned int cur_rx, rx_left; + unsigned int delta, count; ++ int polling = (budget != ~(u32)0) ? 1 : 0; + + cur_rx = tp->cur_rx; + rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; +@@ -4550,8 +4558,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, + skb_put(skb, pkt_size); + skb->protocol = eth_type_trans(skb, dev); + +- if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) +- netif_receive_skb(skb); ++ if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { ++ if (likely(polling)) ++ netif_receive_skb(skb); ++ else ++ netif_rx(skb); ++ } + + dev->stats.rx_bytes += pkt_size; + dev->stats.rx_packets++; +-- +1.7.0.2 + |