Message ID | 20201007231050.1438704-3-anthony.l.nguyen@intel.com |
---|---|
State | Superseded |
Headers | show |
Series | 40GbE Intel Wired LAN Driver Updates 2020-10-07 | expand |
On Wed, Oct 7, 2020 at 7:11 PM Tony Nguyen <anthony.l.nguyen@intel.com> wrote: > > From: Aleksandr Loktionov <aleksandr.loktionov@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.loktionov@intel.com> > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> > Tested-by: Andrew Bowers <andrewx.bowers@intel.com> > Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> If this is a fix, should it target net and/or is there a commit for a Fixes tag? > @@ -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; nit: could break here
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); } /**