net: txgbe: fix to control VLAN strip
[linux-block.git] / drivers / net / ethernet / wangxun / libwx / wx_lib.c
index 6fae161cbcb822614a8f36935559f364ee0a7dc8..07ba3a270a14fa48ad6d1d9c984c7b12cd36d555 100644 (file)
@@ -2690,15 +2690,63 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
                wx->rss_enabled = false;
        }
 
-       if (changed &
-           (NETIF_F_HW_VLAN_CTAG_RX |
-            NETIF_F_HW_VLAN_STAG_RX))
+       netdev->features = features;
+
+       if (wx->mac.type == wx_mac_sp && changed & NETIF_F_HW_VLAN_CTAG_RX)
+               wx->do_reset(netdev);
+       else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER))
                wx_set_rx_mode(netdev);
 
-       return 1;
+       return 0;
 }
 EXPORT_SYMBOL(wx_set_features);
 
+#define NETIF_VLAN_STRIPPING_FEATURES  (NETIF_F_HW_VLAN_CTAG_RX | \
+                                        NETIF_F_HW_VLAN_STAG_RX)
+
+#define NETIF_VLAN_INSERTION_FEATURES  (NETIF_F_HW_VLAN_CTAG_TX | \
+                                        NETIF_F_HW_VLAN_STAG_TX)
+
+#define NETIF_VLAN_FILTERING_FEATURES  (NETIF_F_HW_VLAN_CTAG_FILTER | \
+                                        NETIF_F_HW_VLAN_STAG_FILTER)
+
+netdev_features_t wx_fix_features(struct net_device *netdev,
+                                 netdev_features_t features)
+{
+       netdev_features_t changed = netdev->features ^ features;
+       struct wx *wx = netdev_priv(netdev);
+
+       if (changed & NETIF_VLAN_STRIPPING_FEATURES) {
+               if ((features & NETIF_VLAN_STRIPPING_FEATURES) != NETIF_VLAN_STRIPPING_FEATURES &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES) != 0) {
+                       features &= ~NETIF_VLAN_STRIPPING_FEATURES;
+                       features |= netdev->features & NETIF_VLAN_STRIPPING_FEATURES;
+                       wx_err(wx, "802.1Q and 802.1ad VLAN stripping must be either both on or both off.");
+               }
+       }
+
+       if (changed & NETIF_VLAN_INSERTION_FEATURES) {
+               if ((features & NETIF_VLAN_INSERTION_FEATURES) != NETIF_VLAN_INSERTION_FEATURES &&
+                   (features & NETIF_VLAN_INSERTION_FEATURES) != 0) {
+                       features &= ~NETIF_VLAN_INSERTION_FEATURES;
+                       features |= netdev->features & NETIF_VLAN_INSERTION_FEATURES;
+                       wx_err(wx, "802.1Q and 802.1ad VLAN insertion must be either both on or both off.");
+               }
+       }
+
+       if (changed & NETIF_VLAN_FILTERING_FEATURES) {
+               if ((features & NETIF_VLAN_FILTERING_FEATURES) != NETIF_VLAN_FILTERING_FEATURES &&
+                   (features & NETIF_VLAN_FILTERING_FEATURES) != 0) {
+                       features &= ~NETIF_VLAN_FILTERING_FEATURES;
+                       features |= netdev->features & NETIF_VLAN_FILTERING_FEATURES;
+                       wx_err(wx, "802.1Q and 802.1ad VLAN filtering must be either both on or both off.");
+               }
+       }
+
+       return features;
+}
+EXPORT_SYMBOL(wx_fix_features);
+
 void wx_set_ring(struct wx *wx, u32 new_tx_count,
                 u32 new_rx_count, struct wx_ring *temp_ring)
 {