|
@@ -537,9 +537,6 @@ struct rtl8169_private {
|
|
u16 napi_event;
|
|
u16 napi_event;
|
|
u16 intr_mask;
|
|
u16 intr_mask;
|
|
int phy_1000_ctrl_reg;
|
|
int phy_1000_ctrl_reg;
|
|
-#ifdef CONFIG_R8169_VLAN
|
|
|
|
- struct vlan_group *vlgrp;
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
struct mdio_ops {
|
|
struct mdio_ops {
|
|
void (*write)(void __iomem *, int, int);
|
|
void (*write)(void __iomem *, int, int);
|
|
@@ -1276,8 +1273,6 @@ static int rtl8169_set_rx_csum(struct net_device *dev, u32 data)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_R8169_VLAN
|
|
|
|
-
|
|
|
|
static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
|
|
static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
|
|
struct sk_buff *skb)
|
|
struct sk_buff *skb)
|
|
{
|
|
{
|
|
@@ -1285,64 +1280,37 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
|
|
TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
|
|
TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
|
|
}
|
|
}
|
|
|
|
|
|
-static void rtl8169_vlan_rx_register(struct net_device *dev,
|
|
|
|
- struct vlan_group *grp)
|
|
|
|
|
|
+#define NETIF_F_HW_VLAN_TX_RX (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX)
|
|
|
|
+
|
|
|
|
+static void rtl8169_vlan_mode(struct net_device *dev)
|
|
{
|
|
{
|
|
struct rtl8169_private *tp = netdev_priv(dev);
|
|
struct rtl8169_private *tp = netdev_priv(dev);
|
|
void __iomem *ioaddr = tp->mmio_addr;
|
|
void __iomem *ioaddr = tp->mmio_addr;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&tp->lock, flags);
|
|
spin_lock_irqsave(&tp->lock, flags);
|
|
- tp->vlgrp = grp;
|
|
|
|
- /*
|
|
|
|
- * Do not disable RxVlan on 8110SCd.
|
|
|
|
- */
|
|
|
|
- if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05))
|
|
|
|
|
|
+ if (dev->features & NETIF_F_HW_VLAN_RX)
|
|
tp->cp_cmd |= RxVlan;
|
|
tp->cp_cmd |= RxVlan;
|
|
else
|
|
else
|
|
tp->cp_cmd &= ~RxVlan;
|
|
tp->cp_cmd &= ~RxVlan;
|
|
RTL_W16(CPlusCmd, tp->cp_cmd);
|
|
RTL_W16(CPlusCmd, tp->cp_cmd);
|
|
|
|
+ /* PCI commit */
|
|
RTL_R16(CPlusCmd);
|
|
RTL_R16(CPlusCmd);
|
|
spin_unlock_irqrestore(&tp->lock, flags);
|
|
spin_unlock_irqrestore(&tp->lock, flags);
|
|
|
|
+
|
|
|
|
+ dev->vlan_features = dev->features &~ NETIF_F_HW_VLAN_TX_RX;
|
|
}
|
|
}
|
|
|
|
|
|
-static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
|
|
|
|
- struct sk_buff *skb, int polling)
|
|
|
|
|
|
+static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
|
|
{
|
|
{
|
|
u32 opts2 = le32_to_cpu(desc->opts2);
|
|
u32 opts2 = le32_to_cpu(desc->opts2);
|
|
- struct vlan_group *vlgrp = tp->vlgrp;
|
|
|
|
- int ret;
|
|
|
|
|
|
|
|
- if (vlgrp && (opts2 & RxVlanTag)) {
|
|
|
|
- u16 vtag = swab16(opts2 & 0xffff);
|
|
|
|
|
|
+ if (opts2 & RxVlanTag)
|
|
|
|
+ __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
|
|
|
|
|
|
- if (likely(polling))
|
|
|
|
- vlan_gro_receive(&tp->napi, vlgrp, vtag, skb);
|
|
|
|
- else
|
|
|
|
- __vlan_hwaccel_rx(skb, vlgrp, vtag, polling);
|
|
|
|
- ret = 0;
|
|
|
|
- } else
|
|
|
|
- ret = -1;
|
|
|
|
desc->opts2 = 0;
|
|
desc->opts2 = 0;
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#else /* !CONFIG_R8169_VLAN */
|
|
|
|
-
|
|
|
|
-static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
|
|
|
|
- struct sk_buff *skb)
|
|
|
|
-{
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
|
|
|
|
- struct sk_buff *skb, int polling)
|
|
|
|
-{
|
|
|
|
- return -1;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
|
|
static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
|
|
{
|
|
{
|
|
struct rtl8169_private *tp = netdev_priv(dev);
|
|
struct rtl8169_private *tp = netdev_priv(dev);
|
|
@@ -1513,6 +1481,28 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int rtl8169_set_flags(struct net_device *dev, u32 data)
|
|
|
|
+{
|
|
|
|
+ struct rtl8169_private *tp = netdev_priv(dev);
|
|
|
|
+ unsigned long old_feat = dev->features;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_05) &&
|
|
|
|
+ !(data & ETH_FLAG_RXVLAN)) {
|
|
|
|
+ netif_info(tp, drv, dev, "8110SCd requires hardware Rx VLAN\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = ethtool_op_set_flags(dev, data, ETH_FLAG_TXVLAN | ETH_FLAG_RXVLAN);
|
|
|
|
+ if (rc)
|
|
|
|
+ return rc;
|
|
|
|
+
|
|
|
|
+ if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX)
|
|
|
|
+ rtl8169_vlan_mode(dev);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct ethtool_ops rtl8169_ethtool_ops = {
|
|
static const struct ethtool_ops rtl8169_ethtool_ops = {
|
|
.get_drvinfo = rtl8169_get_drvinfo,
|
|
.get_drvinfo = rtl8169_get_drvinfo,
|
|
.get_regs_len = rtl8169_get_regs_len,
|
|
.get_regs_len = rtl8169_get_regs_len,
|
|
@@ -1532,6 +1522,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
|
|
.get_strings = rtl8169_get_strings,
|
|
.get_strings = rtl8169_get_strings,
|
|
.get_sset_count = rtl8169_get_sset_count,
|
|
.get_sset_count = rtl8169_get_sset_count,
|
|
.get_ethtool_stats = rtl8169_get_ethtool_stats,
|
|
.get_ethtool_stats = rtl8169_get_ethtool_stats,
|
|
|
|
+ .set_flags = rtl8169_set_flags,
|
|
|
|
+ .get_flags = ethtool_op_get_flags,
|
|
};
|
|
};
|
|
|
|
|
|
static void rtl8169_get_mac_version(struct rtl8169_private *tp,
|
|
static void rtl8169_get_mac_version(struct rtl8169_private *tp,
|
|
@@ -2849,9 +2841,6 @@ static const struct net_device_ops rtl8169_netdev_ops = {
|
|
.ndo_set_mac_address = rtl_set_mac_address,
|
|
.ndo_set_mac_address = rtl_set_mac_address,
|
|
.ndo_do_ioctl = rtl8169_ioctl,
|
|
.ndo_do_ioctl = rtl8169_ioctl,
|
|
.ndo_set_multicast_list = rtl_set_rx_mode,
|
|
.ndo_set_multicast_list = rtl_set_rx_mode,
|
|
-#ifdef CONFIG_R8169_VLAN
|
|
|
|
- .ndo_vlan_rx_register = rtl8169_vlan_rx_register,
|
|
|
|
-#endif
|
|
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
|
.ndo_poll_controller = rtl8169_netpoll,
|
|
.ndo_poll_controller = rtl8169_netpoll,
|
|
#endif
|
|
#endif
|
|
@@ -3145,6 +3134,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
/* Identify chip attached to board */
|
|
/* Identify chip attached to board */
|
|
rtl8169_get_mac_version(tp, ioaddr);
|
|
rtl8169_get_mac_version(tp, ioaddr);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Pretend we are using VLANs; This bypasses a nasty bug where
|
|
|
|
+ * Interrupts stop flowing on high load on 8110SCd controllers.
|
|
|
|
+ */
|
|
|
|
+ if (tp->mac_version == RTL_GIGA_MAC_VER_05)
|
|
|
|
+ tp->cp_cmd |= RxVlan;
|
|
|
|
+
|
|
rtl_init_mdio_ops(tp);
|
|
rtl_init_mdio_ops(tp);
|
|
rtl_init_pll_power_ops(tp);
|
|
rtl_init_pll_power_ops(tp);
|
|
|
|
|
|
@@ -3213,10 +3209,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
|
|
|
netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
|
|
netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
|
|
|
|
|
|
-#ifdef CONFIG_R8169_VLAN
|
|
|
|
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
|
|
|
|
-#endif
|
|
|
|
- dev->features |= NETIF_F_GRO;
|
|
|
|
|
|
+ dev->features |= NETIF_F_HW_VLAN_TX_RX | NETIF_F_GRO;
|
|
|
|
|
|
tp->intr_mask = 0xffff;
|
|
tp->intr_mask = 0xffff;
|
|
tp->hw_start = cfg->hw_start;
|
|
tp->hw_start = cfg->hw_start;
|
|
@@ -3334,12 +3327,7 @@ static int rtl8169_open(struct net_device *dev)
|
|
|
|
|
|
rtl8169_init_phy(dev, tp);
|
|
rtl8169_init_phy(dev, tp);
|
|
|
|
|
|
- /*
|
|
|
|
- * Pretend we are using VLANs; This bypasses a nasty bug where
|
|
|
|
- * Interrupts stop flowing on high load on 8110SCd controllers.
|
|
|
|
- */
|
|
|
|
- if (tp->mac_version == RTL_GIGA_MAC_VER_05)
|
|
|
|
- RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
|
|
|
|
|
|
+ rtl8169_vlan_mode(dev);
|
|
|
|
|
|
rtl_pll_power_up(tp);
|
|
rtl_pll_power_up(tp);
|
|
|
|
|
|
@@ -4689,12 +4677,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
|
|
skb_put(skb, pkt_size);
|
|
skb_put(skb, pkt_size);
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
|
|
|
|
- if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
|
|
|
|
- if (likely(polling))
|
|
|
|
- napi_gro_receive(&tp->napi, skb);
|
|
|
|
- else
|
|
|
|
- netif_rx(skb);
|
|
|
|
- }
|
|
|
|
|
|
+ rtl8169_rx_vlan_tag(desc, skb);
|
|
|
|
+
|
|
|
|
+ if (likely(polling))
|
|
|
|
+ napi_gro_receive(&tp->napi, skb);
|
|
|
|
+ else
|
|
|
|
+ netif_rx(skb);
|
|
|
|
|
|
dev->stats.rx_bytes += pkt_size;
|
|
dev->stats.rx_bytes += pkt_size;
|
|
dev->stats.rx_packets++;
|
|
dev->stats.rx_packets++;
|