Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[linux-2.6-microblaze.git] / drivers / net / ethernet / intel / i40e / i40e_virtchnl_pf.c
index 02b09a8..3d24408 100644 (file)
@@ -55,7 +55,12 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf)
 
        pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
        pfe.severity = PF_EVENT_SEVERITY_INFO;
-       if (vf->link_forced) {
+
+       /* Always report link is down if the VF queues aren't enabled */
+       if (!vf->queues_enabled) {
+               pfe.event_data.link_event.link_status = false;
+               pfe.event_data.link_event.link_speed = 0;
+       } else if (vf->link_forced) {
                pfe.event_data.link_event.link_status = vf->link_up;
                pfe.event_data.link_event.link_speed =
                        (vf->link_up ? VIRTCHNL_LINK_SPEED_40GB : 0);
@@ -65,6 +70,7 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf)
                pfe.event_data.link_event.link_speed =
                        i40e_virtchnl_link_speed(ls->link_speed);
        }
+
        i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,
                               0, (u8 *)&pfe, sizeof(pfe), NULL);
 }
@@ -2037,30 +2043,33 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg)
                alluni = true;
        aq_ret = i40e_config_vf_promiscuous_mode(vf, info->vsi_id, allmulti,
                                                 alluni);
-       if (!aq_ret) {
-               if (allmulti) {
+       if (aq_ret)
+               goto err_out;
+
+       if (allmulti) {
+               if (!test_and_set_bit(I40E_VF_STATE_MC_PROMISC,
+                                     &vf->vf_states))
                        dev_info(&pf->pdev->dev,
                                 "VF %d successfully set multicast promiscuous mode\n",
                                 vf->vf_id);
-                       set_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
-               } else {
-                       dev_info(&pf->pdev->dev,
-                                "VF %d successfully unset multicast promiscuous mode\n",
-                                vf->vf_id);
-                       clear_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
-               }
-               if (alluni) {
+       } else if (test_and_clear_bit(I40E_VF_STATE_MC_PROMISC,
+                                     &vf->vf_states))
+               dev_info(&pf->pdev->dev,
+                        "VF %d successfully unset multicast promiscuous mode\n",
+                        vf->vf_id);
+
+       if (alluni) {
+               if (!test_and_set_bit(I40E_VF_STATE_UC_PROMISC,
+                                     &vf->vf_states))
                        dev_info(&pf->pdev->dev,
                                 "VF %d successfully set unicast promiscuous mode\n",
                                 vf->vf_id);
-                       set_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
-               } else {
-                       dev_info(&pf->pdev->dev,
-                                "VF %d successfully unset unicast promiscuous mode\n",
-                                vf->vf_id);
-                       clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
-               }
-       }
+       } else if (test_and_clear_bit(I40E_VF_STATE_UC_PROMISC,
+                                     &vf->vf_states))
+               dev_info(&pf->pdev->dev,
+                        "VF %d successfully unset unicast promiscuous mode\n",
+                        vf->vf_id);
+
 err_out:
        /* send the response to the VF */
        return i40e_vc_send_resp_to_vf(vf,
@@ -2153,7 +2162,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
                 * VF does not know about these additional VSIs and all
                 * it cares is about its own queues. PF configures these queues
                 * to its appropriate VSIs based on TC mapping
-                **/
+                */
                if (vf->adq_enabled) {
                        if (idx >= ARRAY_SIZE(vf->ch)) {
                                aq_ret = I40E_ERR_NO_AVAILABLE_VSI;
@@ -2364,6 +2373,8 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg)
                }
        }
 
+       vf->queues_enabled = true;
+
 error_param:
        /* send the response to the VF */
        return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES,
@@ -2385,6 +2396,9 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg)
        struct i40e_pf *pf = vf->pf;
        i40e_status aq_ret = 0;
 
+       /* Immediately mark queues as disabled */
+       vf->queues_enabled = false;
+
        if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
@@ -3953,10 +3967,15 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
        /* When the VF is resetting wait until it is done.
         * It can take up to 200 milliseconds,
         * but wait for up to 300 milliseconds to be safe.
+        * If the VF is indeed in reset, the vsi pointer has
+        * to show on the newly loaded vsi under pf->vsi[id].
         */
        for (i = 0; i < 15; i++) {
-               if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states))
+               if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
+                       if (i > 0)
+                               vsi = pf->vsi[vf->lan_vsi_idx];
                        break;
+               }
                msleep(20);
        }
        if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
@@ -4244,7 +4263,8 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
        if (min_tx_rate) {
                dev_err(&pf->pdev->dev, "Invalid min tx rate (%d) (greater than 0) specified for VF %d.\n",
                        min_tx_rate, vf_id);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto error;
        }
 
        vf = &pf->vf[vf_id];