|
|
|
@@ -243,8 +243,7 @@ static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr)
|
|
|
|
|
static bool ice_vsi_fltr_changed(struct ice_vsi *vsi)
|
|
|
|
|
{
|
|
|
|
|
return test_bit(ICE_VSI_UMAC_FLTR_CHANGED, vsi->state) ||
|
|
|
|
|
test_bit(ICE_VSI_MMAC_FLTR_CHANGED, vsi->state) ||
|
|
|
|
|
test_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
|
|
|
|
|
test_bit(ICE_VSI_MMAC_FLTR_CHANGED, vsi->state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -260,10 +259,15 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m)
|
|
|
|
|
if (vsi->type != ICE_VSI_PF)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (ice_vsi_has_non_zero_vlans(vsi))
|
|
|
|
|
status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi, promisc_m);
|
|
|
|
|
else
|
|
|
|
|
status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0);
|
|
|
|
|
if (ice_vsi_has_non_zero_vlans(vsi)) {
|
|
|
|
|
promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
|
|
|
|
|
status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi,
|
|
|
|
|
promisc_m);
|
|
|
|
|
} else {
|
|
|
|
|
status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
promisc_m, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -280,10 +284,15 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
|
|
|
|
|
if (vsi->type != ICE_VSI_PF)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (ice_vsi_has_non_zero_vlans(vsi))
|
|
|
|
|
status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi, promisc_m);
|
|
|
|
|
else
|
|
|
|
|
status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0);
|
|
|
|
|
if (ice_vsi_has_non_zero_vlans(vsi)) {
|
|
|
|
|
promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
|
|
|
|
|
status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
|
|
|
|
|
promisc_m);
|
|
|
|
|
} else {
|
|
|
|
|
status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
promisc_m, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -302,7 +311,6 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
|
|
|
|
|
struct ice_pf *pf = vsi->back;
|
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
|
u32 changed_flags = 0;
|
|
|
|
|
u8 promisc_m;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if (!vsi->netdev)
|
|
|
|
@@ -320,7 +328,6 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
|
|
|
|
|
if (ice_vsi_fltr_changed(vsi)) {
|
|
|
|
|
clear_bit(ICE_VSI_UMAC_FLTR_CHANGED, vsi->state);
|
|
|
|
|
clear_bit(ICE_VSI_MMAC_FLTR_CHANGED, vsi->state);
|
|
|
|
|
clear_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
|
|
|
|
|
|
|
|
|
|
/* grab the netdev's addr_list_lock */
|
|
|
|
|
netif_addr_lock_bh(netdev);
|
|
|
|
@@ -369,29 +376,15 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
|
|
|
|
|
/* check for changes in promiscuous modes */
|
|
|
|
|
if (changed_flags & IFF_ALLMULTI) {
|
|
|
|
|
if (vsi->current_netdev_flags & IFF_ALLMULTI) {
|
|
|
|
|
if (ice_vsi_has_non_zero_vlans(vsi))
|
|
|
|
|
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
|
|
|
|
|
else
|
|
|
|
|
promisc_m = ICE_MCAST_PROMISC_BITS;
|
|
|
|
|
|
|
|
|
|
err = ice_set_promisc(vsi, promisc_m);
|
|
|
|
|
err = ice_set_promisc(vsi, ICE_MCAST_PROMISC_BITS);
|
|
|
|
|
if (err) {
|
|
|
|
|
netdev_err(netdev, "Error setting Multicast promiscuous mode on VSI %i\n",
|
|
|
|
|
vsi->vsi_num);
|
|
|
|
|
vsi->current_netdev_flags &= ~IFF_ALLMULTI;
|
|
|
|
|
goto out_promisc;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* !(vsi->current_netdev_flags & IFF_ALLMULTI) */
|
|
|
|
|
if (ice_vsi_has_non_zero_vlans(vsi))
|
|
|
|
|
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
|
|
|
|
|
else
|
|
|
|
|
promisc_m = ICE_MCAST_PROMISC_BITS;
|
|
|
|
|
|
|
|
|
|
err = ice_clear_promisc(vsi, promisc_m);
|
|
|
|
|
err = ice_clear_promisc(vsi, ICE_MCAST_PROMISC_BITS);
|
|
|
|
|
if (err) {
|
|
|
|
|
netdev_err(netdev, "Error clearing Multicast promiscuous mode on VSI %i\n",
|
|
|
|
|
vsi->vsi_num);
|
|
|
|
|
vsi->current_netdev_flags |= IFF_ALLMULTI;
|
|
|
|
|
goto out_promisc;
|
|
|
|
|
}
|
|
|
|
@@ -3488,6 +3481,20 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
|
|
|
|
|
if (!vid)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
while (test_and_set_bit(ICE_CFG_BUSY, vsi->state))
|
|
|
|
|
usleep_range(1000, 2000);
|
|
|
|
|
|
|
|
|
|
/* Add multicast promisc rule for the VLAN ID to be added if
|
|
|
|
|
* all-multicast is currently enabled.
|
|
|
|
|
*/
|
|
|
|
|
if (vsi->current_netdev_flags & IFF_ALLMULTI) {
|
|
|
|
|
ret = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
ICE_MCAST_VLAN_PROMISC_BITS,
|
|
|
|
|
vid);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
|
|
|
|
|
|
|
|
|
|
/* Add a switch rule for this VLAN ID so its corresponding VLAN tagged
|
|
|
|
@@ -3495,8 +3502,23 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
|
|
|
|
|
*/
|
|
|
|
|
vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0);
|
|
|
|
|
ret = vlan_ops->add_vlan(vsi, &vlan);
|
|
|
|
|
if (!ret)
|
|
|
|
|
set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
|
|
/* If all-multicast is currently enabled and this VLAN ID is only one
|
|
|
|
|
* besides VLAN-0 we have to update look-up type of multicast promisc
|
|
|
|
|
* rule for VLAN-0 from ICE_SW_LKUP_PROMISC to ICE_SW_LKUP_PROMISC_VLAN.
|
|
|
|
|
*/
|
|
|
|
|
if ((vsi->current_netdev_flags & IFF_ALLMULTI) &&
|
|
|
|
|
ice_vsi_num_non_zero_vlans(vsi) == 1) {
|
|
|
|
|
ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
ICE_MCAST_PROMISC_BITS, 0);
|
|
|
|
|
ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
ICE_MCAST_VLAN_PROMISC_BITS, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
clear_bit(ICE_CFG_BUSY, vsi->state);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
@@ -3522,6 +3544,9 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
|
|
|
|
|
if (!vid)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
while (test_and_set_bit(ICE_CFG_BUSY, vsi->state))
|
|
|
|
|
usleep_range(1000, 2000);
|
|
|
|
|
|
|
|
|
|
vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
|
|
|
|
|
|
|
|
|
|
/* Make sure VLAN delete is successful before updating VLAN
|
|
|
|
@@ -3530,10 +3555,33 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
|
|
|
|
|
vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0);
|
|
|
|
|
ret = vlan_ops->del_vlan(vsi, &vlan);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
|
|
set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
|
|
|
|
|
return 0;
|
|
|
|
|
/* Remove multicast promisc rule for the removed VLAN ID if
|
|
|
|
|
* all-multicast is enabled.
|
|
|
|
|
*/
|
|
|
|
|
if (vsi->current_netdev_flags & IFF_ALLMULTI)
|
|
|
|
|
ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
ICE_MCAST_VLAN_PROMISC_BITS, vid);
|
|
|
|
|
|
|
|
|
|
if (!ice_vsi_has_non_zero_vlans(vsi)) {
|
|
|
|
|
/* Update look-up type of multicast promisc rule for VLAN 0
|
|
|
|
|
* from ICE_SW_LKUP_PROMISC_VLAN to ICE_SW_LKUP_PROMISC when
|
|
|
|
|
* all-multicast is enabled and VLAN 0 is the only VLAN rule.
|
|
|
|
|
*/
|
|
|
|
|
if (vsi->current_netdev_flags & IFF_ALLMULTI) {
|
|
|
|
|
ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
ICE_MCAST_VLAN_PROMISC_BITS,
|
|
|
|
|
0);
|
|
|
|
|
ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
|
|
|
|
|
ICE_MCAST_PROMISC_BITS, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
clear_bit(ICE_CFG_BUSY, vsi->state);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -5475,16 +5523,19 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
|
|
|
|
|
|
|
|
|
|
/* Add filter for new MAC. If filter exists, return success */
|
|
|
|
|
err = ice_fltr_add_mac(vsi, mac, ICE_FWD_TO_VSI);
|
|
|
|
|
if (err == -EEXIST)
|
|
|
|
|
if (err == -EEXIST) {
|
|
|
|
|
/* Although this MAC filter is already present in hardware it's
|
|
|
|
|
* possible in some cases (e.g. bonding) that dev_addr was
|
|
|
|
|
* modified outside of the driver and needs to be restored back
|
|
|
|
|
* to this value.
|
|
|
|
|
*/
|
|
|
|
|
netdev_dbg(netdev, "filter for MAC %pM already exists\n", mac);
|
|
|
|
|
else if (err)
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
} else if (err) {
|
|
|
|
|
/* error if the new filter addition failed */
|
|
|
|
|
err = -EADDRNOTAVAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err_update_filters:
|
|
|
|
|
if (err) {
|
|
|
|
|