From: Aleksandr Loktionov <aleksandr.loktio...@intel.com>

Fix MAC setting flow for the PF driver.

Without this change the MAC address setting was interpreted
incorrectly in the following use cases:
1) Print incorrect VF MAC or zero MAC
ip link show dev $pf
2) Don't preserve MAC between driver reload
rmmod iavf; modprobe iavf
3) Update VF MAC when macvlan was set
ip link add link $vf address $mac $vf.1 type macvlan
4) Failed to update mac address when VF was trusted
ip link set dev $vf address $mac

This includes all other configurations including above commands.

Signed-off-by: Aleksandr Loktionov <aleksandr.loktio...@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalew...@intel.com>
Tested-by: Andrew Bowers <andrewx.bow...@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.ngu...@intel.com>
---
 .../ethernet/intel/i40e/i40e_virtchnl_pf.c    | 26 +++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c 
b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index c96e2f2d4cba..4919d22d7b6b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2713,6 +2713,10 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, 
u8 *msg)
                                spin_unlock_bh(&vsi->mac_filter_hash_lock);
                                goto error_param;
                        }
+                       if (is_valid_ether_addr(al->list[i].addr) &&
+                           is_zero_ether_addr(vf->default_lan_addr.addr))
+                               ether_addr_copy(vf->default_lan_addr.addr,
+                                               al->list[i].addr);
                }
        }
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
@@ -2740,6 +2744,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, 
u8 *msg)
 {
        struct virtchnl_ether_addr_list *al =
            (struct virtchnl_ether_addr_list *)msg;
+       bool was_unimac_deleted = false;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        i40e_status ret = 0;
@@ -2759,6 +2764,8 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, 
u8 *msg)
                        ret = I40E_ERR_INVALID_MAC_ADDR;
                        goto error_param;
                }
+               if (ether_addr_equal(al->list[i].addr, 
vf->default_lan_addr.addr))
+                       was_unimac_deleted = true;
        }
        vsi = pf->vsi[vf->lan_vsi_idx];
 
@@ -2779,10 +2786,25 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, 
u8 *msg)
                dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters, 
error %d\n",
                        vf->vf_id, ret);
 
+       if (vf->trusted && was_unimac_deleted) {
+               struct i40e_mac_filter *f;
+               struct hlist_node *h;
+               u8 *macaddr = NULL;
+               int bkt;
+
+               /* set last unicast mac address as default */
+               spin_lock_bh(&vsi->mac_filter_hash_lock);
+               hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+                       if (is_valid_ether_addr(f->macaddr))
+                               macaddr = f->macaddr;
+               }
+               if (macaddr)
+                       ether_addr_copy(vf->default_lan_addr.addr, macaddr);
+               spin_unlock_bh(&vsi->mac_filter_hash_lock);
+       }
 error_param:
        /* send the response to the VF */
-       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
-                                      ret);
+       return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR, ret);
 }
 
 /**
-- 
2.26.2

Reply via email to