|
@@ -1042,14 +1042,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;
|
|
@@ -1066,7 +1066,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;
|
|
|
}
|
|
@@ -4445,12 +4445,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;
|
|
@@ -4512,8 +4520,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++;
|