aboutsummaryrefslogtreecommitdiffstats
path: root/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch
diff options
context:
space:
mode:
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.patch89
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
+