Commit 4298a62f authored by David S. Miller's avatar David S. Miller

Merge branch 'ice-fixups'

Tony Nguyen says:

====================
ice-fixups

This series handles a handful of cleanups for the ice
driver.  Ivan fixed a problem on the VSI during a release,
fixing a MAC address setting, and a broken IFF_ALLMULTI
handling.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 066dfc42 1273f895
......@@ -301,7 +301,6 @@ enum ice_vsi_state {
ICE_VSI_NETDEV_REGISTERED,
ICE_VSI_UMAC_FLTR_CHANGED,
ICE_VSI_MMAC_FLTR_CHANGED,
ICE_VSI_VLAN_FLTR_CHANGED,
ICE_VSI_PROMISC_CHANGED,
ICE_VSI_STATE_NBITS /* must be last */
};
......
......@@ -58,7 +58,16 @@ int
ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
u8 promisc_mask)
{
return ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false);
struct ice_pf *pf = hw->back;
int result;
result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false);
if (result)
dev_err(ice_pf_to_dev(pf),
"Error setting promisc mode on VSI %i (rc=%d)\n",
vsi->vsi_num, result);
return result;
}
/**
......@@ -73,7 +82,16 @@ int
ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
u8 promisc_mask)
{
return ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true);
struct ice_pf *pf = hw->back;
int result;
result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true);
if (result)
dev_err(ice_pf_to_dev(pf),
"Error clearing promisc mode on VSI %i (rc=%d)\n",
vsi->vsi_num, result);
return result;
}
/**
......@@ -87,7 +105,16 @@ int
ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
u16 vid)
{
return ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
struct ice_pf *pf = hw->back;
int result;
result = ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
if (result)
dev_err(ice_pf_to_dev(pf),
"Error clearing promisc mode on VSI %i for VID %u (rc=%d)\n",
ice_get_hw_vsi_num(hw, vsi_handle), vid, result);
return result;
}
/**
......@@ -101,7 +128,16 @@ int
ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
u16 vid)
{
return ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
struct ice_pf *pf = hw->back;
int result;
result = ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
if (result)
dev_err(ice_pf_to_dev(pf),
"Error setting promisc mode on VSI %i for VID %u (rc=%d)\n",
ice_get_hw_vsi_num(hw, vsi_handle), vid, result);
return result;
}
/**
......
......@@ -2983,6 +2983,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
}
}
if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
ice_clear_dflt_vsi(pf->first_sw);
ice_fltr_remove_all(vsi);
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment