forked from mirrors/linux
		
	ice: Add support for PF/VF promiscuous mode
Implement support for VF promiscuous mode, MAC/VLAN/MAC_VLAN and PF multicast MAC/VLAN/MAC_VLAN promiscuous mode. Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com> Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
		
							parent
							
								
									e1ca65a3cc
								
							
						
					
					
						commit
						5eda8afd6b
					
				
					 7 changed files with 528 additions and 32 deletions
				
			
		| 
						 | 
					@ -125,6 +125,23 @@ extern const char ice_drv_ver[];
 | 
				
			||||||
#define ice_for_each_q_vector(vsi, i) \
 | 
					#define ice_for_each_q_vector(vsi, i) \
 | 
				
			||||||
	for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++)
 | 
						for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \
 | 
				
			||||||
 | 
									ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_MCAST_TX | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_UCAST_RX | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_MCAST_RX | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_VLAN_TX  | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_VLAN_RX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICE_MCAST_PROMISC_BITS (ICE_PROMISC_MCAST_TX | ICE_PROMISC_MCAST_RX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICE_MCAST_VLAN_PROMISC_BITS (ICE_PROMISC_MCAST_TX | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_MCAST_RX | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_VLAN_TX  | \
 | 
				
			||||||
 | 
									     ICE_PROMISC_VLAN_RX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ice_tc_info {
 | 
					struct ice_tc_info {
 | 
				
			||||||
	u16 qoffset;
 | 
						u16 qoffset;
 | 
				
			||||||
	u16 qcount_tx;
 | 
						u16 qcount_tx;
 | 
				
			||||||
| 
						 | 
					@ -258,6 +275,7 @@ struct ice_vsi {
 | 
				
			||||||
	u8 irqs_ready;
 | 
						u8 irqs_ready;
 | 
				
			||||||
	u8 current_isup;		 /* Sync 'link up' logging */
 | 
						u8 current_isup;		 /* Sync 'link up' logging */
 | 
				
			||||||
	u8 stat_offsets_loaded;
 | 
						u8 stat_offsets_loaded;
 | 
				
			||||||
 | 
						u8 vlan_ena;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* queue information */
 | 
						/* queue information */
 | 
				
			||||||
	u8 tx_mapping_mode;		 /* ICE_MAP_MODE_[CONTIG|SCATTER] */
 | 
						u8 tx_mapping_mode;		 /* ICE_MAP_MODE_[CONTIG|SCATTER] */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2119,10 +2119,11 @@ ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
 | 
				
			||||||
 * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
 | 
					 * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
 | 
				
			||||||
 * @vsi: VSI to enable or disable VLAN pruning on
 | 
					 * @vsi: VSI to enable or disable VLAN pruning on
 | 
				
			||||||
 * @ena: set to true to enable VLAN pruning and false to disable it
 | 
					 * @ena: set to true to enable VLAN pruning and false to disable it
 | 
				
			||||||
 | 
					 * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * returns 0 if VSI is updated, negative otherwise
 | 
					 * returns 0 if VSI is updated, negative otherwise
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
 | 
					int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ice_vsi_ctx *ctxt;
 | 
						struct ice_vsi_ctx *ctxt;
 | 
				
			||||||
	struct device *dev;
 | 
						struct device *dev;
 | 
				
			||||||
| 
						 | 
					@ -2150,8 +2151,10 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
 | 
				
			||||||
		ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
 | 
							ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
 | 
						if (!vlan_promisc)
 | 
				
			||||||
						ICE_AQ_VSI_PROP_SW_VALID);
 | 
							ctxt->info.valid_sections =
 | 
				
			||||||
 | 
								cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
 | 
				
			||||||
 | 
									    ICE_AQ_VSI_PROP_SW_VALID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL);
 | 
						status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL);
 | 
				
			||||||
	if (status) {
 | 
						if (status) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ int
 | 
				
			||||||
ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
 | 
					ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
 | 
				
			||||||
			  u16 rel_vmvf_num);
 | 
								  u16 rel_vmvf_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena);
 | 
					int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ice_vsi_delete(struct ice_vsi *vsi);
 | 
					void ice_vsi_delete(struct ice_vsi *vsi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,6 +167,39 @@ static bool ice_vsi_fltr_changed(struct ice_vsi *vsi)
 | 
				
			||||||
	       test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
 | 
						       test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_cfg_promisc - Enable or disable promiscuous mode for a given PF
 | 
				
			||||||
 | 
					 * @vsi: the VSI being configured
 | 
				
			||||||
 | 
					 * @promisc_m: mask of promiscuous config bits
 | 
				
			||||||
 | 
					 * @set_promisc: enable or disable promisc flag request
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int ice_cfg_promisc(struct ice_vsi *vsi, u8 promisc_m, bool set_promisc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_hw *hw = &vsi->back->hw;
 | 
				
			||||||
 | 
						enum ice_status status = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vsi->type != ICE_VSI_PF)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vsi->vlan_ena) {
 | 
				
			||||||
 | 
							status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											  set_promisc);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (set_promisc)
 | 
				
			||||||
 | 
								status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											     0);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											       0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							return -EIO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * ice_vsi_sync_fltr - Update the VSI filter list to the HW
 | 
					 * ice_vsi_sync_fltr - Update the VSI filter list to the HW
 | 
				
			||||||
 * @vsi: ptr to the VSI
 | 
					 * @vsi: ptr to the VSI
 | 
				
			||||||
