Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[pandora-kernel.git] / drivers / net / ixgbe / ixgbe_dcb_nl.c
index 5e7ed22..0ace6ce 100644 (file)
@@ -114,20 +114,19 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
        u8 err = 0;
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+       /* verify there is something to do, if not then exit */
+       if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+               return err;
+
        if (state > 0) {
                /* Turn on DCB */
-               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
-                       goto out;
-
                if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
                        e_err(drv, "Enable failed, needs MSI-X\n");
                        err = 1;
                        goto out;
                }
 
-               if (netif_running(netdev))
-                       netdev->netdev_ops->ndo_stop(netdev);
-               ixgbe_clear_interrupt_scheme(adapter);
+               adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
 
                switch (adapter->hw.mac.type) {
                case ixgbe_mac_82598EB:
@@ -137,46 +136,30 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
                case ixgbe_mac_82599EB:
                case ixgbe_mac_X540:
                        adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-                       adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
                        break;
                default:
                        break;
                }
 
-               adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
-               if (!netdev_get_num_tc(netdev))
-                       ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
-
-               ixgbe_init_interrupt_scheme(adapter);
-               if (netif_running(netdev))
-                       netdev->netdev_ops->ndo_open(netdev);
+               ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
        } else {
                /* Turn off DCB */
-               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-                       if (netif_running(netdev))
-                               netdev->netdev_ops->ndo_stop(netdev);
-                       ixgbe_clear_interrupt_scheme(adapter);
-
-                       adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
-                       adapter->temp_dcb_cfg.pfc_mode_enable = false;
-                       adapter->dcb_cfg.pfc_mode_enable = false;
-                       adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
-                       switch (adapter->hw.mac.type) {
-                       case ixgbe_mac_82599EB:
-                       case ixgbe_mac_X540:
+               adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+               adapter->temp_dcb_cfg.pfc_mode_enable = false;
+               adapter->dcb_cfg.pfc_mode_enable = false;
+               adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+               switch (adapter->hw.mac.type) {
+               case ixgbe_mac_82599EB:
+               case ixgbe_mac_X540:
+                       if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
                                adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       ixgbe_setup_tc(netdev, 0);
-
-                       ixgbe_init_interrupt_scheme(adapter);
-                       if (netif_running(netdev))
-                               netdev->netdev_ops->ndo_open(netdev);
+                       break;
+               default:
+                       break;
                }
+               ixgbe_setup_tc(netdev, 0);
        }
+
 out:
        return err;
 }
@@ -347,24 +330,20 @@ static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
 static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       int ret;
+#ifdef IXGBE_FCOE
        struct dcb_app app = {
                              .selector = DCB_APP_IDTYPE_ETHTYPE,
                              .protocol = ETH_P_FCOE,
                             };
        u8 up = dcb_getapp(netdev, &app);
-       int ret;
+#endif
 
        ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
                                 MAX_TRAFFIC_CLASS);
        if (ret)
                return DCB_NO_HW_CHG;
 
-       /* In IEEE mode app data must be parsed into DCBX format for
-        * hardware routines.
-        */
-       if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
-               up = (1 << up);
-
 #ifdef IXGBE_FCOE
        if (up && (up != (1 << adapter->fcoe.up)))
                adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
@@ -378,7 +357,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
                while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
                        usleep_range(1000, 2000);
 
-               ixgbe_fcoe_setapp(adapter, up);
+               adapter->fcoe.up = ffs(up) - 1;
 
                if (netif_running(netdev))
                        netdev->netdev_ops->ndo_stop(netdev);
@@ -691,24 +670,75 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
        return err;
 }
 
+#ifdef IXGBE_FCOE
+static void ixgbe_dcbnl_devreset(struct net_device *dev)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+       if (netif_running(dev))
+               dev->netdev_ops->ndo_stop(dev);
+
+       ixgbe_clear_interrupt_scheme(adapter);
+       ixgbe_init_interrupt_scheme(adapter);
+
+       if (netif_running(dev))
+               dev->netdev_ops->ndo_open(dev);
+}
+#endif
+
 static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
                                   struct dcb_app *app)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
+       int err = -EINVAL;
 
        if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
-               return -EINVAL;
+               return err;
 
-       dcb_setapp(dev, app);
+       err = dcb_ieee_setapp(dev, app);
 
 #ifdef IXGBE_FCOE
-       if (app->selector == 1 && app->protocol == ETH_P_FCOE &&
-           adapter->fcoe.tc == app->priority)
-               ixgbe_dcbnl_set_all(dev);
+       if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+           app->protocol == ETH_P_FCOE) {
+               u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+               if (app_mask & (1 << adapter->fcoe.up))
+                       return err;
+
+               adapter->fcoe.up = app->priority;
+               ixgbe_dcbnl_devreset(dev);
+       }
 #endif
        return 0;
 }
 
+static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
+                                  struct dcb_app *app)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(dev);
+       int err;
+
+       if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+               return -EINVAL;
+
+       err = dcb_ieee_delapp(dev, app);
+
+#ifdef IXGBE_FCOE
+       if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+           app->protocol == ETH_P_FCOE) {
+               u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+               if (app_mask & (1 << adapter->fcoe.up))
+                       return err;
+
+               adapter->fcoe.up = app_mask ?
+                                  ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
+               ixgbe_dcbnl_devreset(dev);
+       }
+#endif
+       return err;
+}
+
 static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
@@ -760,6 +790,7 @@ const struct dcbnl_rtnl_ops dcbnl_ops = {
        .ieee_getpfc    = ixgbe_dcbnl_ieee_getpfc,
        .ieee_setpfc    = ixgbe_dcbnl_ieee_setpfc,
        .ieee_setapp    = ixgbe_dcbnl_ieee_setapp,
+       .ieee_delapp    = ixgbe_dcbnl_ieee_delapp,
        .getstate       = ixgbe_dcbnl_get_state,
        .setstate       = ixgbe_dcbnl_set_state,
        .getpermhwaddr  = ixgbe_dcbnl_get_perm_hw_addr,