diff options
author | Akeem G Abodunrin <akeem.g.abodunrin@intel.com> | 2019-02-26 19:35:14 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2019-03-22 11:19:17 -0400 |
commit | 5eda8afd6bcc89d4e4aa5d56b5f54276f63158ae (patch) | |
tree | 44a9e13481cd5aa025b5f576a09f93fa943bb9fa /drivers/net/ethernet | |
parent | e1ca65a3cceacc94dd9cde388016422ca2e15a54 (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.h | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lib.c | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lib.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 91 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_switch.c | 291 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_switch.h | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 125 |
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 | |||
128 | struct ice_tc_info { | 145 | struct 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 | */ |
2125 | int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena) | 2126 | int 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 | |||
35 | ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, | 35 | ice_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 | ||
38 | int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena); | 38 | int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc); |
39 | 39 | ||
40 | void ice_vsi_delete(struct ice_vsi *vsi); | 40 | void 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 | */ | ||
177 | static 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 | */ | ||
2199 | static 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 | */ | ||
2231 | static enum ice_status | ||
2232 | ice_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 | */ | ||
2253 | enum ice_status | ||
2254 | ice_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 | |||
2305 | free_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 | */ | ||
2321 | enum ice_status | ||
2322 | ice_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 | |||
2422 | set_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 | */ | ||
2435 | enum ice_status | ||
2436 | ice_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 | |||
2469 | free_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 | ||
181 | enum 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 */ |
182 | enum ice_status | 193 | enum ice_status |
183 | ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, | 194 | 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); | |||
202 | enum ice_status | 213 | enum ice_status |
203 | ice_add_vlan(struct ice_hw *hw, struct list_head *m_list); | 214 | ice_add_vlan(struct ice_hw *hw, struct list_head *m_list); |
204 | enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list); | 215 | enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list); |
216 | |||
217 | /* Promisc/defport setup for VSIs */ | ||
205 | enum ice_status | 218 | enum ice_status |
206 | ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction); | 219 | ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction); |
220 | enum ice_status | ||
221 | ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, | ||
222 | u16 vid); | ||
223 | enum ice_status | ||
224 | ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, | ||
225 | u16 vid); | ||
226 | enum ice_status | ||
227 | ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, | ||
228 | bool rm_vlan_promisc); | ||
207 | 229 | ||
208 | enum ice_status ice_init_def_sw_recp(struct ice_hw *hw); | 230 | enum ice_status ice_init_def_sw_recp(struct ice_hw *hw); |
209 | u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle); | 231 | u16 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 | */ | ||
784 | static enum ice_status | ||
785 | ice_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) | |||
892 | static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) | 933 | static 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 | } |