| 
						 | 
					@ -182,6 +215,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
 | 
				
			||||||
	struct ice_hw *hw = &pf->hw;
 | 
						struct ice_hw *hw = &pf->hw;
 | 
				
			||||||
	enum ice_status status = 0;
 | 
						enum ice_status status = 0;
 | 
				
			||||||
	u32 changed_flags = 0;
 | 
						u32 changed_flags = 0;
 | 
				
			||||||
 | 
						u8 promisc_m;
 | 
				
			||||||
	int err = 0;
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!vsi->netdev)
 | 
						if (!vsi->netdev)
 | 
				
			||||||
| 
						 | 
					@ -245,8 +279,35 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* check for changes in promiscuous modes */
 | 
						/* check for changes in promiscuous modes */
 | 
				
			||||||
	if (changed_flags & IFF_ALLMULTI)
 | 
						if (changed_flags & IFF_ALLMULTI) {
 | 
				
			||||||
		netdev_warn(netdev, "Unsupported configuration\n");
 | 
							if (vsi->current_netdev_flags & IFF_ALLMULTI) {
 | 
				
			||||||
 | 
								if (vsi->vlan_ena)
 | 
				
			||||||
 | 
									promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									promisc_m = ICE_MCAST_PROMISC_BITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = ice_cfg_promisc(vsi, promisc_m, true);
 | 
				
			||||||
 | 
								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 if (!(vsi->current_netdev_flags & IFF_ALLMULTI)) {
 | 
				
			||||||
 | 
								if (vsi->vlan_ena)
 | 
				
			||||||
 | 
									promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									promisc_m = ICE_MCAST_PROMISC_BITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = ice_cfg_promisc(vsi, promisc_m, false);
 | 
				
			||||||
 | 
								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;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (((changed_flags & IFF_PROMISC) || promisc_forced_on) ||
 | 
						if (((changed_flags & IFF_PROMISC) || promisc_forced_on) ||
 | 
				
			||||||
	    test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) {
 | 
						    test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) {
 | 
				
			||||||
| 
						 | 
					@ -1665,6 +1726,7 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ice_netdev_priv *np = netdev_priv(netdev);
 | 
						struct ice_netdev_priv *np = netdev_priv(netdev);
 | 
				
			||||||
	struct ice_vsi *vsi = np->vsi;
 | 
						struct ice_vsi *vsi = np->vsi;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vid >= VLAN_N_VID) {
 | 
						if (vid >= VLAN_N_VID) {
 | 
				
			||||||
		netdev_err(netdev, "VLAN id requested %d is out of range %d\n",
 | 
							netdev_err(netdev, "VLAN id requested %d is out of range %d\n",
 | 
				
			||||||
| 
						 | 
					@ -1677,8 +1739,7 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable VLAN pruning when VLAN 0 is added */
 | 
						/* Enable VLAN pruning when VLAN 0 is added */
 | 
				
			||||||
	if (unlikely(!vid)) {
 | 
						if (unlikely(!vid)) {
 | 
				
			||||||
		int ret = ice_cfg_vlan_pruning(vsi, true);
 | 
							ret = ice_cfg_vlan_pruning(vsi, true, false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1687,7 +1748,13 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
 | 
				
			||||||
	 * needed to continue allowing all untagged packets since VLAN prune
 | 
						 * needed to continue allowing all untagged packets since VLAN prune
 | 
				
			||||||
	 * list is applied to all packets by the switch
 | 
						 * list is applied to all packets by the switch
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	return ice_vsi_add_vlan(vsi, vid);
 | 
						ret = ice_vsi_add_vlan(vsi, vid);
 | 
				
			||||||
 | 
						if (!ret) {
 | 
				
			||||||
 | 
							vsi->vlan_ena = true;
 | 
				
			||||||
 | 
							set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1704,7 +1771,7 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ice_netdev_priv *np = netdev_priv(netdev);
 | 
						struct ice_netdev_priv *np = netdev_priv(netdev);
 | 
				
			||||||
	struct ice_vsi *vsi = np->vsi;
 | 
						struct ice_vsi *vsi = np->vsi;
 | 
				
			||||||
	int status;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vsi->info.pvid)
 | 
						if (vsi->info.pvid)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -1712,15 +1779,17 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
 | 
				
			||||||
	/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
 | 
						/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
 | 
				
			||||||
	 * information
 | 
						 * information
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	status = ice_vsi_kill_vlan(vsi, vid);
 | 
						ret = ice_vsi_kill_vlan(vsi, vid);
 | 
				
			||||||
	if (status)
 | 
						if (ret)
 | 
				
			||||||
		return status;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Disable VLAN pruning when VLAN 0 is removed */
 | 
						/* Disable VLAN pruning when VLAN 0 is removed */
 | 
				
			||||||
	if (unlikely(!vid))
 | 
						if (unlikely(!vid))
 | 
				
			||||||
		status = ice_cfg_vlan_pruning(vsi, false);
 | 
							ret = ice_cfg_vlan_pruning(vsi, false, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return status;
 | 
						vsi->vlan_ena = false;
 | 
				
			||||||
 | 
						set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2189,6 +2189,291 @@ ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_determine_promisc_mask
 | 
				
			||||||
 | 
					 * @fi: filter info to parse
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Helper function to determine which ICE_PROMISC_ mask corresponds
 | 
				
			||||||
 | 
					 * to given filter into.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u16 vid = fi->l_data.mac_vlan.vlan_id;
 | 
				
			||||||
 | 
						u8 *macaddr = fi->l_data.mac.mac_addr;
 | 
				
			||||||
 | 
						bool is_tx_fltr = false;
 | 
				
			||||||
 | 
						u8 promisc_mask = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fi->flag == ICE_FLTR_TX)
 | 
				
			||||||
 | 
							is_tx_fltr = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (is_broadcast_ether_addr(macaddr))
 | 
				
			||||||
 | 
							promisc_mask |= is_tx_fltr ?
 | 
				
			||||||
 | 
								ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
 | 
				
			||||||
 | 
						else if (is_multicast_ether_addr(macaddr))
 | 
				
			||||||
 | 
							promisc_mask |= is_tx_fltr ?
 | 
				
			||||||
 | 
								ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
 | 
				
			||||||
 | 
						else if (is_unicast_ether_addr(macaddr))
 | 
				
			||||||
 | 
							promisc_mask |= is_tx_fltr ?
 | 
				
			||||||
 | 
								ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
 | 
				
			||||||
 | 
						if (vid)
 | 
				
			||||||
 | 
							promisc_mask |= is_tx_fltr ?
 | 
				
			||||||
 | 
								ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return promisc_mask;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_remove_promisc - Remove promisc based filter rules
 | 
				
			||||||
 | 
					 * @hw: pointer to the hardware structure
 | 
				
			||||||
 | 
					 * @recp_id: recipe id for which the rule needs to removed
 | 
				
			||||||
 | 
					 * @v_list: list of promisc entries
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static enum ice_status
 | 
				
			||||||
 | 
					ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
 | 
				
			||||||
 | 
							   struct list_head *v_list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_fltr_list_entry *v_list_itr, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
 | 
				
			||||||
 | 
							v_list_itr->status =
 | 
				
			||||||
 | 
								ice_remove_rule_internal(hw, recp_id, v_list_itr);
 | 
				
			||||||
 | 
							if (v_list_itr->status)
 | 
				
			||||||
 | 
								return v_list_itr->status;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
 | 
				
			||||||
 | 
					 * @hw: pointer to the hardware structure
 | 
				
			||||||
 | 
					 * @vsi_handle: VSI handle to clear mode
 | 
				
			||||||
 | 
					 * @promisc_mask: mask of promiscuous config bits to clear
 | 
				
			||||||
 | 
					 * @vid: VLAN ID to clear VLAN promiscuous
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ice_status
 | 
				
			||||||
 | 
					ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 | 
				
			||||||
 | 
							      u16 vid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_switch_info *sw = hw->switch_info;
 | 
				
			||||||
 | 
						struct ice_fltr_list_entry *fm_entry, *tmp;
 | 
				
			||||||
 | 
						struct list_head remove_list_head;
 | 
				
			||||||
 | 
						struct ice_fltr_mgmt_list_entry *itr;
 | 
				
			||||||
 | 
						struct list_head *rule_head;
 | 
				
			||||||
 | 
						struct mutex *rule_lock;	/* Lock to protect filter rule list */
 | 
				
			||||||
 | 
						enum ice_status status = 0;
 | 
				
			||||||
 | 
						u8 recipe_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!ice_is_vsi_valid(hw, vsi_handle))
 | 
				
			||||||
 | 
							return ICE_ERR_PARAM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vid)
 | 
				
			||||||
 | 
							recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							recipe_id = ICE_SW_LKUP_PROMISC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rule_head = &sw->recp_list[recipe_id].filt_rules;
 | 
				
			||||||
 | 
						rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&remove_list_head);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(rule_lock);
 | 
				
			||||||
 | 
						list_for_each_entry(itr, rule_head, list_entry) {
 | 
				
			||||||
 | 
							u8 fltr_promisc_mask = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!ice_vsi_uses_fltr(itr, vsi_handle))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fltr_promisc_mask |=
 | 
				
			||||||
 | 
								ice_determine_promisc_mask(&itr->fltr_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Skip if filter is not completely specified by given mask */
 | 
				
			||||||
 | 
							if (fltr_promisc_mask & ~promisc_mask)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
 | 
				
			||||||
 | 
												&remove_list_head,
 | 
				
			||||||
 | 
												&itr->fltr_info);
 | 
				
			||||||
 | 
							if (status) {
 | 
				
			||||||
 | 
								mutex_unlock(rule_lock);
 | 
				
			||||||
 | 
								goto free_fltr_list;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mutex_unlock(rule_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					free_fltr_list:
 | 
				
			||||||
 | 
						list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
 | 
				
			||||||
 | 
							list_del(&fm_entry->list_entry);
 | 
				
			||||||
 | 
							devm_kfree(ice_hw_to_dev(hw), fm_entry);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
 | 
				
			||||||
 | 
					 * @hw: pointer to the hardware structure
 | 
				
			||||||
 | 
					 * @vsi_handle: VSI handle to configure
 | 
				
			||||||
 | 
					 * @promisc_mask: mask of promiscuous config bits
 | 
				
			||||||
 | 
					 * @vid: VLAN ID to set VLAN promiscuous
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ice_status
 | 
				
			||||||
 | 
					ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
 | 
				
			||||||
 | 
						struct ice_fltr_list_entry f_list_entry;
 | 
				
			||||||
 | 
						struct ice_fltr_info new_fltr;
 | 
				
			||||||
 | 
						enum ice_status status = 0;
 | 
				
			||||||
 | 
						bool is_tx_fltr;
 | 
				
			||||||
 | 
						u16 hw_vsi_id;
 | 
				
			||||||
 | 
						int pkt_type;
 | 
				
			||||||
 | 
						u8 recipe_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!ice_is_vsi_valid(hw, vsi_handle))
 | 
				
			||||||
 | 
							return ICE_ERR_PARAM;
 | 
				
			||||||
 | 
						hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&new_fltr, 0, sizeof(new_fltr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
 | 
				
			||||||
 | 
							new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
 | 
				
			||||||
 | 
							new_fltr.l_data.mac_vlan.vlan_id = vid;
 | 
				
			||||||
 | 
							recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
 | 
				
			||||||
 | 
							recipe_id = ICE_SW_LKUP_PROMISC;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Separate filters must be set for each direction/packet type
 | 
				
			||||||
 | 
						 * combination, so we will loop over the mask value, store the
 | 
				
			||||||
 | 
						 * individual type, and clear it out in the input mask as it
 | 
				
			||||||
 | 
						 * is found.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						while (promisc_mask) {
 | 
				
			||||||
 | 
							u8 *mac_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pkt_type = 0;
 | 
				
			||||||
 | 
							is_tx_fltr = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (promisc_mask & ICE_PROMISC_UCAST_RX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_UCAST_RX;
 | 
				
			||||||
 | 
								pkt_type = UCAST_FLTR;
 | 
				
			||||||
 | 
							} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_UCAST_TX;
 | 
				
			||||||
 | 
								pkt_type = UCAST_FLTR;
 | 
				
			||||||
 | 
								is_tx_fltr = true;
 | 
				
			||||||
 | 
							} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_MCAST_RX;
 | 
				
			||||||
 | 
								pkt_type = MCAST_FLTR;
 | 
				
			||||||
 | 
							} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_MCAST_TX;
 | 
				
			||||||
 | 
								pkt_type = MCAST_FLTR;
 | 
				
			||||||
 | 
								is_tx_fltr = true;
 | 
				
			||||||
 | 
							} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_BCAST_RX;
 | 
				
			||||||
 | 
								pkt_type = BCAST_FLTR;
 | 
				
			||||||
 | 
							} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_BCAST_TX;
 | 
				
			||||||
 | 
								pkt_type = BCAST_FLTR;
 | 
				
			||||||
 | 
								is_tx_fltr = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check for VLAN promiscuous flag */
 | 
				
			||||||
 | 
							if (promisc_mask & ICE_PROMISC_VLAN_RX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_VLAN_RX;
 | 
				
			||||||
 | 
							} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
 | 
				
			||||||
 | 
								promisc_mask &= ~ICE_PROMISC_VLAN_TX;
 | 
				
			||||||
 | 
								is_tx_fltr = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Set filter DA based on packet type */
 | 
				
			||||||
 | 
							mac_addr = new_fltr.l_data.mac.mac_addr;
 | 
				
			||||||
 | 
							if (pkt_type == BCAST_FLTR) {
 | 
				
			||||||
 | 
								eth_broadcast_addr(mac_addr);
 | 
				
			||||||
 | 
							} else if (pkt_type == MCAST_FLTR ||
 | 
				
			||||||
 | 
								   pkt_type == UCAST_FLTR) {
 | 
				
			||||||
 | 
								/* Use the dummy ether header DA */
 | 
				
			||||||
 | 
								ether_addr_copy(mac_addr, dummy_eth_header);
 | 
				
			||||||
 | 
								if (pkt_type == MCAST_FLTR)
 | 
				
			||||||
 | 
									mac_addr[0] |= 0x1;	/* Set multicast bit */
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Need to reset this to zero for all iterations */
 | 
				
			||||||
 | 
							new_fltr.flag = 0;
 | 
				
			||||||
 | 
							if (is_tx_fltr) {
 | 
				
			||||||
 | 
								new_fltr.flag |= ICE_FLTR_TX;
 | 
				
			||||||
 | 
								new_fltr.src = hw_vsi_id;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								new_fltr.flag |= ICE_FLTR_RX;
 | 
				
			||||||
 | 
								new_fltr.src = hw->port_info->lport;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							new_fltr.fltr_act = ICE_FWD_TO_VSI;
 | 
				
			||||||
 | 
							new_fltr.vsi_handle = vsi_handle;
 | 
				
			||||||
 | 
							new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
 | 
				
			||||||
 | 
							f_list_entry.fltr_info = new_fltr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
 | 
				
			||||||
 | 
							if (status)
 | 
				
			||||||
 | 
								goto set_promisc_exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_promisc_exit:
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_set_vlan_vsi_promisc
 | 
				
			||||||
 | 
					 * @hw: pointer to the hardware structure
 | 
				
			||||||
 | 
					 * @vsi_handle: VSI handle to configure
 | 
				
			||||||
 | 
					 * @promisc_mask: mask of promiscuous config bits
 | 
				
			||||||
 | 
					 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Configure VSI with all associated VLANs to given promiscuous mode(s)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ice_status
 | 
				
			||||||
 | 
					ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 | 
				
			||||||
 | 
								 bool rm_vlan_promisc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_switch_info *sw = hw->switch_info;
 | 
				
			||||||
 | 
						struct ice_fltr_list_entry *list_itr, *tmp;
 | 
				
			||||||
 | 
						struct list_head vsi_list_head;
 | 
				
			||||||
 | 
						struct list_head *vlan_head;
 | 
				
			||||||
 | 
						struct mutex *vlan_lock; /* Lock to protect filter rule list */
 | 
				
			||||||
 | 
						enum ice_status status;
 | 
				
			||||||
 | 
						u16 vlan_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&vsi_list_head);
 | 
				
			||||||
 | 
						vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
 | 
				
			||||||
 | 
						vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
 | 
				
			||||||
 | 
						mutex_lock(vlan_lock);
 | 
				
			||||||
 | 
						status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
 | 
				
			||||||
 | 
										  &vsi_list_head);
 | 
				
			||||||
 | 
						mutex_unlock(vlan_lock);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							goto free_fltr_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
 | 
				
			||||||
 | 
							vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
 | 
				
			||||||
 | 
							if (rm_vlan_promisc)
 | 
				
			||||||
 | 
								status = ice_clear_vsi_promisc(hw, vsi_handle,
 | 
				
			||||||
 | 
											       promisc_mask, vlan_id);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								status = ice_set_vsi_promisc(hw, vsi_handle,
 | 
				
			||||||
 | 
											     promisc_mask, vlan_id);
 | 
				
			||||||
 | 
							if (status)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					free_fltr_list:
 | 
				
			||||||
 | 
						list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
 | 
				
			||||||
 | 
							list_del(&list_itr->list_entry);
 | 
				
			||||||
 | 
							devm_kfree(ice_hw_to_dev(hw), list_itr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
 | 
					 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
 | 
				
			||||||
 * @hw: pointer to the hardware structure
 | 
					 * @hw: pointer to the hardware structure
 | 
				
			||||||
| 
						 | 
					@ -2224,12 +2509,14 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
 | 
				
			||||||
	case ICE_SW_LKUP_VLAN:
 | 
						case ICE_SW_LKUP_VLAN:
 | 
				
			||||||
		ice_remove_vlan(hw, &remove_list_head);
 | 
							ice_remove_vlan(hw, &remove_list_head);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case ICE_SW_LKUP_PROMISC:
 | 
				
			||||||
 | 
						case ICE_SW_LKUP_PROMISC_VLAN:
 | 
				
			||||||
 | 
							ice_remove_promisc(hw, lkup, &remove_list_head);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case ICE_SW_LKUP_MAC_VLAN:
 | 
						case ICE_SW_LKUP_MAC_VLAN:
 | 
				
			||||||
	case ICE_SW_LKUP_ETHERTYPE:
 | 
						case ICE_SW_LKUP_ETHERTYPE:
 | 
				
			||||||
	case ICE_SW_LKUP_ETHERTYPE_MAC:
 | 
						case ICE_SW_LKUP_ETHERTYPE_MAC:
 | 
				
			||||||
	case ICE_SW_LKUP_PROMISC:
 | 
					 | 
				
			||||||
	case ICE_SW_LKUP_DFLT:
 | 
						case ICE_SW_LKUP_DFLT:
 | 
				
			||||||
	case ICE_SW_LKUP_PROMISC_VLAN:
 | 
					 | 
				
			||||||
	case ICE_SW_LKUP_LAST:
 | 
						case ICE_SW_LKUP_LAST:
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
 | 
							ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,6 +178,17 @@ struct ice_fltr_mgmt_list_entry {
 | 
				
			||||||
	u8 counter_index;
 | 
						u8 counter_index;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum ice_promisc_flags {
 | 
				
			||||||
 | 
						ICE_PROMISC_UCAST_RX = 0x1,
 | 
				
			||||||
 | 
						ICE_PROMISC_UCAST_TX = 0x2,
 | 
				
			||||||
 | 
						ICE_PROMISC_MCAST_RX = 0x4,
 | 
				
			||||||
 | 
						ICE_PROMISC_MCAST_TX = 0x8,
 | 
				
			||||||
 | 
						ICE_PROMISC_BCAST_RX = 0x10,
 | 
				
			||||||
 | 
						ICE_PROMISC_BCAST_TX = 0x20,
 | 
				
			||||||
 | 
						ICE_PROMISC_VLAN_RX = 0x40,
 | 
				
			||||||
 | 
						ICE_PROMISC_VLAN_TX = 0x80,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* VSI related commands */
 | 
					/* VSI related commands */
 | 
				
			||||||
enum ice_status
 | 
					enum ice_status
 | 
				
			||||||
ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
 | 
					ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
 | 
				
			||||||
| 
						 | 
					@ -202,8 +213,19 @@ void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle);
 | 
				
			||||||
enum ice_status
 | 
					enum ice_status
 | 
				
			||||||
ice_add_vlan(struct ice_hw *hw, struct list_head *m_list);
 | 
					ice_add_vlan(struct ice_hw *hw, struct list_head *m_list);
 | 
				
			||||||
enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list);
 | 
					enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Promisc/defport setup for VSIs */
 | 
				
			||||||
enum ice_status
 | 
					enum ice_status
 | 
				
			||||||
ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction);
 | 
					ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction);
 | 
				
			||||||
 | 
					enum ice_status
 | 
				
			||||||
 | 
					ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 | 
				
			||||||
 | 
							    u16 vid);
 | 
				
			||||||
 | 
					enum ice_status
 | 
				
			||||||
 | 
					ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 | 
				
			||||||
 | 
							      u16 vid);
 | 
				
			||||||
 | 
					enum ice_status
 | 
				
			||||||
 | 
					ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 | 
				
			||||||
 | 
								 bool rm_vlan_promisc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ice_status ice_init_def_sw_recp(struct ice_hw *hw);
 | 
					enum ice_status ice_init_def_sw_recp(struct ice_hw *hw);
 | 
				
			||||||
u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle);
 | 
					u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -771,6 +771,47 @@ static void ice_cleanup_and_realloc_vf(struct ice_vf *vf)
 | 
				
			||||||
	wr32(hw, VFGEN_RSTAT(vf->vf_id), VIRTCHNL_VFR_VFACTIVE);
 | 
						wr32(hw, VFGEN_RSTAT(vf->vf_id), VIRTCHNL_VFR_VFACTIVE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ice_vf_set_vsi_promisc - set given VF VSI to given promiscuous mode(s)
 | 
				
			||||||
 | 
					 * @vf: pointer to the VF info
 | 
				
			||||||
 | 
					 * @vsi: the VSI being configured
 | 
				
			||||||
 | 
					 * @promisc_m: mask of promiscuous config bits
 | 
				
			||||||
 | 
					 * @rm_promisc: promisc flag request from the VF to remove or add filter
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function configures VF VSI promiscuous mode, based on the VF requests,
 | 
				
			||||||
 | 
					 * for Unicast, Multicast and VLAN
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static enum ice_status
 | 
				
			||||||
 | 
					ice_vf_set_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m,
 | 
				
			||||||
 | 
							       bool rm_promisc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ice_pf *pf = vf->pf;
 | 
				
			||||||
 | 
						enum ice_status status = 0;
 | 
				
			||||||
 | 
						struct ice_hw *hw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hw = &pf->hw;
 | 
				
			||||||
 | 
						if (vf->num_vlan) {
 | 
				
			||||||
 | 
							status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											  rm_promisc);
 | 
				
			||||||
 | 
						} else if (vf->port_vlan_id) {
 | 
				
			||||||
 | 
							if (rm_promisc)
 | 
				
			||||||
 | 
								status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											       vf->port_vlan_id);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											     vf->port_vlan_id);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (rm_promisc)
 | 
				
			||||||
 | 
								status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											       0);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
 | 
				
			||||||
 | 
											     0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * ice_reset_all_vfs - reset all allocated VFs in one go
 | 
					 * ice_reset_all_vfs - reset all allocated VFs in one go
 | 
				
			||||||
 * @pf: pointer to the PF structure
 | 
					 * @pf: pointer to the PF structure
 | 
				
			||||||
| 
						 | 
					@ -892,9 +933,10 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
 | 
				
			||||||
static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
 | 
					static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ice_pf *pf = vf->pf;
 | 
						struct ice_pf *pf = vf->pf;
 | 
				
			||||||
	struct ice_hw *hw = &pf->hw;
 | 
					 | 
				
			||||||
	struct ice_vsi *vsi;
 | 
						struct ice_vsi *vsi;
 | 
				
			||||||
 | 
						struct ice_hw *hw;
 | 
				
			||||||
	bool rsd = false;
 | 
						bool rsd = false;
 | 
				
			||||||
 | 
						u8 promisc_m;
 | 
				
			||||||
	u32 reg;
 | 
						u32 reg;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -920,6 +962,7 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
 | 
				
			||||||
				vf->vf_id, NULL);
 | 
									vf->vf_id, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hw = &pf->hw;
 | 
				
			||||||
	/* poll VPGEN_VFRSTAT reg to make sure
 | 
						/* poll VPGEN_VFRSTAT reg to make sure
 | 
				
			||||||
	 * that reset is complete
 | 
						 * that reset is complete
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -945,6 +988,21 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usleep_range(10000, 20000);
 | 
						usleep_range(10000, 20000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* disable promiscuous modes in case they were enabled
 | 
				
			||||||
 | 
						 * ignore any error if disabling process failed
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
 | 
				
			||||||
 | 
						    test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) {
 | 
				
			||||||
 | 
							if (vf->port_vlan_id ||  vf->num_vlan)
 | 
				
			||||||
 | 
								promisc_m = ICE_UCAST_VLAN_PROMISC_BITS;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								promisc_m = ICE_UCAST_PROMISC_BITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vsi = pf->vsi[vf->lan_vsi_idx];
 | 
				
			||||||
 | 
							if (ice_vf_set_vsi_promisc(vf, vsi, promisc_m, true))
 | 
				
			||||||
 | 
								dev_err(&pf->pdev->dev, "disabling promiscuous mode failed\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* free VF resources to begin resetting the VSI state */
 | 
						/* free VF resources to begin resetting the VSI state */
 | 
				
			||||||
	ice_free_vf_res(vf);
 | 
						ice_free_vf_res(vf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2192,7 +2250,11 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
 | 
				
			||||||
	    (struct virtchnl_vlan_filter_list *)msg;
 | 
						    (struct virtchnl_vlan_filter_list *)msg;
 | 
				
			||||||
	enum ice_status aq_ret = 0;
 | 
						enum ice_status aq_ret = 0;
 | 
				
			||||||
	struct ice_pf *pf = vf->pf;
 | 
						struct ice_pf *pf = vf->pf;
 | 
				
			||||||
 | 
						bool vlan_promisc = false;
 | 
				
			||||||
	struct ice_vsi *vsi;
 | 
						struct ice_vsi *vsi;
 | 
				
			||||||
 | 
						struct ice_hw *hw;
 | 
				
			||||||
 | 
						int status = 0;
 | 
				
			||||||
 | 
						u8 promisc_m;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
 | 
						if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
 | 
				
			||||||
| 
						 | 
					@ -2209,7 +2271,9 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
 | 
				
			||||||
	    vf->num_vlan >= ICE_MAX_VLAN_PER_VF) {
 | 
						    vf->num_vlan >= ICE_MAX_VLAN_PER_VF) {
 | 
				
			||||||
		dev_info(&pf->pdev->dev,
 | 
							dev_info(&pf->pdev->dev,
 | 
				
			||||||
			 "VF is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n");
 | 
								 "VF is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n");
 | 
				
			||||||
		aq_ret = ICE_ERR_PARAM;
 | 
							/* There is no need to let VF know about being not trusted,
 | 
				
			||||||
 | 
							 * so we can just return success message here
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
		goto error_param;
 | 
							goto error_param;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2222,6 +2286,7 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hw = &pf->hw;
 | 
				
			||||||
	vsi = ice_find_vsi_from_id(vf->pf, vfl->vsi_id);
 | 
						vsi = ice_find_vsi_from_id(vf->pf, vfl->vsi_id);
 | 
				
			||||||
	if (!vsi) {
 | 
						if (!vsi) {
 | 
				
			||||||
		aq_ret = ICE_ERR_PARAM;
 | 
							aq_ret = ICE_ERR_PARAM;
 | 
				
			||||||
| 
						 | 
					@ -2241,19 +2306,41 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
 | 
				
			||||||
		goto error_param;
 | 
							goto error_param;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
 | 
				
			||||||
 | 
						    test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
 | 
				
			||||||
 | 
							vlan_promisc = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (add_v) {
 | 
						if (add_v) {
 | 
				
			||||||
		for (i = 0; i < vfl->num_elements; i++) {
 | 
							for (i = 0; i < vfl->num_elements; i++) {
 | 
				
			||||||
			u16 vid = vfl->vlan_id[i];
 | 
								u16 vid = vfl->vlan_id[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!ice_vsi_add_vlan(vsi, vid)) {
 | 
								if (ice_vsi_add_vlan(vsi, vid)) {
 | 
				
			||||||
				vf->num_vlan++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				/* Enable VLAN pruning when VLAN 0 is added */
 | 
					 | 
				
			||||||
				if (unlikely(!vid))
 | 
					 | 
				
			||||||
					if (ice_cfg_vlan_pruning(vsi, true))
 | 
					 | 
				
			||||||
						aq_ret = ICE_ERR_PARAM;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				aq_ret = ICE_ERR_PARAM;
 | 
									aq_ret = ICE_ERR_PARAM;
 | 
				
			||||||
 | 
									goto error_param;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								vf->num_vlan++;
 | 
				
			||||||
 | 
								/* Enable VLAN pruning when VLAN is added */
 | 
				
			||||||
 | 
								if (!vlan_promisc) {
 | 
				
			||||||
 | 
									status = ice_cfg_vlan_pruning(vsi, true, false);
 | 
				
			||||||
 | 
									if (status) {
 | 
				
			||||||
 | 
										aq_ret = ICE_ERR_PARAM;
 | 
				
			||||||
 | 
										dev_err(&pf->pdev->dev,
 | 
				
			||||||
 | 
											"Enable VLAN pruning on VLAN ID: %d failed error-%d\n",
 | 
				
			||||||
 | 
											vid, status);
 | 
				
			||||||
 | 
										goto error_param;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									/* Enable Ucast/Mcast VLAN promiscuous mode */
 | 
				
			||||||
 | 
									promisc_m = ICE_PROMISC_VLAN_TX |
 | 
				
			||||||
 | 
										    ICE_PROMISC_VLAN_RX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									status = ice_set_vsi_promisc(hw, vsi->idx,
 | 
				
			||||||
 | 
												     promisc_m, vid);
 | 
				
			||||||
 | 
									if (status)
 | 
				
			||||||
 | 
										dev_err(&pf->pdev->dev,
 | 
				
			||||||
 | 
											"Enable Unicast/multicast promiscuous mode on VLAN ID:%d failed error-%d\n",
 | 
				
			||||||
 | 
											vid, status);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -2263,12 +2350,22 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
 | 
				
			||||||
			/* Make sure ice_vsi_kill_vlan is successful before
 | 
								/* Make sure ice_vsi_kill_vlan is successful before
 | 
				
			||||||
			 * updating VLAN information
 | 
								 * updating VLAN information
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if (!ice_vsi_kill_vlan(vsi, vid)) {
 | 
								if (ice_vsi_kill_vlan(vsi, vid)) {
 | 
				
			||||||
				vf->num_vlan--;
 | 
									aq_ret = ICE_ERR_PARAM;
 | 
				
			||||||
 | 
									goto error_param;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				/* Disable VLAN pruning when removing VLAN 0 */
 | 
								vf->num_vlan--;
 | 
				
			||||||
				if (unlikely(!vid))
 | 
								/* Disable VLAN pruning when removing VLAN */
 | 
				
			||||||
					ice_cfg_vlan_pruning(vsi, false);
 | 
								ice_cfg_vlan_pruning(vsi, false, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Disable Unicast/Multicast VLAN promiscuous mode */
 | 
				
			||||||
 | 
								if (vlan_promisc) {
 | 
				
			||||||
 | 
									promisc_m = ICE_PROMISC_VLAN_TX |
 | 
				
			||||||
 | 
										    ICE_PROMISC_VLAN_RX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									ice_clear_vsi_promisc(hw, vsi->idx,
 | 
				
			||||||
 | 
											      promisc_m, vid);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue