aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorAkeem G Abodunrin <akeem.g.abodunrin@intel.com>2019-02-26 19:35:14 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-03-22 11:19:17 -0400
commit5eda8afd6bcc89d4e4aa5d56b5f54276f63158ae (patch)
tree44a9e13481cd5aa025b5f576a09f93fa943bb9fa /drivers/net/ethernet
parente1ca65a3cceacc94dd9cde388016422ca2e15a54 (diff)
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>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h18
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c91
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c291
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.h22
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c125
7 files changed, 527 insertions, 31 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index 2bb2898efb82..0843868d1bbd 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -125,6 +125,23 @@ extern const char ice_drv_ver[];
125#define ice_for_each_q_vector(vsi, i) \ 125#define ice_for_each_q_vector(vsi, i) \
126 for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++) 126 for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++)
127 127
128#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \
129 ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX)
130
131#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
132 ICE_PROMISC_MCAST_TX | \
133 ICE_PROMISC_UCAST_RX | \
134 ICE_PROMISC_MCAST_RX | \
135 ICE_PROMISC_VLAN_TX | \
136 ICE_PROMISC_VLAN_RX)
137
138#define ICE_MCAST_PROMISC_BITS (ICE_PROMISC_MCAST_TX | ICE_PROMISC_MCAST_RX)
139
140#define ICE_MCAST_VLAN_PROMISC_BITS (ICE_PROMISC_MCAST_TX | \
141 ICE_PROMISC_MCAST_RX | \
142 ICE_PROMISC_VLAN_TX | \
143 ICE_PROMISC_VLAN_RX)
144
128struct ice_tc_info { 145struct ice_tc_info {
129 u16 qoffset; 146 u16 qoffset;
130 u16 qcount_tx; 147 u16 qcount_tx;
@@ -258,6 +275,7 @@ struct ice_vsi {
258 u8 irqs_ready; 275 u8 irqs_ready;
259 u8 current_isup; /* Sync 'link up' logging */ 276 u8 current_isup; /* Sync 'link up' logging */
260 u8 stat_offsets_loaded; 277 u8 stat_offsets_loaded;
278 u8 vlan_ena;
261 279
262 /* queue information */ 280 /* queue information */
263 u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */ 281 u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 87e57328a81b..7a692f80bda4 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -2119,10 +2119,11 @@ ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
2119 * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 2119 * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
2120 * @vsi: VSI to enable or disable VLAN pruning on 2120 * @vsi: VSI to enable or disable VLAN pruning on
2121 * @ena: set to true to enable VLAN pruning and false to disable it 2121 * @ena: set to true to enable VLAN pruning and false to disable it
2122 * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
2122 * 2123 *
2123 * returns 0 if VSI is updated, negative otherwise 2124 * returns 0 if VSI is updated, negative otherwise
2124 */ 2125 */
2125int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena) 2126int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
2126{ 2127{
2127 struct ice_vsi_ctx *ctxt; 2128 struct ice_vsi_ctx *ctxt;
2128 struct device *dev; 2129 struct device *dev;
@@ -2150,8 +2151,10 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
2150 ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 2151 ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
2151 } 2152 }
2152 2153
2153 ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID | 2154 if (!vlan_promisc)
2154 ICE_AQ_VSI_PROP_SW_VALID); 2155 ctxt->info.valid_sections =
2156 cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
2157 ICE_AQ_VSI_PROP_SW_VALID);
2155 2158
2156 status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL); 2159 status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL);
2157 if (status) { 2160 if (status) {
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index 7988a53729a9..044617138122 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -35,7 +35,7 @@ int
35ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 35ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
36 u16 rel_vmvf_num); 36 u16 rel_vmvf_num);
37 37
38int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena); 38int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc);
39 39
40void ice_vsi_delete(struct ice_vsi *vsi); 40void ice_vsi_delete(struct ice_vsi *vsi);
41 41
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 34712e38121e..879c1f176a17 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -168,6 +168,39 @@ static bool ice_vsi_fltr_changed(struct ice_vsi *vsi)
168} 168}
169 169
170/** 170/**
171 * ice_cfg_promisc - Enable or disable promiscuous mode for a given PF
172 * @vsi: the VSI being configured
173 * @promisc_m: mask of promiscuous config bits
174 * @set_promisc: enable or disable promisc flag request
175 *
176 */
177static int ice_cfg_promisc(struct ice_vsi *vsi, u8 promisc_m, bool set_promisc)
178{
179 struct ice_hw *hw = &vsi->back->hw;
180 enum ice_status status = 0;
181
182 if (vsi->type != ICE_VSI_PF)
183 return 0;
184
185 if (vsi->vlan_ena) {
186 status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m,
187 set_promisc);
188 } else {
189 if (set_promisc)
190 status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
191 0);
192 else
193 status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
194 0);
195 }
196
197 if (status)
198 return -EIO;
199
200 return 0;
201}
202
203/**
171 * ice_vsi_sync_fltr - Update the VSI filter list to the HW 204 * ice_vsi_sync_fltr - Update the VSI filter list to the HW
172 * @vsi: ptr to the VSI 205 * @vsi: ptr to the VSI
173 * 206 *
@@ -182,6 +215,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
182 struct ice_hw *hw = &pf->hw; 215 struct ice_hw *hw = &pf->hw;
183 enum ice_status status = 0; 216 enum ice_status status = 0;
184 u32 changed_flags = 0; 217 u32 changed_flags = 0;
218 u8 promisc_m;
185 int err = 0; 219 int err = 0;
186 220
187 if (!vsi->netdev) 221 if (!vsi->netdev)
@@ -245,8 +279,35 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
245 } 279 }
246 } 280 }
247 /* check for changes in promiscuous modes */ 281 /* check for changes in promiscuous modes */
248 if (changed_flags & IFF_ALLMULTI) 282 if (changed_flags & IFF_ALLMULTI) {
249 netdev_warn(netdev, "Unsupported configuration\n"); 283 if (vsi->current_netdev_flags & IFF_ALLMULTI) {
284 if (vsi->vlan_ena)
285 promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
286 else
287 promisc_m = ICE_MCAST_PROMISC_BITS;
288
289 err = ice_cfg_promisc(vsi, promisc_m, true);
290 if (err) {
291 netdev_err(netdev, "Error setting Multicast promiscuous mode on VSI %i\n",
292 vsi->vsi_num);
293 vsi->current_netdev_flags &= ~IFF_ALLMULTI;
294 goto out_promisc;
295 }
296 } else if (!(vsi->current_netdev_flags & IFF_ALLMULTI)) {
297 if (vsi->vlan_ena)
298 promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
299 else
300 promisc_m = ICE_MCAST_PROMISC_BITS;
301
302 err = ice_cfg_promisc(vsi, promisc_m, false);
303 if (err) {
304 netdev_err(netdev, "Error clearing Multicast promiscuous mode on VSI %i\n",
305 vsi->vsi_num);
306 vsi->current_netdev_flags |= IFF_ALLMULTI;
307 goto out_promisc;
308 }
309 }
310 }
250 311
251 if (((changed_flags & IFF_PROMISC) || promisc_forced_on) || 312 if (((changed_flags & IFF_PROMISC) || promisc_forced_on) ||
252 test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) { 313 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,
1665{ 1726{
1666 struct ice_netdev_priv *np = netdev_priv(netdev); 1727 struct ice_netdev_priv *np = netdev_priv(netdev);
1667 struct ice_vsi *vsi = np->vsi; 1728 struct ice_vsi *vsi = np->vsi;
1729 int ret;
1668 1730
1669 if (vid >= VLAN_N_VID) { 1731 if (vid >= VLAN_N_VID) {
1670 netdev_err(netdev, "VLAN id requested %d is out of range %d\n", 1732 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,
1677 1739
1678 /* Enable VLAN pruning when VLAN 0 is added */ 1740 /* Enable VLAN pruning when VLAN 0 is added */
1679 if (unlikely(!vid)) { 1741 if (unlikely(!vid)) {
1680 int ret = ice_cfg_vlan_pruning(vsi, true); 1742 ret = ice_cfg_vlan_pruning(vsi, true, false);
1681
1682 if (ret) 1743 if (ret)
1683 return ret; 1744 return ret;
1684 } 1745 }
@@ -1687,7 +1748,13 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
1687 * needed to continue allowing all untagged packets since VLAN prune 1748 * needed to continue allowing all untagged packets since VLAN prune
1688 * list is applied to all packets by the switch 1749 * list is applied to all packets by the switch
1689 */ 1750 */
1690 return ice_vsi_add_vlan(vsi, vid); 1751 ret = ice_vsi_add_vlan(vsi, vid);
1752 if (!ret) {
1753 vsi->vlan_ena = true;
1754 set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
1755 }
1756
1757 return ret;
1691} 1758}
1692 1759
1693/** 1760/**
@@ -1704,7 +1771,7 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
1704{ 1771{
1705 struct ice_netdev_priv *np = netdev_priv(netdev); 1772 struct ice_netdev_priv *np = netdev_priv(netdev);
1706 struct ice_vsi *vsi = np->vsi; 1773 struct ice_vsi *vsi = np->vsi;
1707 int status; 1774 int ret;
1708 1775
1709 if (vsi->info.pvid) 1776 if (vsi->info.pvid)
1710 return -EINVAL; 1777 return -EINVAL;
@@ -1712,15 +1779,17 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
1712 /* Make sure ice_vsi_kill_vlan is successful before updating VLAN 1779 /* Make sure ice_vsi_kill_vlan is successful before updating VLAN
1713 * information 1780 * information
1714 */ 1781 */
1715 status = ice_vsi_kill_vlan(vsi, vid); 1782 ret = ice_vsi_kill_vlan(vsi, vid);
1716 if (status) 1783 if (ret)
1717 return status; 1784 return ret;
1718 1785
1719 /* Disable VLAN pruning when VLAN 0 is removed */ 1786 /* Disable VLAN pruning when VLAN 0 is removed */
1720 if (unlikely(!vid)) 1787 if (unlikely(!vid))
1721 status = ice_cfg_vlan_pruning(vsi, false); 1788 ret = ice_cfg_vlan_pruning(vsi, false, false);
1722 1789
1723 return status; 1790 vsi->vlan_ena = false;
1791 set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
1792 return ret;
1724} 1793}
1725 1794
1726/** 1795/**
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index ed87361f6112..64e9e0cb61ce 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -2190,6 +2190,291 @@ ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2190} 2190}
2191 2191
2192/** 2192/**
2193 * ice_determine_promisc_mask
2194 * @fi: filter info to parse
2195 *
2196 * Helper function to determine which ICE_PROMISC_ mask corresponds
2197 * to given filter into.
2198 */
2199static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
2200{
2201 u16 vid = fi->l_data.mac_vlan.vlan_id;
2202 u8 *macaddr = fi->l_data.mac.mac_addr;
2203 bool is_tx_fltr = false;
2204 u8 promisc_mask = 0;
2205
2206 if (fi->flag == ICE_FLTR_TX)
2207 is_tx_fltr = true;
2208
2209 if (is_broadcast_ether_addr(macaddr))
2210 promisc_mask |= is_tx_fltr ?
2211 ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
2212 else if (is_multicast_ether_addr(macaddr))
2213 promisc_mask |= is_tx_fltr ?
2214 ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
2215 else if (is_unicast_ether_addr(macaddr))
2216 promisc_mask |= is_tx_fltr ?
2217 ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
2218 if (vid)
2219 promisc_mask |= is_tx_fltr ?
2220 ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
2221
2222 return promisc_mask;
2223}
2224
2225/**
2226 * ice_remove_promisc - Remove promisc based filter rules
2227 * @hw: pointer to the hardware structure
2228 * @recp_id: recipe id for which the rule needs to removed
2229 * @v_list: list of promisc entries
2230 */
2231static enum ice_status
2232ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
2233 struct list_head *v_list)
2234{
2235 struct ice_fltr_list_entry *v_list_itr, *tmp;
2236
2237 list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2238 v_list_itr->status =
2239 ice_remove_rule_internal(hw, recp_id, v_list_itr);
2240 if (v_list_itr->status)
2241 return v_list_itr->status;
2242 }
2243 return 0;
2244}
2245
2246/**
2247 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
2248 * @hw: pointer to the hardware structure
2249 * @vsi_handle: VSI handle to clear mode
2250 * @promisc_mask: mask of promiscuous config bits to clear
2251 * @vid: VLAN ID to clear VLAN promiscuous
2252 */
2253enum ice_status
2254ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2255 u16 vid)
2256{
2257 struct ice_switch_info *sw = hw->switch_info;
2258 struct ice_fltr_list_entry *fm_entry, *tmp;
2259 struct list_head remove_list_head;
2260 struct ice_fltr_mgmt_list_entry *itr;
2261 struct list_head *rule_head;
2262 struct mutex *rule_lock; /* Lock to protect filter rule list */
2263 enum ice_status status = 0;
2264 u8 recipe_id;
2265
2266 if (!ice_is_vsi_valid(hw, vsi_handle))
2267 return ICE_ERR_PARAM;
2268
2269 if (vid)
2270 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2271 else
2272 recipe_id = ICE_SW_LKUP_PROMISC;
2273
2274 rule_head = &sw->recp_list[recipe_id].filt_rules;
2275 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
2276
2277 INIT_LIST_HEAD(&remove_list_head);
2278
2279 mutex_lock(rule_lock);
2280 list_for_each_entry(itr, rule_head, list_entry) {
2281 u8 fltr_promisc_mask = 0;
2282
2283 if (!ice_vsi_uses_fltr(itr, vsi_handle))
2284 continue;
2285
2286 fltr_promisc_mask |=
2287 ice_determine_promisc_mask(&itr->fltr_info);
2288
2289 /* Skip if filter is not completely specified by given mask */
2290 if (fltr_promisc_mask & ~promisc_mask)
2291 continue;
2292
2293 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2294 &remove_list_head,
2295 &itr->fltr_info);
2296 if (status) {
2297 mutex_unlock(rule_lock);
2298 goto free_fltr_list;
2299 }
2300 }
2301 mutex_unlock(rule_lock);
2302
2303 status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
2304
2305free_fltr_list:
2306 list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
2307 list_del(&fm_entry->list_entry);
2308 devm_kfree(ice_hw_to_dev(hw), fm_entry);
2309 }
2310
2311 return status;
2312}
2313
2314/**
2315 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
2316 * @hw: pointer to the hardware structure
2317 * @vsi_handle: VSI handle to configure
2318 * @promisc_mask: mask of promiscuous config bits
2319 * @vid: VLAN ID to set VLAN promiscuous
2320 */
2321enum ice_status
2322ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
2323{
2324 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
2325 struct ice_fltr_list_entry f_list_entry;
2326 struct ice_fltr_info new_fltr;
2327 enum ice_status status = 0;
2328 bool is_tx_fltr;
2329 u16 hw_vsi_id;
2330 int pkt_type;
2331 u8 recipe_id;
2332
2333 if (!ice_is_vsi_valid(hw, vsi_handle))
2334 return ICE_ERR_PARAM;
2335 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2336
2337 memset(&new_fltr, 0, sizeof(new_fltr));
2338
2339 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
2340 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
2341 new_fltr.l_data.mac_vlan.vlan_id = vid;
2342 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2343 } else {
2344 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
2345 recipe_id = ICE_SW_LKUP_PROMISC;
2346 }
2347
2348 /* Separate filters must be set for each direction/packet type
2349 * combination, so we will loop over the mask value, store the
2350 * individual type, and clear it out in the input mask as it
2351 * is found.
2352 */
2353 while (promisc_mask) {
2354 u8 *mac_addr;
2355
2356 pkt_type = 0;
2357 is_tx_fltr = false;
2358
2359 if (promisc_mask & ICE_PROMISC_UCAST_RX) {
2360 promisc_mask &= ~ICE_PROMISC_UCAST_RX;
2361 pkt_type = UCAST_FLTR;
2362 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
2363 promisc_mask &= ~ICE_PROMISC_UCAST_TX;
2364 pkt_type = UCAST_FLTR;
2365 is_tx_fltr = true;
2366 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
2367 promisc_mask &= ~ICE_PROMISC_MCAST_RX;
2368 pkt_type = MCAST_FLTR;
2369 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
2370 promisc_mask &= ~ICE_PROMISC_MCAST_TX;
2371 pkt_type = MCAST_FLTR;
2372 is_tx_fltr = true;
2373 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
2374 promisc_mask &= ~ICE_PROMISC_BCAST_RX;
2375 pkt_type = BCAST_FLTR;
2376 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
2377 promisc_mask &= ~ICE_PROMISC_BCAST_TX;
2378 pkt_type = BCAST_FLTR;
2379 is_tx_fltr = true;
2380 }
2381
2382 /* Check for VLAN promiscuous flag */
2383 if (promisc_mask & ICE_PROMISC_VLAN_RX) {
2384 promisc_mask &= ~ICE_PROMISC_VLAN_RX;
2385 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
2386 promisc_mask &= ~ICE_PROMISC_VLAN_TX;
2387 is_tx_fltr = true;
2388 }
2389
2390 /* Set filter DA based on packet type */
2391 mac_addr = new_fltr.l_data.mac.mac_addr;
2392 if (pkt_type == BCAST_FLTR) {
2393 eth_broadcast_addr(mac_addr);
2394 } else if (pkt_type == MCAST_FLTR ||
2395 pkt_type == UCAST_FLTR) {
2396 /* Use the dummy ether header DA */
2397 ether_addr_copy(mac_addr, dummy_eth_header);
2398 if (pkt_type == MCAST_FLTR)
2399 mac_addr[0] |= 0x1; /* Set multicast bit */
2400 }
2401
2402 /* Need to reset this to zero for all iterations */
2403 new_fltr.flag = 0;
2404 if (is_tx_fltr) {
2405 new_fltr.flag |= ICE_FLTR_TX;
2406 new_fltr.src = hw_vsi_id;
2407 } else {
2408 new_fltr.flag |= ICE_FLTR_RX;
2409 new_fltr.src = hw->port_info->lport;
2410 }
2411
2412 new_fltr.fltr_act = ICE_FWD_TO_VSI;
2413 new_fltr.vsi_handle = vsi_handle;
2414 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
2415 f_list_entry.fltr_info = new_fltr;
2416
2417 status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
2418 if (status)
2419 goto set_promisc_exit;
2420 }
2421
2422set_promisc_exit:
2423 return status;
2424}
2425
2426/**
2427 * ice_set_vlan_vsi_promisc
2428 * @hw: pointer to the hardware structure
2429 * @vsi_handle: VSI handle to configure
2430 * @promisc_mask: mask of promiscuous config bits
2431 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
2432 *
2433 * Configure VSI with all associated VLANs to given promiscuous mode(s)
2434 */
2435enum ice_status
2436ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2437 bool rm_vlan_promisc)
2438{
2439 struct ice_switch_info *sw = hw->switch_info;
2440 struct ice_fltr_list_entry *list_itr, *tmp;
2441 struct list_head vsi_list_head;
2442 struct list_head *vlan_head;
2443 struct mutex *vlan_lock; /* Lock to protect filter rule list */
2444 enum ice_status status;
2445 u16 vlan_id;
2446
2447 INIT_LIST_HEAD(&vsi_list_head);
2448 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
2449 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
2450 mutex_lock(vlan_lock);
2451 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
2452 &vsi_list_head);
2453 mutex_unlock(vlan_lock);
2454 if (status)
2455 goto free_fltr_list;
2456
2457 list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
2458 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
2459 if (rm_vlan_promisc)
2460 status = ice_clear_vsi_promisc(hw, vsi_handle,
2461 promisc_mask, vlan_id);
2462 else
2463 status = ice_set_vsi_promisc(hw, vsi_handle,
2464 promisc_mask, vlan_id);
2465 if (status)
2466 break;
2467 }
2468
2469free_fltr_list:
2470 list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
2471 list_del(&list_itr->list_entry);
2472 devm_kfree(ice_hw_to_dev(hw), list_itr);
2473 }
2474 return status;
2475}
2476
2477/**
2193 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 2478 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
2194 * @hw: pointer to the hardware structure 2479 * @hw: pointer to the hardware structure
2195 * @vsi_handle: VSI handle to remove filters from 2480 * @vsi_handle: VSI handle to remove filters from
@@ -2224,12 +2509,14 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
2224 case ICE_SW_LKUP_VLAN: 2509 case ICE_SW_LKUP_VLAN:
2225 ice_remove_vlan(hw, &remove_list_head); 2510 ice_remove_vlan(hw, &remove_list_head);
2226 break; 2511 break;
2512 case ICE_SW_LKUP_PROMISC:
2513 case ICE_SW_LKUP_PROMISC_VLAN:
2514 ice_remove_promisc(hw, lkup, &remove_list_head);
2515 break;
2227 case ICE_SW_LKUP_MAC_VLAN: 2516 case ICE_SW_LKUP_MAC_VLAN:
2228 case ICE_SW_LKUP_ETHERTYPE: 2517 case ICE_SW_LKUP_ETHERTYPE:
2229 case ICE_SW_LKUP_ETHERTYPE_MAC: 2518 case ICE_SW_LKUP_ETHERTYPE_MAC:
2230 case ICE_SW_LKUP_PROMISC:
2231 case ICE_SW_LKUP_DFLT: 2519 case ICE_SW_LKUP_DFLT:
2232 case ICE_SW_LKUP_PROMISC_VLAN:
2233 case ICE_SW_LKUP_LAST: 2520 case ICE_SW_LKUP_LAST:
2234 default: 2521 default:
2235 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup); 2522 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h
index 2d3a2dfcb0de..e4ce0720b871 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.h
+++ b/drivers/net/ethernet/intel/ice/ice_switch.h
@@ -178,6 +178,17 @@ struct ice_fltr_mgmt_list_entry {
178 u8 counter_index; 178 u8 counter_index;
179}; 179};
180 180
181enum ice_promisc_flags {
182 ICE_PROMISC_UCAST_RX = 0x1,
183 ICE_PROMISC_UCAST_TX = 0x2,
184 ICE_PROMISC_MCAST_RX = 0x4,
185 ICE_PROMISC_MCAST_TX = 0x8,
186 ICE_PROMISC_BCAST_RX = 0x10,
187 ICE_PROMISC_BCAST_TX = 0x20,
188 ICE_PROMISC_VLAN_RX = 0x40,
189 ICE_PROMISC_VLAN_TX = 0x80,
190};
191
181/* VSI related commands */ 192/* VSI related commands */
182enum ice_status 193enum ice_status
183ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 194ice_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);
202enum ice_status 213enum ice_status
203ice_add_vlan(struct ice_hw *hw, struct list_head *m_list); 214ice_add_vlan(struct ice_hw *hw, struct list_head *m_list);
204enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list); 215enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list);
216
217/* Promisc/defport setup for VSIs */
205enum ice_status 218enum ice_status
206ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction); 219ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction);
220enum ice_status
221ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
222 u16 vid);
223enum ice_status
224ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
225 u16 vid);
226enum ice_status
227ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
228 bool rm_vlan_promisc);
207 229
208enum ice_status ice_init_def_sw_recp(struct ice_hw *hw); 230enum ice_status ice_init_def_sw_recp(struct ice_hw *hw);
209u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle); 231u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle);
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
index 926720bead48..6c0178b4b3ab 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -772,6 +772,47 @@ static void ice_cleanup_and_realloc_vf(struct ice_vf *vf)
772} 772}
773 773
774/** 774/**
775 * ice_vf_set_vsi_promisc - set given VF VSI to given promiscuous mode(s)
776 * @vf: pointer to the VF info
777 * @vsi: the VSI being configured
778 * @promisc_m: mask of promiscuous config bits
779 * @rm_promisc: promisc flag request from the VF to remove or add filter
780 *
781 * This function configures VF VSI promiscuous mode, based on the VF requests,
782 * for Unicast, Multicast and VLAN
783 */
784static enum ice_status
785ice_vf_set_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m,
786 bool rm_promisc)
787{
788 struct ice_pf *pf = vf->pf;
789 enum ice_status status = 0;
790 struct ice_hw *hw;
791
792 hw = &pf->hw;
793 if (vf->num_vlan) {
794 status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m,
795 rm_promisc);
796 } else if (vf->port_vlan_id) {
797 if (rm_promisc)
798 status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
799 vf->port_vlan_id);
800 else
801 status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
802 vf->port_vlan_id);
803 } else {
804 if (rm_promisc)
805 status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
806 0);
807 else
808 status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
809 0);
810 }
811
812 return status;
813}
814
815/**
775 * ice_reset_all_vfs - reset all allocated VFs in one go 816 * ice_reset_all_vfs - reset all allocated VFs in one go
776 * @pf: pointer to the PF structure 817 * @pf: pointer to the PF structure
777 * @is_vflr: true if VFLR was issued, false if not 818 * @is_vflr: true if VFLR was issued, false if not
@@ -892,9 +933,10 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
892static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) 933static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
893{ 934{
894 struct ice_pf *pf = vf->pf; 935 struct ice_pf *pf = vf->pf;
895 struct ice_hw *hw = &pf->hw;
896 struct ice_vsi *vsi; 936 struct ice_vsi *vsi;
937 struct ice_hw *hw;
897 bool rsd = false; 938 bool rsd = false;
939 u8 promisc_m;
898 u32 reg; 940 u32 reg;
899 int i; 941 int i;
900 942
@@ -920,6 +962,7 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
920 vf->vf_id, NULL); 962 vf->vf_id, NULL);
921 } 963 }
922 964
965 hw = &pf->hw;
923 /* poll VPGEN_VFRSTAT reg to make sure 966 /* poll VPGEN_VFRSTAT reg to make sure
924 * that reset is complete 967 * that reset is complete
925 */ 968 */
@@ -945,6 +988,21 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
945 988
946 usleep_range(10000, 20000); 989 usleep_range(10000, 20000);
947 990
991 /* disable promiscuous modes in case they were enabled
992 * ignore any error if disabling process failed
993 */
994 if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
995 test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) {
996 if (vf->port_vlan_id || vf->num_vlan)
997 promisc_m = ICE_UCAST_VLAN_PROMISC_BITS;
998 else
999 promisc_m = ICE_UCAST_PROMISC_BITS;
1000
1001 vsi = pf->vsi[vf->lan_vsi_idx];
1002 if (ice_vf_set_vsi_promisc(vf, vsi, promisc_m, true))
1003 dev_err(&pf->pdev->dev, "disabling promiscuous mode failed\n");
1004 }
1005
948 /* free VF resources to begin resetting the VSI state */ 1006 /* free VF resources to begin resetting the VSI state */
949 ice_free_vf_res(vf); 1007 ice_free_vf_res(vf);
950 1008
@@ -2192,7 +2250,11 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
2192 (struct virtchnl_vlan_filter_list *)msg; 2250 (struct virtchnl_vlan_filter_list *)msg;
2193 enum ice_status aq_ret = 0; 2251 enum ice_status aq_ret = 0;
2194 struct ice_pf *pf = vf->pf; 2252 struct ice_pf *pf = vf->pf;
2253 bool vlan_promisc = false;
2195 struct ice_vsi *vsi; 2254 struct ice_vsi *vsi;
2255 struct ice_hw *hw;
2256 int status = 0;
2257 u8 promisc_m;
2196 int i; 2258 int i;
2197 2259
2198 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 2260 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)
2209 vf->num_vlan >= ICE_MAX_VLAN_PER_VF) { 2271 vf->num_vlan >= ICE_MAX_VLAN_PER_VF) {
2210 dev_info(&pf->pdev->dev, 2272 dev_info(&pf->pdev->dev,
2211 "VF is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n"); 2273 "VF is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n");
2212 aq_ret = ICE_ERR_PARAM; 2274 /* There is no need to let VF know about being not trusted,
2275 * so we can just return success message here
2276 */
2213 goto error_param; 2277 goto error_param;
2214 } 2278 }
2215 2279
@@ -2222,6 +2286,7 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
2222 } 2286 }
2223 } 2287 }
2224 2288
2289 hw = &pf->hw;
2225 vsi = ice_find_vsi_from_id(vf->pf, vfl->vsi_id); 2290 vsi = ice_find_vsi_from_id(vf->pf, vfl->vsi_id);
2226 if (!vsi) { 2291 if (!vsi) {
2227 aq_ret = ICE_ERR_PARAM; 2292 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)
2241 goto error_param; 2306 goto error_param;
2242 } 2307 }
2243 2308
2309 if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
2310 test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
2311 vlan_promisc = true;
2312
2244 if (add_v) { 2313 if (add_v) {
2245 for (i = 0; i < vfl->num_elements; i++) { 2314 for (i = 0; i < vfl->num_elements; i++) {
2246 u16 vid = vfl->vlan_id[i]; 2315 u16 vid = vfl->vlan_id[i];
2247 2316
2248 if (!ice_vsi_add_vlan(vsi, vid)) { 2317 if (ice_vsi_add_vlan(vsi, vid)) {
2249 vf->num_vlan++; 2318 aq_ret = ICE_ERR_PARAM;
2319 goto error_param;
2320 }
2250 2321
2251 /* Enable VLAN pruning when VLAN 0 is added */ 2322 vf->num_vlan++;
2252 if (unlikely(!vid)) 2323 /* Enable VLAN pruning when VLAN is added */
2253 if (ice_cfg_vlan_pruning(vsi, true)) 2324 if (!vlan_promisc) {
2254 aq_ret = ICE_ERR_PARAM; 2325 status = ice_cfg_vlan_pruning(vsi, true, false);
2326 if (status) {
2327 aq_ret = ICE_ERR_PARAM;
2328 dev_err(&pf->pdev->dev,
2329 "Enable VLAN pruning on VLAN ID: %d failed error-%d\n",
2330 vid, status);
2331 goto error_param;
2332 }
2255 } else { 2333 } else {
2256 aq_ret = ICE_ERR_PARAM; 2334 /* Enable Ucast/Mcast VLAN promiscuous mode */
2335 promisc_m = ICE_PROMISC_VLAN_TX |
2336 ICE_PROMISC_VLAN_RX;
2337
2338 status = ice_set_vsi_promisc(hw, vsi->idx,
2339 promisc_m, vid);
2340 if (status)
2341 dev_err(&pf->pdev->dev,
2342 "Enable Unicast/multicast promiscuous mode on VLAN ID:%d failed error-%d\n",
2343 vid, status);
2257 } 2344 }
2258 } 2345 }
2259 } else { 2346 } else {
@@ -2263,12 +2350,22 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
2263 /* Make sure ice_vsi_kill_vlan is successful before 2350 /* Make sure ice_vsi_kill_vlan is successful before
2264 * updating VLAN information 2351 * updating VLAN information
2265 */ 2352 */
2266 if (!ice_vsi_kill_vlan(vsi, vid)) { 2353 if (ice_vsi_kill_vlan(vsi, vid)) {
2267 vf->num_vlan--; 2354 aq_ret = ICE_ERR_PARAM;
2355 goto error_param;
2356 }
2357
2358 vf->num_vlan--;
2359 /* Disable VLAN pruning when removing VLAN */
2360 ice_cfg_vlan_pruning(vsi, false, false);
2361
2362 /* Disable Unicast/Multicast VLAN promiscuous mode */
2363 if (vlan_promisc) {
2364 promisc_m = ICE_PROMISC_VLAN_TX |
2365 ICE_PROMISC_VLAN_RX;
2268 2366
2269 /* Disable VLAN pruning when removing VLAN 0 */ 2367 ice_clear_vsi_promisc(hw, vsi->idx,
2270 if (unlikely(!vid)) 2368 promisc_m, vid);
2271 ice_cfg_vlan_pruning(vsi, false);
2272 } 2369 }
2273 } 2370 }
2274 } 2371 }