cxgb3: do vlan cleanup
[pandora-kernel.git] / drivers / net / cxgb3 / cxgb3_main.c
index 9081ce0..93b41a7 100644 (file)
@@ -2532,25 +2532,51 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
        }
 }
 
-static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+static void cxgb_vlan_mode(struct net_device *dev, u32 features)
 {
        struct port_info *pi = netdev_priv(dev);
        struct adapter *adapter = pi->adapter;
 
-       pi->vlan_grp = grp;
-       if (adapter->params.rev > 0)
-               t3_set_vlan_accel(adapter, 1 << pi->port_id, grp != NULL);
-       else {
+       if (adapter->params.rev > 0) {
+               t3_set_vlan_accel(adapter, 1 << pi->port_id,
+                                 features & NETIF_F_HW_VLAN_RX);
+       else {
                /* single control for all ports */
-               unsigned int i, have_vlans = 0;
+               unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
+
                for_each_port(adapter, i)
-                   have_vlans |= adap2pinfo(adapter, i)->vlan_grp != NULL;
+                       have_vlans |=
+                               adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
 
                t3_set_vlan_accel(adapter, 1, have_vlans);
        }
        t3_synchronize_rx(adapter, pi);
 }
 
+static u32 cxgb_fix_features(struct net_device *dev, u32 features)
+{
+       /*
+        * Since there is no support for separate rx/tx vlan accel
+        * enable/disable make sure tx flag is always in same state as rx.
+        */
+       if (features & NETIF_F_HW_VLAN_RX)
+               features |= NETIF_F_HW_VLAN_TX;
+       else
+               features &= ~NETIF_F_HW_VLAN_TX;
+
+       return features;
+}
+
+static int cxgb_set_features(struct net_device *dev, u32 features)
+{
+       u32 changed = dev->features ^ features;
+
+       if (changed & NETIF_F_HW_VLAN_RX)
+               cxgb_vlan_mode(dev, features);
+
+       return 0;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void cxgb_netpoll(struct net_device *dev)
 {
@@ -3131,7 +3157,8 @@ static const struct net_device_ops cxgb_netdev_ops = {
        .ndo_do_ioctl           = cxgb_ioctl,
        .ndo_change_mtu         = cxgb_change_mtu,
        .ndo_set_mac_address    = cxgb_set_mac_addr,
-       .ndo_vlan_rx_register   = vlan_rx_register,
+       .ndo_fix_features       = cxgb_fix_features,
+       .ndo_set_features       = cxgb_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = cxgb_netpoll,
 #endif
@@ -3263,9 +3290,8 @@ static int __devinit init_one(struct pci_dev *pdev,
                netdev->mem_start = mmio_start;
                netdev->mem_end = mmio_start + mmio_len - 1;
                netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-                       NETIF_F_TSO | NETIF_F_RXCSUM;
-               netdev->features |= netdev->hw_features |
-                       NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+                       NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX;
+               netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_TX;
                if (pci_using_dac)
                        netdev->features |= NETIF_F_HIGHDMA;
 
@@ -3329,6 +3355,9 @@ static int __devinit init_one(struct pci_dev *pdev,
        err = sysfs_create_group(&adapter->port[0]->dev.kobj,
                                 &cxgb3_attr_group);
 
+       for_each_port(adapter, i)
+               cxgb_vlan_mode(adapter->port[i], adapter->port[i]->features);
+
        print_port_info(adapter, ai);
        return 0;