xref: /linux/drivers/net/ethernet/intel/ice/virt/virtchnl.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
15de6c855SPrzemek Kitszel // SPDX-License-Identifier: GPL-2.0
25de6c855SPrzemek Kitszel /* Copyright (C) 2022, Intel Corporation. */
35de6c855SPrzemek Kitszel 
45de6c855SPrzemek Kitszel #include "virtchnl.h"
5c762b0a5SPrzemek Kitszel #include "queues.h"
6*e0d2795aSPrzemek Kitszel #include "rss.h"
75de6c855SPrzemek Kitszel #include "ice_vf_lib_private.h"
85de6c855SPrzemek Kitszel #include "ice.h"
95de6c855SPrzemek Kitszel #include "ice_base.h"
105de6c855SPrzemek Kitszel #include "ice_lib.h"
115de6c855SPrzemek Kitszel #include "ice_fltr.h"
125de6c855SPrzemek Kitszel #include "allowlist.h"
135de6c855SPrzemek Kitszel #include "ice_vf_vsi_vlan_ops.h"
145de6c855SPrzemek Kitszel #include "ice_vlan.h"
155de6c855SPrzemek Kitszel #include "ice_flex_pipe.h"
165de6c855SPrzemek Kitszel #include "ice_dcb_lib.h"
175de6c855SPrzemek Kitszel 
185de6c855SPrzemek Kitszel /**
195de6c855SPrzemek Kitszel  * ice_vc_vf_broadcast - Broadcast a message to all VFs on PF
205de6c855SPrzemek Kitszel  * @pf: pointer to the PF structure
215de6c855SPrzemek Kitszel  * @v_opcode: operation code
225de6c855SPrzemek Kitszel  * @v_retval: return value
235de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
245de6c855SPrzemek Kitszel  * @msglen: msg length
255de6c855SPrzemek Kitszel  */
265de6c855SPrzemek Kitszel static void
275de6c855SPrzemek Kitszel ice_vc_vf_broadcast(struct ice_pf *pf, enum virtchnl_ops v_opcode,
285de6c855SPrzemek Kitszel 		    enum virtchnl_status_code v_retval, u8 *msg, u16 msglen)
295de6c855SPrzemek Kitszel {
305de6c855SPrzemek Kitszel 	struct ice_hw *hw = &pf->hw;
315de6c855SPrzemek Kitszel 	struct ice_vf *vf;
325de6c855SPrzemek Kitszel 	unsigned int bkt;
335de6c855SPrzemek Kitszel 
345de6c855SPrzemek Kitszel 	mutex_lock(&pf->vfs.table_lock);
355de6c855SPrzemek Kitszel 	ice_for_each_vf(pf, bkt, vf) {
365de6c855SPrzemek Kitszel 		/* Not all vfs are enabled so skip the ones that are not */
375de6c855SPrzemek Kitszel 		if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states) &&
385de6c855SPrzemek Kitszel 		    !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
395de6c855SPrzemek Kitszel 			continue;
405de6c855SPrzemek Kitszel 
415de6c855SPrzemek Kitszel 		/* Ignore return value on purpose - a given VF may fail, but
425de6c855SPrzemek Kitszel 		 * we need to keep going and send to all of them
435de6c855SPrzemek Kitszel 		 */
445de6c855SPrzemek Kitszel 		ice_aq_send_msg_to_vf(hw, vf->vf_id, v_opcode, v_retval, msg,
455de6c855SPrzemek Kitszel 				      msglen, NULL);
465de6c855SPrzemek Kitszel 	}
475de6c855SPrzemek Kitszel 	mutex_unlock(&pf->vfs.table_lock);
485de6c855SPrzemek Kitszel }
495de6c855SPrzemek Kitszel 
505de6c855SPrzemek Kitszel /**
515de6c855SPrzemek Kitszel  * ice_set_pfe_link - Set the link speed/status of the virtchnl_pf_event
525de6c855SPrzemek Kitszel  * @vf: pointer to the VF structure
535de6c855SPrzemek Kitszel  * @pfe: pointer to the virtchnl_pf_event to set link speed/status for
545de6c855SPrzemek Kitszel  * @ice_link_speed: link speed specified by ICE_AQ_LINK_SPEED_*
555de6c855SPrzemek Kitszel  * @link_up: whether or not to set the link up/down
565de6c855SPrzemek Kitszel  */
575de6c855SPrzemek Kitszel static void
585de6c855SPrzemek Kitszel ice_set_pfe_link(struct ice_vf *vf, struct virtchnl_pf_event *pfe,
595de6c855SPrzemek Kitszel 		 int ice_link_speed, bool link_up)
605de6c855SPrzemek Kitszel {
615de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
625de6c855SPrzemek Kitszel 		pfe->event_data.link_event_adv.link_status = link_up;
635de6c855SPrzemek Kitszel 		/* Speed in Mbps */
645de6c855SPrzemek Kitszel 		pfe->event_data.link_event_adv.link_speed =
655de6c855SPrzemek Kitszel 			ice_conv_link_speed_to_virtchnl(true, ice_link_speed);
665de6c855SPrzemek Kitszel 	} else {
675de6c855SPrzemek Kitszel 		pfe->event_data.link_event.link_status = link_up;
685de6c855SPrzemek Kitszel 		/* Legacy method for virtchnl link speeds */
695de6c855SPrzemek Kitszel 		pfe->event_data.link_event.link_speed =
705de6c855SPrzemek Kitszel 			(enum virtchnl_link_speed)
715de6c855SPrzemek Kitszel 			ice_conv_link_speed_to_virtchnl(false, ice_link_speed);
725de6c855SPrzemek Kitszel 	}
735de6c855SPrzemek Kitszel }
745de6c855SPrzemek Kitszel 
755de6c855SPrzemek Kitszel /**
765de6c855SPrzemek Kitszel  * ice_vc_notify_vf_link_state - Inform a VF of link status
775de6c855SPrzemek Kitszel  * @vf: pointer to the VF structure
785de6c855SPrzemek Kitszel  *
795de6c855SPrzemek Kitszel  * send a link status message to a single VF
805de6c855SPrzemek Kitszel  */
815de6c855SPrzemek Kitszel void ice_vc_notify_vf_link_state(struct ice_vf *vf)
825de6c855SPrzemek Kitszel {
835de6c855SPrzemek Kitszel 	struct virtchnl_pf_event pfe = { 0 };
845de6c855SPrzemek Kitszel 	struct ice_hw *hw = &vf->pf->hw;
855de6c855SPrzemek Kitszel 
865de6c855SPrzemek Kitszel 	pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
875de6c855SPrzemek Kitszel 	pfe.severity = PF_EVENT_SEVERITY_INFO;
885de6c855SPrzemek Kitszel 
895de6c855SPrzemek Kitszel 	if (ice_is_vf_link_up(vf))
905de6c855SPrzemek Kitszel 		ice_set_pfe_link(vf, &pfe,
915de6c855SPrzemek Kitszel 				 hw->port_info->phy.link_info.link_speed, true);
925de6c855SPrzemek Kitszel 	else
935de6c855SPrzemek Kitszel 		ice_set_pfe_link(vf, &pfe, ICE_AQ_LINK_SPEED_UNKNOWN, false);
945de6c855SPrzemek Kitszel 
955de6c855SPrzemek Kitszel 	ice_aq_send_msg_to_vf(hw, vf->vf_id, VIRTCHNL_OP_EVENT,
965de6c855SPrzemek Kitszel 			      VIRTCHNL_STATUS_SUCCESS, (u8 *)&pfe,
975de6c855SPrzemek Kitszel 			      sizeof(pfe), NULL);
985de6c855SPrzemek Kitszel }
995de6c855SPrzemek Kitszel 
1005de6c855SPrzemek Kitszel /**
1015de6c855SPrzemek Kitszel  * ice_vc_notify_link_state - Inform all VFs on a PF of link status
1025de6c855SPrzemek Kitszel  * @pf: pointer to the PF structure
1035de6c855SPrzemek Kitszel  */
1045de6c855SPrzemek Kitszel void ice_vc_notify_link_state(struct ice_pf *pf)
1055de6c855SPrzemek Kitszel {
1065de6c855SPrzemek Kitszel 	struct ice_vf *vf;
1075de6c855SPrzemek Kitszel 	unsigned int bkt;
1085de6c855SPrzemek Kitszel 
1095de6c855SPrzemek Kitszel 	mutex_lock(&pf->vfs.table_lock);
1105de6c855SPrzemek Kitszel 	ice_for_each_vf(pf, bkt, vf)
1115de6c855SPrzemek Kitszel 		ice_vc_notify_vf_link_state(vf);
1125de6c855SPrzemek Kitszel 	mutex_unlock(&pf->vfs.table_lock);
1135de6c855SPrzemek Kitszel }
1145de6c855SPrzemek Kitszel 
1155de6c855SPrzemek Kitszel /**
1165de6c855SPrzemek Kitszel  * ice_vc_notify_reset - Send pending reset message to all VFs
1175de6c855SPrzemek Kitszel  * @pf: pointer to the PF structure
1185de6c855SPrzemek Kitszel  *
1195de6c855SPrzemek Kitszel  * indicate a pending reset to all VFs on a given PF
1205de6c855SPrzemek Kitszel  */
1215de6c855SPrzemek Kitszel void ice_vc_notify_reset(struct ice_pf *pf)
1225de6c855SPrzemek Kitszel {
1235de6c855SPrzemek Kitszel 	struct virtchnl_pf_event pfe;
1245de6c855SPrzemek Kitszel 
1255de6c855SPrzemek Kitszel 	if (!ice_has_vfs(pf))
1265de6c855SPrzemek Kitszel 		return;
1275de6c855SPrzemek Kitszel 
1285de6c855SPrzemek Kitszel 	pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
1295de6c855SPrzemek Kitszel 	pfe.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM;
1305de6c855SPrzemek Kitszel 	ice_vc_vf_broadcast(pf, VIRTCHNL_OP_EVENT, VIRTCHNL_STATUS_SUCCESS,
1315de6c855SPrzemek Kitszel 			    (u8 *)&pfe, sizeof(struct virtchnl_pf_event));
1325de6c855SPrzemek Kitszel }
1335de6c855SPrzemek Kitszel 
1345de6c855SPrzemek Kitszel /**
1355de6c855SPrzemek Kitszel  * ice_vc_send_msg_to_vf - Send message to VF
1365de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
1375de6c855SPrzemek Kitszel  * @v_opcode: virtual channel opcode
1385de6c855SPrzemek Kitszel  * @v_retval: virtual channel return value
1395de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
1405de6c855SPrzemek Kitszel  * @msglen: msg length
1415de6c855SPrzemek Kitszel  *
1425de6c855SPrzemek Kitszel  * send msg to VF
1435de6c855SPrzemek Kitszel  */
1445de6c855SPrzemek Kitszel int
1455de6c855SPrzemek Kitszel ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
1465de6c855SPrzemek Kitszel 		      enum virtchnl_status_code v_retval, u8 *msg, u16 msglen)
1475de6c855SPrzemek Kitszel {
1485de6c855SPrzemek Kitszel 	struct device *dev;
1495de6c855SPrzemek Kitszel 	struct ice_pf *pf;
1505de6c855SPrzemek Kitszel 	int aq_ret;
1515de6c855SPrzemek Kitszel 
1525de6c855SPrzemek Kitszel 	pf = vf->pf;
1535de6c855SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
1545de6c855SPrzemek Kitszel 
1555de6c855SPrzemek Kitszel 	aq_ret = ice_aq_send_msg_to_vf(&pf->hw, vf->vf_id, v_opcode, v_retval,
1565de6c855SPrzemek Kitszel 				       msg, msglen, NULL);
1575de6c855SPrzemek Kitszel 	if (aq_ret && pf->hw.mailboxq.sq_last_status != LIBIE_AQ_RC_ENOSYS) {
1585de6c855SPrzemek Kitszel 		dev_info(dev, "Unable to send the message to VF %d ret %d aq_err %s\n",
1595de6c855SPrzemek Kitszel 			 vf->vf_id, aq_ret,
1605de6c855SPrzemek Kitszel 			 libie_aq_str(pf->hw.mailboxq.sq_last_status));
1615de6c855SPrzemek Kitszel 		return -EIO;
1625de6c855SPrzemek Kitszel 	}
1635de6c855SPrzemek Kitszel 
1645de6c855SPrzemek Kitszel 	return 0;
1655de6c855SPrzemek Kitszel }
1665de6c855SPrzemek Kitszel 
1675de6c855SPrzemek Kitszel /**
1685de6c855SPrzemek Kitszel  * ice_vc_get_ver_msg
1695de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
1705de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
1715de6c855SPrzemek Kitszel  *
1725de6c855SPrzemek Kitszel  * called from the VF to request the API version used by the PF
1735de6c855SPrzemek Kitszel  */
1745de6c855SPrzemek Kitszel static int ice_vc_get_ver_msg(struct ice_vf *vf, u8 *msg)
1755de6c855SPrzemek Kitszel {
1765de6c855SPrzemek Kitszel 	struct virtchnl_version_info info = {
1775de6c855SPrzemek Kitszel 		VIRTCHNL_VERSION_MAJOR, VIRTCHNL_VERSION_MINOR
1785de6c855SPrzemek Kitszel 	};
1795de6c855SPrzemek Kitszel 
1805de6c855SPrzemek Kitszel 	vf->vf_ver = *(struct virtchnl_version_info *)msg;
1815de6c855SPrzemek Kitszel 	/* VFs running the 1.0 API expect to get 1.0 back or they will cry. */
1825de6c855SPrzemek Kitszel 	if (VF_IS_V10(&vf->vf_ver))
1835de6c855SPrzemek Kitszel 		info.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;
1845de6c855SPrzemek Kitszel 
1855de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_VERSION,
1865de6c855SPrzemek Kitszel 				     VIRTCHNL_STATUS_SUCCESS, (u8 *)&info,
1875de6c855SPrzemek Kitszel 				     sizeof(struct virtchnl_version_info));
1885de6c855SPrzemek Kitszel }
1895de6c855SPrzemek Kitszel 
1905de6c855SPrzemek Kitszel /**
1915de6c855SPrzemek Kitszel  * ice_vc_get_vlan_caps
1925de6c855SPrzemek Kitszel  * @hw: pointer to the hw
1935de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
1945de6c855SPrzemek Kitszel  * @vsi: pointer to the VSI
1955de6c855SPrzemek Kitszel  * @driver_caps: current driver caps
1965de6c855SPrzemek Kitszel  *
1975de6c855SPrzemek Kitszel  * Return 0 if there is no VLAN caps supported, or VLAN caps value
1985de6c855SPrzemek Kitszel  */
1995de6c855SPrzemek Kitszel static u32
2005de6c855SPrzemek Kitszel ice_vc_get_vlan_caps(struct ice_hw *hw, struct ice_vf *vf, struct ice_vsi *vsi,
2015de6c855SPrzemek Kitszel 		     u32 driver_caps)
2025de6c855SPrzemek Kitszel {
2035de6c855SPrzemek Kitszel 	if (ice_is_eswitch_mode_switchdev(vf->pf))
2045de6c855SPrzemek Kitszel 		/* In switchdev setting VLAN from VF isn't supported */
2055de6c855SPrzemek Kitszel 		return 0;
2065de6c855SPrzemek Kitszel 
2075de6c855SPrzemek Kitszel 	if (driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
2085de6c855SPrzemek Kitszel 		/* VLAN offloads based on current device configuration */
2095de6c855SPrzemek Kitszel 		return VIRTCHNL_VF_OFFLOAD_VLAN_V2;
2105de6c855SPrzemek Kitszel 	} else if (driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN) {
2115de6c855SPrzemek Kitszel 		/* allow VF to negotiate VIRTCHNL_VF_OFFLOAD explicitly for
2125de6c855SPrzemek Kitszel 		 * these two conditions, which amounts to guest VLAN filtering
2135de6c855SPrzemek Kitszel 		 * and offloads being based on the inner VLAN or the
2145de6c855SPrzemek Kitszel 		 * inner/single VLAN respectively and don't allow VF to
2155de6c855SPrzemek Kitszel 		 * negotiate VIRTCHNL_VF_OFFLOAD in any other cases
2165de6c855SPrzemek Kitszel 		 */
2175de6c855SPrzemek Kitszel 		if (ice_is_dvm_ena(hw) && ice_vf_is_port_vlan_ena(vf)) {
2185de6c855SPrzemek Kitszel 			return VIRTCHNL_VF_OFFLOAD_VLAN;
2195de6c855SPrzemek Kitszel 		} else if (!ice_is_dvm_ena(hw) &&
2205de6c855SPrzemek Kitszel 			   !ice_vf_is_port_vlan_ena(vf)) {
2215de6c855SPrzemek Kitszel 			/* configure backward compatible support for VFs that
2225de6c855SPrzemek Kitszel 			 * only support VIRTCHNL_VF_OFFLOAD_VLAN, the PF is
2235de6c855SPrzemek Kitszel 			 * configured in SVM, and no port VLAN is configured
2245de6c855SPrzemek Kitszel 			 */
2255de6c855SPrzemek Kitszel 			ice_vf_vsi_cfg_svm_legacy_vlan_mode(vsi);
2265de6c855SPrzemek Kitszel 			return VIRTCHNL_VF_OFFLOAD_VLAN;
2275de6c855SPrzemek Kitszel 		} else if (ice_is_dvm_ena(hw)) {
2285de6c855SPrzemek Kitszel 			/* configure software offloaded VLAN support when DVM
2295de6c855SPrzemek Kitszel 			 * is enabled, but no port VLAN is enabled
2305de6c855SPrzemek Kitszel 			 */
2315de6c855SPrzemek Kitszel 			ice_vf_vsi_cfg_dvm_legacy_vlan_mode(vsi);
2325de6c855SPrzemek Kitszel 		}
2335de6c855SPrzemek Kitszel 	}
2345de6c855SPrzemek Kitszel 
2355de6c855SPrzemek Kitszel 	return 0;
2365de6c855SPrzemek Kitszel }
2375de6c855SPrzemek Kitszel 
2385de6c855SPrzemek Kitszel /**
2395de6c855SPrzemek Kitszel  * ice_vc_get_vf_res_msg
2405de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
2415de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
2425de6c855SPrzemek Kitszel  *
2435de6c855SPrzemek Kitszel  * called from the VF to request its resources
2445de6c855SPrzemek Kitszel  */
2455de6c855SPrzemek Kitszel static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
2465de6c855SPrzemek Kitszel {
2475de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2485de6c855SPrzemek Kitszel 	struct virtchnl_vf_resource *vfres = NULL;
2495de6c855SPrzemek Kitszel 	struct ice_hw *hw = &vf->pf->hw;
2505de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
2515de6c855SPrzemek Kitszel 	int len = 0;
2525de6c855SPrzemek Kitszel 	int ret;
2535de6c855SPrzemek Kitszel 
2545de6c855SPrzemek Kitszel 	if (ice_check_vf_init(vf)) {
2555de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2565de6c855SPrzemek Kitszel 		goto err;
2575de6c855SPrzemek Kitszel 	}
2585de6c855SPrzemek Kitszel 
2595de6c855SPrzemek Kitszel 	len = virtchnl_struct_size(vfres, vsi_res, 0);
2605de6c855SPrzemek Kitszel 
2615de6c855SPrzemek Kitszel 	vfres = kzalloc(len, GFP_KERNEL);
2625de6c855SPrzemek Kitszel 	if (!vfres) {
2635de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2645de6c855SPrzemek Kitszel 		len = 0;
2655de6c855SPrzemek Kitszel 		goto err;
2665de6c855SPrzemek Kitszel 	}
2675de6c855SPrzemek Kitszel 	if (VF_IS_V11(&vf->vf_ver))
2685de6c855SPrzemek Kitszel 		vf->driver_caps = *(u32 *)msg;
2695de6c855SPrzemek Kitszel 	else
2705de6c855SPrzemek Kitszel 		vf->driver_caps = VIRTCHNL_VF_OFFLOAD_L2 |
2715de6c855SPrzemek Kitszel 				  VIRTCHNL_VF_OFFLOAD_VLAN;
2725de6c855SPrzemek Kitszel 
2735de6c855SPrzemek Kitszel 	vfres->vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2;
2745de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
2755de6c855SPrzemek Kitszel 	if (!vsi) {
2765de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2775de6c855SPrzemek Kitszel 		goto err;
2785de6c855SPrzemek Kitszel 	}
2795de6c855SPrzemek Kitszel 
2805de6c855SPrzemek Kitszel 	vfres->vf_cap_flags |= ice_vc_get_vlan_caps(hw, vf, vsi,
2815de6c855SPrzemek Kitszel 						    vf->driver_caps);
2825de6c855SPrzemek Kitszel 
2835de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF)
2845de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PF;
2855de6c855SPrzemek Kitszel 
2865de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)
2875de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC;
2885de6c855SPrzemek Kitszel 
2895de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF)
2905de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_FDIR_PF;
2915de6c855SPrzemek Kitszel 
2925de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_TC_U32 &&
2935de6c855SPrzemek Kitszel 	    vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_FDIR_PF)
2945de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_TC_U32;
2955de6c855SPrzemek Kitszel 
2965de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
2975de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2;
2985de6c855SPrzemek Kitszel 
2995de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ENCAP)
3005de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_ENCAP;
3015de6c855SPrzemek Kitszel 
3025de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM)
3035de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
3045de6c855SPrzemek Kitszel 
3055de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_POLLING)
3065de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RX_POLLING;
3075de6c855SPrzemek Kitszel 
3085de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
3095de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_WB_ON_ITR;
3105de6c855SPrzemek Kitszel 
3115de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)
3125de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
3135de6c855SPrzemek Kitszel 
3145de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_CRC)
3155de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_CRC;
3165de6c855SPrzemek Kitszel 
3175de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
3185de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
3195de6c855SPrzemek Kitszel 
3205de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF)
3215de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF;
3225de6c855SPrzemek Kitszel 
3235de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_USO)
3245de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_USO;
3255de6c855SPrzemek Kitszel 
3265de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_QOS)
3275de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_QOS;
3285de6c855SPrzemek Kitszel 
3295de6c855SPrzemek Kitszel 	if (vf->driver_caps & VIRTCHNL_VF_CAP_PTP)
3305de6c855SPrzemek Kitszel 		vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_PTP;
3315de6c855SPrzemek Kitszel 
3325de6c855SPrzemek Kitszel 	vfres->num_vsis = 1;
3335de6c855SPrzemek Kitszel 	/* Tx and Rx queue are equal for VF */
3345de6c855SPrzemek Kitszel 	vfres->num_queue_pairs = vsi->num_txq;
3355de6c855SPrzemek Kitszel 	vfres->max_vectors = vf->num_msix;
3365de6c855SPrzemek Kitszel 	vfres->rss_key_size = ICE_VSIQF_HKEY_ARRAY_SIZE;
3375de6c855SPrzemek Kitszel 	vfres->rss_lut_size = ICE_LUT_VSI_SIZE;
3385de6c855SPrzemek Kitszel 	vfres->max_mtu = ice_vc_get_max_frame_size(vf);
3395de6c855SPrzemek Kitszel 
3405de6c855SPrzemek Kitszel 	vfres->vsi_res[0].vsi_id = ICE_VF_VSI_ID;
3415de6c855SPrzemek Kitszel 	vfres->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;
3425de6c855SPrzemek Kitszel 	vfres->vsi_res[0].num_queue_pairs = vsi->num_txq;
3435de6c855SPrzemek Kitszel 	ether_addr_copy(vfres->vsi_res[0].default_mac_addr,
3445de6c855SPrzemek Kitszel 			vf->hw_lan_addr);
3455de6c855SPrzemek Kitszel 
3465de6c855SPrzemek Kitszel 	/* match guest capabilities */
3475de6c855SPrzemek Kitszel 	vf->driver_caps = vfres->vf_cap_flags;
3485de6c855SPrzemek Kitszel 
3495de6c855SPrzemek Kitszel 	ice_vc_set_caps_allowlist(vf);
3505de6c855SPrzemek Kitszel 	ice_vc_set_working_allowlist(vf);
3515de6c855SPrzemek Kitszel 
3525de6c855SPrzemek Kitszel 	set_bit(ICE_VF_STATE_ACTIVE, vf->vf_states);
3535de6c855SPrzemek Kitszel 
3545de6c855SPrzemek Kitszel err:
3555de6c855SPrzemek Kitszel 	/* send the response back to the VF */
3565de6c855SPrzemek Kitszel 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_VF_RESOURCES, v_ret,
3575de6c855SPrzemek Kitszel 				    (u8 *)vfres, len);
3585de6c855SPrzemek Kitszel 
3595de6c855SPrzemek Kitszel 	kfree(vfres);
3605de6c855SPrzemek Kitszel 	return ret;
3615de6c855SPrzemek Kitszel }
3625de6c855SPrzemek Kitszel 
3635de6c855SPrzemek Kitszel /**
3645de6c855SPrzemek Kitszel  * ice_vc_reset_vf_msg
3655de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
3665de6c855SPrzemek Kitszel  *
3675de6c855SPrzemek Kitszel  * called from the VF to reset itself,
3685de6c855SPrzemek Kitszel  * unlike other virtchnl messages, PF driver
3695de6c855SPrzemek Kitszel  * doesn't send the response back to the VF
3705de6c855SPrzemek Kitszel  */
3715de6c855SPrzemek Kitszel static void ice_vc_reset_vf_msg(struct ice_vf *vf)
3725de6c855SPrzemek Kitszel {
3735de6c855SPrzemek Kitszel 	if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
3745de6c855SPrzemek Kitszel 		ice_reset_vf(vf, 0);
3755de6c855SPrzemek Kitszel }
3765de6c855SPrzemek Kitszel 
3775de6c855SPrzemek Kitszel /**
3785de6c855SPrzemek Kitszel  * ice_vc_isvalid_vsi_id
3795de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
3805de6c855SPrzemek Kitszel  * @vsi_id: VF relative VSI ID
3815de6c855SPrzemek Kitszel  *
3825de6c855SPrzemek Kitszel  * check for the valid VSI ID
3835de6c855SPrzemek Kitszel  */
3845de6c855SPrzemek Kitszel bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id)
3855de6c855SPrzemek Kitszel {
3865de6c855SPrzemek Kitszel 	return vsi_id == ICE_VF_VSI_ID;
3875de6c855SPrzemek Kitszel }
3885de6c855SPrzemek Kitszel 
3895de6c855SPrzemek Kitszel /**
3905de6c855SPrzemek Kitszel  * ice_vc_get_qos_caps - Get current QoS caps from PF
3915de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
3925de6c855SPrzemek Kitszel  *
3935de6c855SPrzemek Kitszel  * Get VF's QoS capabilities, such as TC number, arbiter and
3945de6c855SPrzemek Kitszel  * bandwidth from PF.
3955de6c855SPrzemek Kitszel  *
3965de6c855SPrzemek Kitszel  * Return: 0 on success or negative error value.
3975de6c855SPrzemek Kitszel  */
3985de6c855SPrzemek Kitszel static int ice_vc_get_qos_caps(struct ice_vf *vf)
3995de6c855SPrzemek Kitszel {
4005de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
4015de6c855SPrzemek Kitszel 	struct virtchnl_qos_cap_list *cap_list = NULL;
4025de6c855SPrzemek Kitszel 	u8 tc_prio[ICE_MAX_TRAFFIC_CLASS] = { 0 };
4035de6c855SPrzemek Kitszel 	struct virtchnl_qos_cap_elem *cfg = NULL;
4045de6c855SPrzemek Kitszel 	struct ice_vsi_ctx *vsi_ctx;
4055de6c855SPrzemek Kitszel 	struct ice_pf *pf = vf->pf;
4065de6c855SPrzemek Kitszel 	struct ice_port_info *pi;
4075de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
4085de6c855SPrzemek Kitszel 	u8 numtc, tc;
4095de6c855SPrzemek Kitszel 	u16 len = 0;
4105de6c855SPrzemek Kitszel 	int ret, i;
4115de6c855SPrzemek Kitszel 
4125de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
4135de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
4145de6c855SPrzemek Kitszel 		goto err;
4155de6c855SPrzemek Kitszel 	}
4165de6c855SPrzemek Kitszel 
4175de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
4185de6c855SPrzemek Kitszel 	if (!vsi) {
4195de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
4205de6c855SPrzemek Kitszel 		goto err;
4215de6c855SPrzemek Kitszel 	}
4225de6c855SPrzemek Kitszel 
4235de6c855SPrzemek Kitszel 	pi = pf->hw.port_info;
4245de6c855SPrzemek Kitszel 	numtc = vsi->tc_cfg.numtc;
4255de6c855SPrzemek Kitszel 
4265de6c855SPrzemek Kitszel 	vsi_ctx = ice_get_vsi_ctx(pi->hw, vf->lan_vsi_idx);
4275de6c855SPrzemek Kitszel 	if (!vsi_ctx) {
4285de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
4295de6c855SPrzemek Kitszel 		goto err;
4305de6c855SPrzemek Kitszel 	}
4315de6c855SPrzemek Kitszel 
4325de6c855SPrzemek Kitszel 	len = struct_size(cap_list, cap, numtc);
4335de6c855SPrzemek Kitszel 	cap_list = kzalloc(len, GFP_KERNEL);
4345de6c855SPrzemek Kitszel 	if (!cap_list) {
4355de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
4365de6c855SPrzemek Kitszel 		len = 0;
4375de6c855SPrzemek Kitszel 		goto err;
4385de6c855SPrzemek Kitszel 	}
4395de6c855SPrzemek Kitszel 
4405de6c855SPrzemek Kitszel 	cap_list->vsi_id = vsi->vsi_num;
4415de6c855SPrzemek Kitszel 	cap_list->num_elem = numtc;
4425de6c855SPrzemek Kitszel 
4435de6c855SPrzemek Kitszel 	/* Store the UP2TC configuration from DCB to a user priority bitmap
4445de6c855SPrzemek Kitszel 	 * of each TC. Each element of prio_of_tc represents one TC. Each
4455de6c855SPrzemek Kitszel 	 * bitmap indicates the user priorities belong to this TC.
4465de6c855SPrzemek Kitszel 	 */
4475de6c855SPrzemek Kitszel 	for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) {
4485de6c855SPrzemek Kitszel 		tc = pi->qos_cfg.local_dcbx_cfg.etscfg.prio_table[i];
4495de6c855SPrzemek Kitszel 		tc_prio[tc] |= BIT(i);
4505de6c855SPrzemek Kitszel 	}
4515de6c855SPrzemek Kitszel 
4525de6c855SPrzemek Kitszel 	for (i = 0; i < numtc; i++) {
4535de6c855SPrzemek Kitszel 		cfg = &cap_list->cap[i];
4545de6c855SPrzemek Kitszel 		cfg->tc_num = i;
4555de6c855SPrzemek Kitszel 		cfg->tc_prio = tc_prio[i];
4565de6c855SPrzemek Kitszel 		cfg->arbiter = pi->qos_cfg.local_dcbx_cfg.etscfg.tsatable[i];
4575de6c855SPrzemek Kitszel 		cfg->weight = VIRTCHNL_STRICT_WEIGHT;
4585de6c855SPrzemek Kitszel 		cfg->type = VIRTCHNL_BW_SHAPER;
4595de6c855SPrzemek Kitszel 		cfg->shaper.committed = vsi_ctx->sched.bw_t_info[i].cir_bw.bw;
4605de6c855SPrzemek Kitszel 		cfg->shaper.peak = vsi_ctx->sched.bw_t_info[i].eir_bw.bw;
4615de6c855SPrzemek Kitszel 	}
4625de6c855SPrzemek Kitszel 
4635de6c855SPrzemek Kitszel err:
4645de6c855SPrzemek Kitszel 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_QOS_CAPS, v_ret,
4655de6c855SPrzemek Kitszel 				    (u8 *)cap_list, len);
4665de6c855SPrzemek Kitszel 	kfree(cap_list);
4675de6c855SPrzemek Kitszel 	return ret;
4685de6c855SPrzemek Kitszel }
4695de6c855SPrzemek Kitszel 
4705de6c855SPrzemek Kitszel /**
4715de6c855SPrzemek Kitszel  * ice_vc_cfg_promiscuous_mode_msg
4725de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
4735de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
4745de6c855SPrzemek Kitszel  *
4755de6c855SPrzemek Kitszel  * called from the VF to configure VF VSIs promiscuous mode
4765de6c855SPrzemek Kitszel  */
4775de6c855SPrzemek Kitszel static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
4785de6c855SPrzemek Kitszel {
4795de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
4805de6c855SPrzemek Kitszel 	bool rm_promisc, alluni = false, allmulti = false;
4815de6c855SPrzemek Kitszel 	struct virtchnl_promisc_info *info =
4825de6c855SPrzemek Kitszel 	    (struct virtchnl_promisc_info *)msg;
4835de6c855SPrzemek Kitszel 	struct ice_vsi_vlan_ops *vlan_ops;
4845de6c855SPrzemek Kitszel 	int mcast_err = 0, ucast_err = 0;
4855de6c855SPrzemek Kitszel 	struct ice_pf *pf = vf->pf;
4865de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
4875de6c855SPrzemek Kitszel 	u8 mcast_m, ucast_m;
4885de6c855SPrzemek Kitszel 	struct device *dev;
4895de6c855SPrzemek Kitszel 	int ret = 0;
4905de6c855SPrzemek Kitszel 
4915de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
4925de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
4935de6c855SPrzemek Kitszel 		goto error_param;
4945de6c855SPrzemek Kitszel 	}
4955de6c855SPrzemek Kitszel 
4965de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, info->vsi_id)) {
4975de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
4985de6c855SPrzemek Kitszel 		goto error_param;
4995de6c855SPrzemek Kitszel 	}
5005de6c855SPrzemek Kitszel 
5015de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
5025de6c855SPrzemek Kitszel 	if (!vsi) {
5035de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
5045de6c855SPrzemek Kitszel 		goto error_param;
5055de6c855SPrzemek Kitszel 	}
5065de6c855SPrzemek Kitszel 
5075de6c855SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
5085de6c855SPrzemek Kitszel 	if (!ice_is_vf_trusted(vf)) {
5095de6c855SPrzemek Kitszel 		dev_err(dev, "Unprivileged VF %d is attempting to configure promiscuous mode\n",
5105de6c855SPrzemek Kitszel 			vf->vf_id);
5115de6c855SPrzemek Kitszel 		/* Leave v_ret alone, lie to the VF on purpose. */
5125de6c855SPrzemek Kitszel 		goto error_param;
5135de6c855SPrzemek Kitszel 	}
5145de6c855SPrzemek Kitszel 
5155de6c855SPrzemek Kitszel 	if (info->flags & FLAG_VF_UNICAST_PROMISC)
5165de6c855SPrzemek Kitszel 		alluni = true;
5175de6c855SPrzemek Kitszel 
5185de6c855SPrzemek Kitszel 	if (info->flags & FLAG_VF_MULTICAST_PROMISC)
5195de6c855SPrzemek Kitszel 		allmulti = true;
5205de6c855SPrzemek Kitszel 
5215de6c855SPrzemek Kitszel 	rm_promisc = !allmulti && !alluni;
5225de6c855SPrzemek Kitszel 
5235de6c855SPrzemek Kitszel 	vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
5245de6c855SPrzemek Kitszel 	if (rm_promisc)
5255de6c855SPrzemek Kitszel 		ret = vlan_ops->ena_rx_filtering(vsi);
5265de6c855SPrzemek Kitszel 	else
5275de6c855SPrzemek Kitszel 		ret = vlan_ops->dis_rx_filtering(vsi);
5285de6c855SPrzemek Kitszel 	if (ret) {
5295de6c855SPrzemek Kitszel 		dev_err(dev, "Failed to configure VLAN pruning in promiscuous mode\n");
5305de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
5315de6c855SPrzemek Kitszel 		goto error_param;
5325de6c855SPrzemek Kitszel 	}
5335de6c855SPrzemek Kitszel 
5345de6c855SPrzemek Kitszel 	ice_vf_get_promisc_masks(vf, vsi, &ucast_m, &mcast_m);
5355de6c855SPrzemek Kitszel 
5365de6c855SPrzemek Kitszel 	if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
5375de6c855SPrzemek Kitszel 		if (alluni) {
5385de6c855SPrzemek Kitszel 			/* in this case we're turning on promiscuous mode */
5395de6c855SPrzemek Kitszel 			ret = ice_set_dflt_vsi(vsi);
5405de6c855SPrzemek Kitszel 		} else {
5415de6c855SPrzemek Kitszel 			/* in this case we're turning off promiscuous mode */
5425de6c855SPrzemek Kitszel 			if (ice_is_dflt_vsi_in_use(vsi->port_info))
5435de6c855SPrzemek Kitszel 				ret = ice_clear_dflt_vsi(vsi);
5445de6c855SPrzemek Kitszel 		}
5455de6c855SPrzemek Kitszel 
5465de6c855SPrzemek Kitszel 		/* in this case we're turning on/off only
5475de6c855SPrzemek Kitszel 		 * allmulticast
5485de6c855SPrzemek Kitszel 		 */
5495de6c855SPrzemek Kitszel 		if (allmulti)
5505de6c855SPrzemek Kitszel 			mcast_err = ice_vf_set_vsi_promisc(vf, vsi, mcast_m);
5515de6c855SPrzemek Kitszel 		else
5525de6c855SPrzemek Kitszel 			mcast_err = ice_vf_clear_vsi_promisc(vf, vsi, mcast_m);
5535de6c855SPrzemek Kitszel 
5545de6c855SPrzemek Kitszel 		if (ret) {
5555de6c855SPrzemek Kitszel 			dev_err(dev, "Turning on/off promiscuous mode for VF %d failed, error: %d\n",
5565de6c855SPrzemek Kitszel 				vf->vf_id, ret);
5575de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
5585de6c855SPrzemek Kitszel 			goto error_param;
5595de6c855SPrzemek Kitszel 		}
5605de6c855SPrzemek Kitszel 	} else {
5615de6c855SPrzemek Kitszel 		if (alluni)
5625de6c855SPrzemek Kitszel 			ucast_err = ice_vf_set_vsi_promisc(vf, vsi, ucast_m);
5635de6c855SPrzemek Kitszel 		else
5645de6c855SPrzemek Kitszel 			ucast_err = ice_vf_clear_vsi_promisc(vf, vsi, ucast_m);
5655de6c855SPrzemek Kitszel 
5665de6c855SPrzemek Kitszel 		if (allmulti)
5675de6c855SPrzemek Kitszel 			mcast_err = ice_vf_set_vsi_promisc(vf, vsi, mcast_m);
5685de6c855SPrzemek Kitszel 		else
5695de6c855SPrzemek Kitszel 			mcast_err = ice_vf_clear_vsi_promisc(vf, vsi, mcast_m);
5705de6c855SPrzemek Kitszel 
5715de6c855SPrzemek Kitszel 		if (ucast_err || mcast_err)
5725de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
5735de6c855SPrzemek Kitszel 	}
5745de6c855SPrzemek Kitszel 
5755de6c855SPrzemek Kitszel 	if (!mcast_err) {
5765de6c855SPrzemek Kitszel 		if (allmulti &&
5775de6c855SPrzemek Kitszel 		    !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
5785de6c855SPrzemek Kitszel 			dev_info(dev, "VF %u successfully set multicast promiscuous mode\n",
5795de6c855SPrzemek Kitszel 				 vf->vf_id);
5805de6c855SPrzemek Kitszel 		else if (!allmulti &&
5815de6c855SPrzemek Kitszel 			 test_and_clear_bit(ICE_VF_STATE_MC_PROMISC,
5825de6c855SPrzemek Kitszel 					    vf->vf_states))
5835de6c855SPrzemek Kitszel 			dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n",
5845de6c855SPrzemek Kitszel 				 vf->vf_id);
5855de6c855SPrzemek Kitszel 	} else {
5865de6c855SPrzemek Kitszel 		dev_err(dev, "Error while modifying multicast promiscuous mode for VF %u, error: %d\n",
5875de6c855SPrzemek Kitszel 			vf->vf_id, mcast_err);
5885de6c855SPrzemek Kitszel 	}
5895de6c855SPrzemek Kitszel 
5905de6c855SPrzemek Kitszel 	if (!ucast_err) {
5915de6c855SPrzemek Kitszel 		if (alluni &&
5925de6c855SPrzemek Kitszel 		    !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states))
5935de6c855SPrzemek Kitszel 			dev_info(dev, "VF %u successfully set unicast promiscuous mode\n",
5945de6c855SPrzemek Kitszel 				 vf->vf_id);
5955de6c855SPrzemek Kitszel 		else if (!alluni &&
5965de6c855SPrzemek Kitszel 			 test_and_clear_bit(ICE_VF_STATE_UC_PROMISC,
5975de6c855SPrzemek Kitszel 					    vf->vf_states))
5985de6c855SPrzemek Kitszel 			dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n",
5995de6c855SPrzemek Kitszel 				 vf->vf_id);
6005de6c855SPrzemek Kitszel 	} else {
6015de6c855SPrzemek Kitszel 		dev_err(dev, "Error while modifying unicast promiscuous mode for VF %u, error: %d\n",
6025de6c855SPrzemek Kitszel 			vf->vf_id, ucast_err);
6035de6c855SPrzemek Kitszel 	}
6045de6c855SPrzemek Kitszel 
6055de6c855SPrzemek Kitszel error_param:
6065de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
6075de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
6085de6c855SPrzemek Kitszel }
6095de6c855SPrzemek Kitszel 
6105de6c855SPrzemek Kitszel /**
6115de6c855SPrzemek Kitszel  * ice_vc_get_stats_msg
6125de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
6135de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
6145de6c855SPrzemek Kitszel  *
6155de6c855SPrzemek Kitszel  * called from the VF to get VSI stats
6165de6c855SPrzemek Kitszel  */
6175de6c855SPrzemek Kitszel static int ice_vc_get_stats_msg(struct ice_vf *vf, u8 *msg)
6185de6c855SPrzemek Kitszel {
6195de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
6205de6c855SPrzemek Kitszel 	struct virtchnl_queue_select *vqs =
6215de6c855SPrzemek Kitszel 		(struct virtchnl_queue_select *)msg;
6225de6c855SPrzemek Kitszel 	struct ice_eth_stats stats = { 0 };
6235de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
6245de6c855SPrzemek Kitszel 
6255de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
6265de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
6275de6c855SPrzemek Kitszel 		goto error_param;
6285de6c855SPrzemek Kitszel 	}
6295de6c855SPrzemek Kitszel 
6305de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, vqs->vsi_id)) {
6315de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
6325de6c855SPrzemek Kitszel 		goto error_param;
6335de6c855SPrzemek Kitszel 	}
6345de6c855SPrzemek Kitszel 
6355de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
6365de6c855SPrzemek Kitszel 	if (!vsi) {
6375de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
6385de6c855SPrzemek Kitszel 		goto error_param;
6395de6c855SPrzemek Kitszel 	}
6405de6c855SPrzemek Kitszel 
6415de6c855SPrzemek Kitszel 	ice_update_eth_stats(vsi);
6425de6c855SPrzemek Kitszel 
6435de6c855SPrzemek Kitszel 	stats = vsi->eth_stats;
6445de6c855SPrzemek Kitszel 
6455de6c855SPrzemek Kitszel error_param:
6465de6c855SPrzemek Kitszel 	/* send the response to the VF */
6475de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS, v_ret,
6485de6c855SPrzemek Kitszel 				     (u8 *)&stats, sizeof(stats));
6495de6c855SPrzemek Kitszel }
6505de6c855SPrzemek Kitszel 
6515de6c855SPrzemek Kitszel /**
6525de6c855SPrzemek Kitszel  * ice_can_vf_change_mac
6535de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
6545de6c855SPrzemek Kitszel  *
6555de6c855SPrzemek Kitszel  * Return true if the VF is allowed to change its MAC filters, false otherwise
6565de6c855SPrzemek Kitszel  */
6575de6c855SPrzemek Kitszel static bool ice_can_vf_change_mac(struct ice_vf *vf)
6585de6c855SPrzemek Kitszel {
6595de6c855SPrzemek Kitszel 	/* If the VF MAC address has been set administratively (via the
6605de6c855SPrzemek Kitszel 	 * ndo_set_vf_mac command), then deny permission to the VF to
6615de6c855SPrzemek Kitszel 	 * add/delete unicast MAC addresses, unless the VF is trusted
6625de6c855SPrzemek Kitszel 	 */
6635de6c855SPrzemek Kitszel 	if (vf->pf_set_mac && !ice_is_vf_trusted(vf))
6645de6c855SPrzemek Kitszel 		return false;
6655de6c855SPrzemek Kitszel 
6665de6c855SPrzemek Kitszel 	return true;
6675de6c855SPrzemek Kitszel }
6685de6c855SPrzemek Kitszel 
6695de6c855SPrzemek Kitszel /**
6705de6c855SPrzemek Kitszel  * ice_vc_ether_addr_type - get type of virtchnl_ether_addr
6715de6c855SPrzemek Kitszel  * @vc_ether_addr: used to extract the type
6725de6c855SPrzemek Kitszel  */
6735de6c855SPrzemek Kitszel static u8
6745de6c855SPrzemek Kitszel ice_vc_ether_addr_type(struct virtchnl_ether_addr *vc_ether_addr)
6755de6c855SPrzemek Kitszel {
6765de6c855SPrzemek Kitszel 	return (vc_ether_addr->type & VIRTCHNL_ETHER_ADDR_TYPE_MASK);
6775de6c855SPrzemek Kitszel }
6785de6c855SPrzemek Kitszel 
6795de6c855SPrzemek Kitszel /**
6805de6c855SPrzemek Kitszel  * ice_is_vc_addr_legacy - check if the MAC address is from an older VF
6815de6c855SPrzemek Kitszel  * @vc_ether_addr: VIRTCHNL structure that contains MAC and type
6825de6c855SPrzemek Kitszel  */
6835de6c855SPrzemek Kitszel static bool
6845de6c855SPrzemek Kitszel ice_is_vc_addr_legacy(struct virtchnl_ether_addr *vc_ether_addr)
6855de6c855SPrzemek Kitszel {
6865de6c855SPrzemek Kitszel 	u8 type = ice_vc_ether_addr_type(vc_ether_addr);
6875de6c855SPrzemek Kitszel 
6885de6c855SPrzemek Kitszel 	return (type == VIRTCHNL_ETHER_ADDR_LEGACY);
6895de6c855SPrzemek Kitszel }
6905de6c855SPrzemek Kitszel 
6915de6c855SPrzemek Kitszel /**
6925de6c855SPrzemek Kitszel  * ice_is_vc_addr_primary - check if the MAC address is the VF's primary MAC
6935de6c855SPrzemek Kitszel  * @vc_ether_addr: VIRTCHNL structure that contains MAC and type
6945de6c855SPrzemek Kitszel  *
6955de6c855SPrzemek Kitszel  * This function should only be called when the MAC address in
6965de6c855SPrzemek Kitszel  * virtchnl_ether_addr is a valid unicast MAC
6975de6c855SPrzemek Kitszel  */
6985de6c855SPrzemek Kitszel static bool
6995de6c855SPrzemek Kitszel ice_is_vc_addr_primary(struct virtchnl_ether_addr __maybe_unused *vc_ether_addr)
7005de6c855SPrzemek Kitszel {
7015de6c855SPrzemek Kitszel 	u8 type = ice_vc_ether_addr_type(vc_ether_addr);
7025de6c855SPrzemek Kitszel 
7035de6c855SPrzemek Kitszel 	return (type == VIRTCHNL_ETHER_ADDR_PRIMARY);
7045de6c855SPrzemek Kitszel }
7055de6c855SPrzemek Kitszel 
7065de6c855SPrzemek Kitszel /**
7075de6c855SPrzemek Kitszel  * ice_vfhw_mac_add - update the VF's cached hardware MAC if allowed
7085de6c855SPrzemek Kitszel  * @vf: VF to update
7095de6c855SPrzemek Kitszel  * @vc_ether_addr: structure from VIRTCHNL with MAC to add
7105de6c855SPrzemek Kitszel  */
7115de6c855SPrzemek Kitszel static void
7125de6c855SPrzemek Kitszel ice_vfhw_mac_add(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)
7135de6c855SPrzemek Kitszel {
7145de6c855SPrzemek Kitszel 	u8 *mac_addr = vc_ether_addr->addr;
7155de6c855SPrzemek Kitszel 
7165de6c855SPrzemek Kitszel 	if (!is_valid_ether_addr(mac_addr))
7175de6c855SPrzemek Kitszel 		return;
7185de6c855SPrzemek Kitszel 
7195de6c855SPrzemek Kitszel 	/* only allow legacy VF drivers to set the device and hardware MAC if it
7205de6c855SPrzemek Kitszel 	 * is zero and allow new VF drivers to set the hardware MAC if the type
7215de6c855SPrzemek Kitszel 	 * was correctly specified over VIRTCHNL
7225de6c855SPrzemek Kitszel 	 */
7235de6c855SPrzemek Kitszel 	if ((ice_is_vc_addr_legacy(vc_ether_addr) &&
7245de6c855SPrzemek Kitszel 	     is_zero_ether_addr(vf->hw_lan_addr)) ||
7255de6c855SPrzemek Kitszel 	    ice_is_vc_addr_primary(vc_ether_addr)) {
7265de6c855SPrzemek Kitszel 		ether_addr_copy(vf->dev_lan_addr, mac_addr);
7275de6c855SPrzemek Kitszel 		ether_addr_copy(vf->hw_lan_addr, mac_addr);
7285de6c855SPrzemek Kitszel 	}
7295de6c855SPrzemek Kitszel 
7305de6c855SPrzemek Kitszel 	/* hardware and device MACs are already set, but its possible that the
7315de6c855SPrzemek Kitszel 	 * VF driver sent the VIRTCHNL_OP_ADD_ETH_ADDR message before the
7325de6c855SPrzemek Kitszel 	 * VIRTCHNL_OP_DEL_ETH_ADDR when trying to update its MAC, so save it
7335de6c855SPrzemek Kitszel 	 * away for the legacy VF driver case as it will be updated in the
7345de6c855SPrzemek Kitszel 	 * delete flow for this case
7355de6c855SPrzemek Kitszel 	 */
7365de6c855SPrzemek Kitszel 	if (ice_is_vc_addr_legacy(vc_ether_addr)) {
7375de6c855SPrzemek Kitszel 		ether_addr_copy(vf->legacy_last_added_umac.addr,
7385de6c855SPrzemek Kitszel 				mac_addr);
7395de6c855SPrzemek Kitszel 		vf->legacy_last_added_umac.time_modified = jiffies;
7405de6c855SPrzemek Kitszel 	}
7415de6c855SPrzemek Kitszel }
7425de6c855SPrzemek Kitszel 
7435de6c855SPrzemek Kitszel /**
7445de6c855SPrzemek Kitszel  * ice_is_mc_lldp_eth_addr - check if the given MAC is a multicast LLDP address
7455de6c855SPrzemek Kitszel  * @mac: address to check
7465de6c855SPrzemek Kitszel  *
7475de6c855SPrzemek Kitszel  * Return: true if the address is one of the three possible LLDP multicast
7485de6c855SPrzemek Kitszel  *	   addresses, false otherwise.
7495de6c855SPrzemek Kitszel  */
7505de6c855SPrzemek Kitszel static bool ice_is_mc_lldp_eth_addr(const u8 *mac)
7515de6c855SPrzemek Kitszel {
7525de6c855SPrzemek Kitszel 	const u8 lldp_mac_base[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
7535de6c855SPrzemek Kitszel 
7545de6c855SPrzemek Kitszel 	if (memcmp(mac, lldp_mac_base, sizeof(lldp_mac_base)))
7555de6c855SPrzemek Kitszel 		return false;
7565de6c855SPrzemek Kitszel 
7575de6c855SPrzemek Kitszel 	return (mac[5] == 0x0e || mac[5] == 0x03 || mac[5] == 0x00);
7585de6c855SPrzemek Kitszel }
7595de6c855SPrzemek Kitszel 
7605de6c855SPrzemek Kitszel /**
7615de6c855SPrzemek Kitszel  * ice_vc_can_add_mac - check if the VF is allowed to add a given MAC
7625de6c855SPrzemek Kitszel  * @vf: a VF to add the address to
7635de6c855SPrzemek Kitszel  * @mac: address to check
7645de6c855SPrzemek Kitszel  *
7655de6c855SPrzemek Kitszel  * Return: true if the VF is allowed to add such MAC address, false otherwise.
7665de6c855SPrzemek Kitszel  */
7675de6c855SPrzemek Kitszel static bool ice_vc_can_add_mac(const struct ice_vf *vf, const u8 *mac)
7685de6c855SPrzemek Kitszel {
7695de6c855SPrzemek Kitszel 	struct device *dev = ice_pf_to_dev(vf->pf);
7705de6c855SPrzemek Kitszel 
7715de6c855SPrzemek Kitszel 	if (is_unicast_ether_addr(mac) &&
7725de6c855SPrzemek Kitszel 	    !ice_can_vf_change_mac((struct ice_vf *)vf)) {
7735de6c855SPrzemek Kitszel 		dev_err(dev,
7745de6c855SPrzemek Kitszel 			"VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
7755de6c855SPrzemek Kitszel 		return false;
7765de6c855SPrzemek Kitszel 	}
7775de6c855SPrzemek Kitszel 
7785de6c855SPrzemek Kitszel 	if (!vf->trusted && ice_is_mc_lldp_eth_addr(mac)) {
7795de6c855SPrzemek Kitszel 		dev_warn(dev,
7805de6c855SPrzemek Kitszel 			 "An untrusted VF %u is attempting to configure an LLDP multicast address\n",
7815de6c855SPrzemek Kitszel 			 vf->vf_id);
7825de6c855SPrzemek Kitszel 		return false;
7835de6c855SPrzemek Kitszel 	}
7845de6c855SPrzemek Kitszel 
7855de6c855SPrzemek Kitszel 	return true;
7865de6c855SPrzemek Kitszel }
7875de6c855SPrzemek Kitszel 
7885de6c855SPrzemek Kitszel /**
7895de6c855SPrzemek Kitszel  * ice_vc_add_mac_addr - attempt to add the MAC address passed in
7905de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
7915de6c855SPrzemek Kitszel  * @vsi: pointer to the VF's VSI
7925de6c855SPrzemek Kitszel  * @vc_ether_addr: VIRTCHNL MAC address structure used to add MAC
7935de6c855SPrzemek Kitszel  */
7945de6c855SPrzemek Kitszel static int
7955de6c855SPrzemek Kitszel ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
7965de6c855SPrzemek Kitszel 		    struct virtchnl_ether_addr *vc_ether_addr)
7975de6c855SPrzemek Kitszel {
7985de6c855SPrzemek Kitszel 	struct device *dev = ice_pf_to_dev(vf->pf);
7995de6c855SPrzemek Kitszel 	u8 *mac_addr = vc_ether_addr->addr;
8005de6c855SPrzemek Kitszel 	int ret;
8015de6c855SPrzemek Kitszel 
8025de6c855SPrzemek Kitszel 	/* device MAC already added */
8035de6c855SPrzemek Kitszel 	if (ether_addr_equal(mac_addr, vf->dev_lan_addr))
8045de6c855SPrzemek Kitszel 		return 0;
8055de6c855SPrzemek Kitszel 
8065de6c855SPrzemek Kitszel 	if (!ice_vc_can_add_mac(vf, mac_addr))
8075de6c855SPrzemek Kitszel 		return -EPERM;
8085de6c855SPrzemek Kitszel 
8095de6c855SPrzemek Kitszel 	ret = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI);
8105de6c855SPrzemek Kitszel 	if (ret == -EEXIST) {
8115de6c855SPrzemek Kitszel 		dev_dbg(dev, "MAC %pM already exists for VF %d\n", mac_addr,
8125de6c855SPrzemek Kitszel 			vf->vf_id);
8135de6c855SPrzemek Kitszel 		/* don't return since we might need to update
8145de6c855SPrzemek Kitszel 		 * the primary MAC in ice_vfhw_mac_add() below
8155de6c855SPrzemek Kitszel 		 */
8165de6c855SPrzemek Kitszel 	} else if (ret) {
8175de6c855SPrzemek Kitszel 		dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %d\n",
8185de6c855SPrzemek Kitszel 			mac_addr, vf->vf_id, ret);
8195de6c855SPrzemek Kitszel 		return ret;
8205de6c855SPrzemek Kitszel 	} else {
8215de6c855SPrzemek Kitszel 		vf->num_mac++;
8225de6c855SPrzemek Kitszel 		if (ice_is_mc_lldp_eth_addr(mac_addr))
8235de6c855SPrzemek Kitszel 			ice_vf_update_mac_lldp_num(vf, vsi, true);
8245de6c855SPrzemek Kitszel 	}
8255de6c855SPrzemek Kitszel 
8265de6c855SPrzemek Kitszel 	ice_vfhw_mac_add(vf, vc_ether_addr);
8275de6c855SPrzemek Kitszel 
8285de6c855SPrzemek Kitszel 	return ret;
8295de6c855SPrzemek Kitszel }
8305de6c855SPrzemek Kitszel 
8315de6c855SPrzemek Kitszel /**
8325de6c855SPrzemek Kitszel  * ice_is_legacy_umac_expired - check if last added legacy unicast MAC expired
8335de6c855SPrzemek Kitszel  * @last_added_umac: structure used to check expiration
8345de6c855SPrzemek Kitszel  */
8355de6c855SPrzemek Kitszel static bool ice_is_legacy_umac_expired(struct ice_time_mac *last_added_umac)
8365de6c855SPrzemek Kitszel {
8375de6c855SPrzemek Kitszel #define ICE_LEGACY_VF_MAC_CHANGE_EXPIRE_TIME	msecs_to_jiffies(3000)
8385de6c855SPrzemek Kitszel 	return time_is_before_jiffies(last_added_umac->time_modified +
8395de6c855SPrzemek Kitszel 				      ICE_LEGACY_VF_MAC_CHANGE_EXPIRE_TIME);
8405de6c855SPrzemek Kitszel }
8415de6c855SPrzemek Kitszel 
8425de6c855SPrzemek Kitszel /**
8435de6c855SPrzemek Kitszel  * ice_update_legacy_cached_mac - update cached hardware MAC for legacy VF
8445de6c855SPrzemek Kitszel  * @vf: VF to update
8455de6c855SPrzemek Kitszel  * @vc_ether_addr: structure from VIRTCHNL with MAC to check
8465de6c855SPrzemek Kitszel  *
8475de6c855SPrzemek Kitszel  * only update cached hardware MAC for legacy VF drivers on delete
8485de6c855SPrzemek Kitszel  * because we cannot guarantee order/type of MAC from the VF driver
8495de6c855SPrzemek Kitszel  */
8505de6c855SPrzemek Kitszel static void
8515de6c855SPrzemek Kitszel ice_update_legacy_cached_mac(struct ice_vf *vf,
8525de6c855SPrzemek Kitszel 			     struct virtchnl_ether_addr *vc_ether_addr)
8535de6c855SPrzemek Kitszel {
8545de6c855SPrzemek Kitszel 	if (!ice_is_vc_addr_legacy(vc_ether_addr) ||
8555de6c855SPrzemek Kitszel 	    ice_is_legacy_umac_expired(&vf->legacy_last_added_umac))
8565de6c855SPrzemek Kitszel 		return;
8575de6c855SPrzemek Kitszel 
8585de6c855SPrzemek Kitszel 	ether_addr_copy(vf->dev_lan_addr, vf->legacy_last_added_umac.addr);
8595de6c855SPrzemek Kitszel 	ether_addr_copy(vf->hw_lan_addr, vf->legacy_last_added_umac.addr);
8605de6c855SPrzemek Kitszel }
8615de6c855SPrzemek Kitszel 
8625de6c855SPrzemek Kitszel /**
8635de6c855SPrzemek Kitszel  * ice_vfhw_mac_del - update the VF's cached hardware MAC if allowed
8645de6c855SPrzemek Kitszel  * @vf: VF to update
8655de6c855SPrzemek Kitszel  * @vc_ether_addr: structure from VIRTCHNL with MAC to delete
8665de6c855SPrzemek Kitszel  */
8675de6c855SPrzemek Kitszel static void
8685de6c855SPrzemek Kitszel ice_vfhw_mac_del(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)
8695de6c855SPrzemek Kitszel {
8705de6c855SPrzemek Kitszel 	u8 *mac_addr = vc_ether_addr->addr;
8715de6c855SPrzemek Kitszel 
8725de6c855SPrzemek Kitszel 	if (!is_valid_ether_addr(mac_addr) ||
8735de6c855SPrzemek Kitszel 	    !ether_addr_equal(vf->dev_lan_addr, mac_addr))
8745de6c855SPrzemek Kitszel 		return;
8755de6c855SPrzemek Kitszel 
8765de6c855SPrzemek Kitszel 	/* allow the device MAC to be repopulated in the add flow and don't
8775de6c855SPrzemek Kitszel 	 * clear the hardware MAC (i.e. hw_lan_addr) here as that is meant
8785de6c855SPrzemek Kitszel 	 * to be persistent on VM reboot and across driver unload/load, which
8795de6c855SPrzemek Kitszel 	 * won't work if we clear the hardware MAC here
8805de6c855SPrzemek Kitszel 	 */
8815de6c855SPrzemek Kitszel 	eth_zero_addr(vf->dev_lan_addr);
8825de6c855SPrzemek Kitszel 
8835de6c855SPrzemek Kitszel 	ice_update_legacy_cached_mac(vf, vc_ether_addr);
8845de6c855SPrzemek Kitszel }
8855de6c855SPrzemek Kitszel 
8865de6c855SPrzemek Kitszel /**
8875de6c855SPrzemek Kitszel  * ice_vc_del_mac_addr - attempt to delete the MAC address passed in
8885de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
8895de6c855SPrzemek Kitszel  * @vsi: pointer to the VF's VSI
8905de6c855SPrzemek Kitszel  * @vc_ether_addr: VIRTCHNL MAC address structure used to delete MAC
8915de6c855SPrzemek Kitszel  */
8925de6c855SPrzemek Kitszel static int
8935de6c855SPrzemek Kitszel ice_vc_del_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
8945de6c855SPrzemek Kitszel 		    struct virtchnl_ether_addr *vc_ether_addr)
8955de6c855SPrzemek Kitszel {
8965de6c855SPrzemek Kitszel 	struct device *dev = ice_pf_to_dev(vf->pf);
8975de6c855SPrzemek Kitszel 	u8 *mac_addr = vc_ether_addr->addr;
8985de6c855SPrzemek Kitszel 	int status;
8995de6c855SPrzemek Kitszel 
9005de6c855SPrzemek Kitszel 	if (!ice_can_vf_change_mac(vf) &&
9015de6c855SPrzemek Kitszel 	    ether_addr_equal(vf->dev_lan_addr, mac_addr))
9025de6c855SPrzemek Kitszel 		return 0;
9035de6c855SPrzemek Kitszel 
9045de6c855SPrzemek Kitszel 	status = ice_fltr_remove_mac(vsi, mac_addr, ICE_FWD_TO_VSI);
9055de6c855SPrzemek Kitszel 	if (status == -ENOENT) {
9065de6c855SPrzemek Kitszel 		dev_err(dev, "MAC %pM does not exist for VF %d\n", mac_addr,
9075de6c855SPrzemek Kitszel 			vf->vf_id);
9085de6c855SPrzemek Kitszel 		return -ENOENT;
9095de6c855SPrzemek Kitszel 	} else if (status) {
9105de6c855SPrzemek Kitszel 		dev_err(dev, "Failed to delete MAC %pM for VF %d, error %d\n",
9115de6c855SPrzemek Kitszel 			mac_addr, vf->vf_id, status);
9125de6c855SPrzemek Kitszel 		return -EIO;
9135de6c855SPrzemek Kitszel 	}
9145de6c855SPrzemek Kitszel 
9155de6c855SPrzemek Kitszel 	ice_vfhw_mac_del(vf, vc_ether_addr);
9165de6c855SPrzemek Kitszel 
9175de6c855SPrzemek Kitszel 	vf->num_mac--;
9185de6c855SPrzemek Kitszel 	if (ice_is_mc_lldp_eth_addr(mac_addr))
9195de6c855SPrzemek Kitszel 		ice_vf_update_mac_lldp_num(vf, vsi, false);
9205de6c855SPrzemek Kitszel 
9215de6c855SPrzemek Kitszel 	return 0;
9225de6c855SPrzemek Kitszel }
9235de6c855SPrzemek Kitszel 
9245de6c855SPrzemek Kitszel /**
9255de6c855SPrzemek Kitszel  * ice_vc_handle_mac_addr_msg
9265de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
9275de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
9285de6c855SPrzemek Kitszel  * @set: true if MAC filters are being set, false otherwise
9295de6c855SPrzemek Kitszel  *
9305de6c855SPrzemek Kitszel  * add guest MAC address filter
9315de6c855SPrzemek Kitszel  */
9325de6c855SPrzemek Kitszel static int
9335de6c855SPrzemek Kitszel ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set)
9345de6c855SPrzemek Kitszel {
9355de6c855SPrzemek Kitszel 	int (*ice_vc_cfg_mac)
9365de6c855SPrzemek Kitszel 		(struct ice_vf *vf, struct ice_vsi *vsi,
9375de6c855SPrzemek Kitszel 		 struct virtchnl_ether_addr *virtchnl_ether_addr);
9385de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
9395de6c855SPrzemek Kitszel 	struct virtchnl_ether_addr_list *al =
9405de6c855SPrzemek Kitszel 	    (struct virtchnl_ether_addr_list *)msg;
9415de6c855SPrzemek Kitszel 	struct ice_pf *pf = vf->pf;
9425de6c855SPrzemek Kitszel 	enum virtchnl_ops vc_op;
9435de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
9445de6c855SPrzemek Kitszel 	int i;
9455de6c855SPrzemek Kitszel 
9465de6c855SPrzemek Kitszel 	if (set) {
9475de6c855SPrzemek Kitszel 		vc_op = VIRTCHNL_OP_ADD_ETH_ADDR;
9485de6c855SPrzemek Kitszel 		ice_vc_cfg_mac = ice_vc_add_mac_addr;
9495de6c855SPrzemek Kitszel 	} else {
9505de6c855SPrzemek Kitszel 		vc_op = VIRTCHNL_OP_DEL_ETH_ADDR;
9515de6c855SPrzemek Kitszel 		ice_vc_cfg_mac = ice_vc_del_mac_addr;
9525de6c855SPrzemek Kitszel 	}
9535de6c855SPrzemek Kitszel 
9545de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
9555de6c855SPrzemek Kitszel 	    !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
9565de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
9575de6c855SPrzemek Kitszel 		goto handle_mac_exit;
9585de6c855SPrzemek Kitszel 	}
9595de6c855SPrzemek Kitszel 
9605de6c855SPrzemek Kitszel 	/* If this VF is not privileged, then we can't add more than a
9615de6c855SPrzemek Kitszel 	 * limited number of addresses. Check to make sure that the
9625de6c855SPrzemek Kitszel 	 * additions do not push us over the limit.
9635de6c855SPrzemek Kitszel 	 */
9645de6c855SPrzemek Kitszel 	if (set && !ice_is_vf_trusted(vf) &&
9655de6c855SPrzemek Kitszel 	    (vf->num_mac + al->num_elements) > ICE_MAX_MACADDR_PER_VF) {
9665de6c855SPrzemek Kitszel 		dev_err(ice_pf_to_dev(pf), "Can't add more MAC addresses, because VF-%d is not trusted, switch the VF to trusted mode in order to add more functionalities\n",
9675de6c855SPrzemek Kitszel 			vf->vf_id);
9685de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
9695de6c855SPrzemek Kitszel 		goto handle_mac_exit;
9705de6c855SPrzemek Kitszel 	}
9715de6c855SPrzemek Kitszel 
9725de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
9735de6c855SPrzemek Kitszel 	if (!vsi) {
9745de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
9755de6c855SPrzemek Kitszel 		goto handle_mac_exit;
9765de6c855SPrzemek Kitszel 	}
9775de6c855SPrzemek Kitszel 
9785de6c855SPrzemek Kitszel 	for (i = 0; i < al->num_elements; i++) {
9795de6c855SPrzemek Kitszel 		u8 *mac_addr = al->list[i].addr;
9805de6c855SPrzemek Kitszel 		int result;
9815de6c855SPrzemek Kitszel 
9825de6c855SPrzemek Kitszel 		if (is_broadcast_ether_addr(mac_addr) ||
9835de6c855SPrzemek Kitszel 		    is_zero_ether_addr(mac_addr))
9845de6c855SPrzemek Kitszel 			continue;
9855de6c855SPrzemek Kitszel 
9865de6c855SPrzemek Kitszel 		result = ice_vc_cfg_mac(vf, vsi, &al->list[i]);
9875de6c855SPrzemek Kitszel 		if (result == -EEXIST || result == -ENOENT) {
9885de6c855SPrzemek Kitszel 			continue;
9895de6c855SPrzemek Kitszel 		} else if (result) {
9905de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
9915de6c855SPrzemek Kitszel 			goto handle_mac_exit;
9925de6c855SPrzemek Kitszel 		}
9935de6c855SPrzemek Kitszel 	}
9945de6c855SPrzemek Kitszel 
9955de6c855SPrzemek Kitszel handle_mac_exit:
9965de6c855SPrzemek Kitszel 	/* send the response to the VF */
9975de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, vc_op, v_ret, NULL, 0);
9985de6c855SPrzemek Kitszel }
9995de6c855SPrzemek Kitszel 
10005de6c855SPrzemek Kitszel /**
10015de6c855SPrzemek Kitszel  * ice_vc_add_mac_addr_msg
10025de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
10035de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
10045de6c855SPrzemek Kitszel  *
10055de6c855SPrzemek Kitszel  * add guest MAC address filter
10065de6c855SPrzemek Kitszel  */
10075de6c855SPrzemek Kitszel static int ice_vc_add_mac_addr_msg(struct ice_vf *vf, u8 *msg)
10085de6c855SPrzemek Kitszel {
10095de6c855SPrzemek Kitszel 	return ice_vc_handle_mac_addr_msg(vf, msg, true);
10105de6c855SPrzemek Kitszel }
10115de6c855SPrzemek Kitszel 
10125de6c855SPrzemek Kitszel /**
10135de6c855SPrzemek Kitszel  * ice_vc_del_mac_addr_msg
10145de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
10155de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
10165de6c855SPrzemek Kitszel  *
10175de6c855SPrzemek Kitszel  * remove guest MAC address filter
10185de6c855SPrzemek Kitszel  */
10195de6c855SPrzemek Kitszel static int ice_vc_del_mac_addr_msg(struct ice_vf *vf, u8 *msg)
10205de6c855SPrzemek Kitszel {
10215de6c855SPrzemek Kitszel 	return ice_vc_handle_mac_addr_msg(vf, msg, false);
10225de6c855SPrzemek Kitszel }
10235de6c855SPrzemek Kitszel 
10245de6c855SPrzemek Kitszel /**
10255de6c855SPrzemek Kitszel  * ice_vf_vlan_offload_ena - determine if capabilities support VLAN offloads
10265de6c855SPrzemek Kitszel  * @caps: VF driver negotiated capabilities
10275de6c855SPrzemek Kitszel  *
10285de6c855SPrzemek Kitszel  * Return true if VIRTCHNL_VF_OFFLOAD_VLAN capability is set, else return false
10295de6c855SPrzemek Kitszel  */
10305de6c855SPrzemek Kitszel static bool ice_vf_vlan_offload_ena(u32 caps)
10315de6c855SPrzemek Kitszel {
10325de6c855SPrzemek Kitszel 	return !!(caps & VIRTCHNL_VF_OFFLOAD_VLAN);
10335de6c855SPrzemek Kitszel }
10345de6c855SPrzemek Kitszel 
10355de6c855SPrzemek Kitszel /**
10365de6c855SPrzemek Kitszel  * ice_is_vlan_promisc_allowed - check if VLAN promiscuous config is allowed
10375de6c855SPrzemek Kitszel  * @vf: VF used to determine if VLAN promiscuous config is allowed
10385de6c855SPrzemek Kitszel  */
10395de6c855SPrzemek Kitszel bool ice_is_vlan_promisc_allowed(struct ice_vf *vf)
10405de6c855SPrzemek Kitszel {
10415de6c855SPrzemek Kitszel 	if ((test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
10425de6c855SPrzemek Kitszel 	     test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) &&
10435de6c855SPrzemek Kitszel 	    test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, vf->pf->flags))
10445de6c855SPrzemek Kitszel 		return true;
10455de6c855SPrzemek Kitszel 
10465de6c855SPrzemek Kitszel 	return false;
10475de6c855SPrzemek Kitszel }
10485de6c855SPrzemek Kitszel 
10495de6c855SPrzemek Kitszel /**
10505de6c855SPrzemek Kitszel  * ice_vf_ena_vlan_promisc - Enable Tx/Rx VLAN promiscuous for the VLAN
10515de6c855SPrzemek Kitszel  * @vf: VF to enable VLAN promisc on
10525de6c855SPrzemek Kitszel  * @vsi: VF's VSI used to enable VLAN promiscuous mode
10535de6c855SPrzemek Kitszel  * @vlan: VLAN used to enable VLAN promiscuous
10545de6c855SPrzemek Kitszel  *
10555de6c855SPrzemek Kitszel  * This function should only be called if VLAN promiscuous mode is allowed,
10565de6c855SPrzemek Kitszel  * which can be determined via ice_is_vlan_promisc_allowed().
10575de6c855SPrzemek Kitszel  */
10585de6c855SPrzemek Kitszel int ice_vf_ena_vlan_promisc(struct ice_vf *vf, struct ice_vsi *vsi,
10595de6c855SPrzemek Kitszel 			    struct ice_vlan *vlan)
10605de6c855SPrzemek Kitszel {
10615de6c855SPrzemek Kitszel 	u8 promisc_m = 0;
10625de6c855SPrzemek Kitszel 	int status;
10635de6c855SPrzemek Kitszel 
10645de6c855SPrzemek Kitszel 	if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states))
10655de6c855SPrzemek Kitszel 		promisc_m |= ICE_UCAST_VLAN_PROMISC_BITS;
10665de6c855SPrzemek Kitszel 	if (test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
10675de6c855SPrzemek Kitszel 		promisc_m |= ICE_MCAST_VLAN_PROMISC_BITS;
10685de6c855SPrzemek Kitszel 
10695de6c855SPrzemek Kitszel 	if (!promisc_m)
10705de6c855SPrzemek Kitszel 		return 0;
10715de6c855SPrzemek Kitszel 
10725de6c855SPrzemek Kitszel 	status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m,
10735de6c855SPrzemek Kitszel 					  vlan->vid);
10745de6c855SPrzemek Kitszel 	if (status && status != -EEXIST)
10755de6c855SPrzemek Kitszel 		return status;
10765de6c855SPrzemek Kitszel 
10775de6c855SPrzemek Kitszel 	return 0;
10785de6c855SPrzemek Kitszel }
10795de6c855SPrzemek Kitszel 
10805de6c855SPrzemek Kitszel /**
10815de6c855SPrzemek Kitszel  * ice_vf_dis_vlan_promisc - Disable Tx/Rx VLAN promiscuous for the VLAN
10825de6c855SPrzemek Kitszel  * @vsi: VF's VSI used to disable VLAN promiscuous mode for
10835de6c855SPrzemek Kitszel  * @vlan: VLAN used to disable VLAN promiscuous
10845de6c855SPrzemek Kitszel  *
10855de6c855SPrzemek Kitszel  * This function should only be called if VLAN promiscuous mode is allowed,
10865de6c855SPrzemek Kitszel  * which can be determined via ice_is_vlan_promisc_allowed().
10875de6c855SPrzemek Kitszel  */
10885de6c855SPrzemek Kitszel static int ice_vf_dis_vlan_promisc(struct ice_vsi *vsi, struct ice_vlan *vlan)
10895de6c855SPrzemek Kitszel {
10905de6c855SPrzemek Kitszel 	u8 promisc_m = ICE_UCAST_VLAN_PROMISC_BITS | ICE_MCAST_VLAN_PROMISC_BITS;
10915de6c855SPrzemek Kitszel 	int status;
10925de6c855SPrzemek Kitszel 
10935de6c855SPrzemek Kitszel 	status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m,
10945de6c855SPrzemek Kitszel 					    vlan->vid);
10955de6c855SPrzemek Kitszel 	if (status && status != -ENOENT)
10965de6c855SPrzemek Kitszel 		return status;
10975de6c855SPrzemek Kitszel 
10985de6c855SPrzemek Kitszel 	return 0;
10995de6c855SPrzemek Kitszel }
11005de6c855SPrzemek Kitszel 
11015de6c855SPrzemek Kitszel /**
11025de6c855SPrzemek Kitszel  * ice_vf_has_max_vlans - check if VF already has the max allowed VLAN filters
11035de6c855SPrzemek Kitszel  * @vf: VF to check against
11045de6c855SPrzemek Kitszel  * @vsi: VF's VSI
11055de6c855SPrzemek Kitszel  *
11065de6c855SPrzemek Kitszel  * If the VF is trusted then the VF is allowed to add as many VLANs as it
11075de6c855SPrzemek Kitszel  * wants to, so return false.
11085de6c855SPrzemek Kitszel  *
11095de6c855SPrzemek Kitszel  * When the VF is untrusted compare the number of non-zero VLANs + 1 to the max
11105de6c855SPrzemek Kitszel  * allowed VLANs for an untrusted VF. Return the result of this comparison.
11115de6c855SPrzemek Kitszel  */
11125de6c855SPrzemek Kitszel static bool ice_vf_has_max_vlans(struct ice_vf *vf, struct ice_vsi *vsi)
11135de6c855SPrzemek Kitszel {
11145de6c855SPrzemek Kitszel 	if (ice_is_vf_trusted(vf))
11155de6c855SPrzemek Kitszel 		return false;
11165de6c855SPrzemek Kitszel 
11175de6c855SPrzemek Kitszel #define ICE_VF_ADDED_VLAN_ZERO_FLTRS	1
11185de6c855SPrzemek Kitszel 	return ((ice_vsi_num_non_zero_vlans(vsi) +
11195de6c855SPrzemek Kitszel 		ICE_VF_ADDED_VLAN_ZERO_FLTRS) >= ICE_MAX_VLAN_PER_VF);
11205de6c855SPrzemek Kitszel }
11215de6c855SPrzemek Kitszel 
11225de6c855SPrzemek Kitszel /**
11235de6c855SPrzemek Kitszel  * ice_vc_process_vlan_msg
11245de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
11255de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
11265de6c855SPrzemek Kitszel  * @add_v: Add VLAN if true, otherwise delete VLAN
11275de6c855SPrzemek Kitszel  *
11285de6c855SPrzemek Kitszel  * Process virtchnl op to add or remove programmed guest VLAN ID
11295de6c855SPrzemek Kitszel  */
11305de6c855SPrzemek Kitszel static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
11315de6c855SPrzemek Kitszel {
11325de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
11335de6c855SPrzemek Kitszel 	struct virtchnl_vlan_filter_list *vfl =
11345de6c855SPrzemek Kitszel 	    (struct virtchnl_vlan_filter_list *)msg;
11355de6c855SPrzemek Kitszel 	struct ice_pf *pf = vf->pf;
11365de6c855SPrzemek Kitszel 	bool vlan_promisc = false;
11375de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
11385de6c855SPrzemek Kitszel 	struct device *dev;
11395de6c855SPrzemek Kitszel 	int status = 0;
11405de6c855SPrzemek Kitszel 	int i;
11415de6c855SPrzemek Kitszel 
11425de6c855SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
11435de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
11445de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
11455de6c855SPrzemek Kitszel 		goto error_param;
11465de6c855SPrzemek Kitszel 	}
11475de6c855SPrzemek Kitszel 
11485de6c855SPrzemek Kitszel 	if (!ice_vf_vlan_offload_ena(vf->driver_caps)) {
11495de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
11505de6c855SPrzemek Kitszel 		goto error_param;
11515de6c855SPrzemek Kitszel 	}
11525de6c855SPrzemek Kitszel 
11535de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, vfl->vsi_id)) {
11545de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
11555de6c855SPrzemek Kitszel 		goto error_param;
11565de6c855SPrzemek Kitszel 	}
11575de6c855SPrzemek Kitszel 
11585de6c855SPrzemek Kitszel 	for (i = 0; i < vfl->num_elements; i++) {
11595de6c855SPrzemek Kitszel 		if (vfl->vlan_id[i] >= VLAN_N_VID) {
11605de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
11615de6c855SPrzemek Kitszel 			dev_err(dev, "invalid VF VLAN id %d\n",
11625de6c855SPrzemek Kitszel 				vfl->vlan_id[i]);
11635de6c855SPrzemek Kitszel 			goto error_param;
11645de6c855SPrzemek Kitszel 		}
11655de6c855SPrzemek Kitszel 	}
11665de6c855SPrzemek Kitszel 
11675de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
11685de6c855SPrzemek Kitszel 	if (!vsi) {
11695de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
11705de6c855SPrzemek Kitszel 		goto error_param;
11715de6c855SPrzemek Kitszel 	}
11725de6c855SPrzemek Kitszel 
11735de6c855SPrzemek Kitszel 	if (add_v && ice_vf_has_max_vlans(vf, vsi)) {
11745de6c855SPrzemek Kitszel 		dev_info(dev, "VF-%d is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n",
11755de6c855SPrzemek Kitszel 			 vf->vf_id);
11765de6c855SPrzemek Kitszel 		/* There is no need to let VF know about being not trusted,
11775de6c855SPrzemek Kitszel 		 * so we can just return success message here
11785de6c855SPrzemek Kitszel 		 */
11795de6c855SPrzemek Kitszel 		goto error_param;
11805de6c855SPrzemek Kitszel 	}
11815de6c855SPrzemek Kitszel 
11825de6c855SPrzemek Kitszel 	/* in DVM a VF can add/delete inner VLAN filters when
11835de6c855SPrzemek Kitszel 	 * VIRTCHNL_VF_OFFLOAD_VLAN is negotiated, so only reject in SVM
11845de6c855SPrzemek Kitszel 	 */
11855de6c855SPrzemek Kitszel 	if (ice_vf_is_port_vlan_ena(vf) && !ice_is_dvm_ena(&pf->hw)) {
11865de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
11875de6c855SPrzemek Kitszel 		goto error_param;
11885de6c855SPrzemek Kitszel 	}
11895de6c855SPrzemek Kitszel 
11905de6c855SPrzemek Kitszel 	/* in DVM VLAN promiscuous is based on the outer VLAN, which would be
11915de6c855SPrzemek Kitszel 	 * the port VLAN if VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, so only
11925de6c855SPrzemek Kitszel 	 * allow vlan_promisc = true in SVM and if no port VLAN is configured
11935de6c855SPrzemek Kitszel 	 */
11945de6c855SPrzemek Kitszel 	vlan_promisc = ice_is_vlan_promisc_allowed(vf) &&
11955de6c855SPrzemek Kitszel 		!ice_is_dvm_ena(&pf->hw) &&
11965de6c855SPrzemek Kitszel 		!ice_vf_is_port_vlan_ena(vf);
11975de6c855SPrzemek Kitszel 
11985de6c855SPrzemek Kitszel 	if (add_v) {
11995de6c855SPrzemek Kitszel 		for (i = 0; i < vfl->num_elements; i++) {
12005de6c855SPrzemek Kitszel 			u16 vid = vfl->vlan_id[i];
12015de6c855SPrzemek Kitszel 			struct ice_vlan vlan;
12025de6c855SPrzemek Kitszel 
12035de6c855SPrzemek Kitszel 			if (ice_vf_has_max_vlans(vf, vsi)) {
12045de6c855SPrzemek Kitszel 				dev_info(dev, "VF-%d is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n",
12055de6c855SPrzemek Kitszel 					 vf->vf_id);
12065de6c855SPrzemek Kitszel 				/* There is no need to let VF know about being
12075de6c855SPrzemek Kitszel 				 * not trusted, so we can just return success
12085de6c855SPrzemek Kitszel 				 * message here as well.
12095de6c855SPrzemek Kitszel 				 */
12105de6c855SPrzemek Kitszel 				goto error_param;
12115de6c855SPrzemek Kitszel 			}
12125de6c855SPrzemek Kitszel 
12135de6c855SPrzemek Kitszel 			/* we add VLAN 0 by default for each VF so we can enable
12145de6c855SPrzemek Kitszel 			 * Tx VLAN anti-spoof without triggering MDD events so
12155de6c855SPrzemek Kitszel 			 * we don't need to add it again here
12165de6c855SPrzemek Kitszel 			 */
12175de6c855SPrzemek Kitszel 			if (!vid)
12185de6c855SPrzemek Kitszel 				continue;
12195de6c855SPrzemek Kitszel 
12205de6c855SPrzemek Kitszel 			vlan = ICE_VLAN(ETH_P_8021Q, vid, 0);
12215de6c855SPrzemek Kitszel 			status = vsi->inner_vlan_ops.add_vlan(vsi, &vlan);
12225de6c855SPrzemek Kitszel 			if (status) {
12235de6c855SPrzemek Kitszel 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
12245de6c855SPrzemek Kitszel 				goto error_param;
12255de6c855SPrzemek Kitszel 			}
12265de6c855SPrzemek Kitszel 
12275de6c855SPrzemek Kitszel 			/* Enable VLAN filtering on first non-zero VLAN */
12285de6c855SPrzemek Kitszel 			if (!vlan_promisc && vid && !ice_is_dvm_ena(&pf->hw)) {
12295de6c855SPrzemek Kitszel 				if (vf->spoofchk) {
12305de6c855SPrzemek Kitszel 					status = vsi->inner_vlan_ops.ena_tx_filtering(vsi);
12315de6c855SPrzemek Kitszel 					if (status) {
12325de6c855SPrzemek Kitszel 						v_ret = VIRTCHNL_STATUS_ERR_PARAM;
12335de6c855SPrzemek Kitszel 						dev_err(dev, "Enable VLAN anti-spoofing on VLAN ID: %d failed error-%d\n",
12345de6c855SPrzemek Kitszel 							vid, status);
12355de6c855SPrzemek Kitszel 						goto error_param;
12365de6c855SPrzemek Kitszel 					}
12375de6c855SPrzemek Kitszel 				}
12385de6c855SPrzemek Kitszel 				if (vsi->inner_vlan_ops.ena_rx_filtering(vsi)) {
12395de6c855SPrzemek Kitszel 					v_ret = VIRTCHNL_STATUS_ERR_PARAM;
12405de6c855SPrzemek Kitszel 					dev_err(dev, "Enable VLAN pruning on VLAN ID: %d failed error-%d\n",
12415de6c855SPrzemek Kitszel 						vid, status);
12425de6c855SPrzemek Kitszel 					goto error_param;
12435de6c855SPrzemek Kitszel 				}
12445de6c855SPrzemek Kitszel 			} else if (vlan_promisc) {
12455de6c855SPrzemek Kitszel 				status = ice_vf_ena_vlan_promisc(vf, vsi, &vlan);
12465de6c855SPrzemek Kitszel 				if (status) {
12475de6c855SPrzemek Kitszel 					v_ret = VIRTCHNL_STATUS_ERR_PARAM;
12485de6c855SPrzemek Kitszel 					dev_err(dev, "Enable Unicast/multicast promiscuous mode on VLAN ID:%d failed error-%d\n",
12495de6c855SPrzemek Kitszel 						vid, status);
12505de6c855SPrzemek Kitszel 				}
12515de6c855SPrzemek Kitszel 			}
12525de6c855SPrzemek Kitszel 		}
12535de6c855SPrzemek Kitszel 	} else {
12545de6c855SPrzemek Kitszel 		/* In case of non_trusted VF, number of VLAN elements passed
12555de6c855SPrzemek Kitszel 		 * to PF for removal might be greater than number of VLANs
12565de6c855SPrzemek Kitszel 		 * filter programmed for that VF - So, use actual number of
12575de6c855SPrzemek Kitszel 		 * VLANS added earlier with add VLAN opcode. In order to avoid
12585de6c855SPrzemek Kitszel 		 * removing VLAN that doesn't exist, which result to sending
12595de6c855SPrzemek Kitszel 		 * erroneous failed message back to the VF
12605de6c855SPrzemek Kitszel 		 */
12615de6c855SPrzemek Kitszel 		int num_vf_vlan;
12625de6c855SPrzemek Kitszel 
12635de6c855SPrzemek Kitszel 		num_vf_vlan = vsi->num_vlan;
12645de6c855SPrzemek Kitszel 		for (i = 0; i < vfl->num_elements && i < num_vf_vlan; i++) {
12655de6c855SPrzemek Kitszel 			u16 vid = vfl->vlan_id[i];
12665de6c855SPrzemek Kitszel 			struct ice_vlan vlan;
12675de6c855SPrzemek Kitszel 
12685de6c855SPrzemek Kitszel 			/* we add VLAN 0 by default for each VF so we can enable
12695de6c855SPrzemek Kitszel 			 * Tx VLAN anti-spoof without triggering MDD events so
12705de6c855SPrzemek Kitszel 			 * we don't want a VIRTCHNL request to remove it
12715de6c855SPrzemek Kitszel 			 */
12725de6c855SPrzemek Kitszel 			if (!vid)
12735de6c855SPrzemek Kitszel 				continue;
12745de6c855SPrzemek Kitszel 
12755de6c855SPrzemek Kitszel 			vlan = ICE_VLAN(ETH_P_8021Q, vid, 0);
12765de6c855SPrzemek Kitszel 			status = vsi->inner_vlan_ops.del_vlan(vsi, &vlan);
12775de6c855SPrzemek Kitszel 			if (status) {
12785de6c855SPrzemek Kitszel 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
12795de6c855SPrzemek Kitszel 				goto error_param;
12805de6c855SPrzemek Kitszel 			}
12815de6c855SPrzemek Kitszel 
12825de6c855SPrzemek Kitszel 			/* Disable VLAN filtering when only VLAN 0 is left */
12835de6c855SPrzemek Kitszel 			if (!ice_vsi_has_non_zero_vlans(vsi)) {
12845de6c855SPrzemek Kitszel 				vsi->inner_vlan_ops.dis_tx_filtering(vsi);
12855de6c855SPrzemek Kitszel 				vsi->inner_vlan_ops.dis_rx_filtering(vsi);
12865de6c855SPrzemek Kitszel 			}
12875de6c855SPrzemek Kitszel 
12885de6c855SPrzemek Kitszel 			if (vlan_promisc)
12895de6c855SPrzemek Kitszel 				ice_vf_dis_vlan_promisc(vsi, &vlan);
12905de6c855SPrzemek Kitszel 		}
12915de6c855SPrzemek Kitszel 	}
12925de6c855SPrzemek Kitszel 
12935de6c855SPrzemek Kitszel error_param:
12945de6c855SPrzemek Kitszel 	/* send the response to the VF */
12955de6c855SPrzemek Kitszel 	if (add_v)
12965de6c855SPrzemek Kitszel 		return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN, v_ret,
12975de6c855SPrzemek Kitszel 					     NULL, 0);
12985de6c855SPrzemek Kitszel 	else
12995de6c855SPrzemek Kitszel 		return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN, v_ret,
13005de6c855SPrzemek Kitszel 					     NULL, 0);
13015de6c855SPrzemek Kitszel }
13025de6c855SPrzemek Kitszel 
13035de6c855SPrzemek Kitszel /**
13045de6c855SPrzemek Kitszel  * ice_vc_add_vlan_msg
13055de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
13065de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
13075de6c855SPrzemek Kitszel  *
13085de6c855SPrzemek Kitszel  * Add and program guest VLAN ID
13095de6c855SPrzemek Kitszel  */
13105de6c855SPrzemek Kitszel static int ice_vc_add_vlan_msg(struct ice_vf *vf, u8 *msg)
13115de6c855SPrzemek Kitszel {
13125de6c855SPrzemek Kitszel 	return ice_vc_process_vlan_msg(vf, msg, true);
13135de6c855SPrzemek Kitszel }
13145de6c855SPrzemek Kitszel 
13155de6c855SPrzemek Kitszel /**
13165de6c855SPrzemek Kitszel  * ice_vc_remove_vlan_msg
13175de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
13185de6c855SPrzemek Kitszel  * @msg: pointer to the msg buffer
13195de6c855SPrzemek Kitszel  *
13205de6c855SPrzemek Kitszel  * remove programmed guest VLAN ID
13215de6c855SPrzemek Kitszel  */
13225de6c855SPrzemek Kitszel static int ice_vc_remove_vlan_msg(struct ice_vf *vf, u8 *msg)
13235de6c855SPrzemek Kitszel {
13245de6c855SPrzemek Kitszel 	return ice_vc_process_vlan_msg(vf, msg, false);
13255de6c855SPrzemek Kitszel }
13265de6c855SPrzemek Kitszel 
13275de6c855SPrzemek Kitszel /**
13285de6c855SPrzemek Kitszel  * ice_vsi_is_rxq_crc_strip_dis - check if Rx queue CRC strip is disabled or not
13295de6c855SPrzemek Kitszel  * @vsi: pointer to the VF VSI info
13305de6c855SPrzemek Kitszel  */
13315de6c855SPrzemek Kitszel static bool ice_vsi_is_rxq_crc_strip_dis(struct ice_vsi *vsi)
13325de6c855SPrzemek Kitszel {
13335de6c855SPrzemek Kitszel 	unsigned int i;
13345de6c855SPrzemek Kitszel 
13355de6c855SPrzemek Kitszel 	ice_for_each_alloc_rxq(vsi, i)
13365de6c855SPrzemek Kitszel 		if (vsi->rx_rings[i]->flags & ICE_RX_FLAGS_CRC_STRIP_DIS)
13375de6c855SPrzemek Kitszel 			return true;
13385de6c855SPrzemek Kitszel 
13395de6c855SPrzemek Kitszel 	return false;
13405de6c855SPrzemek Kitszel }
13415de6c855SPrzemek Kitszel 
13425de6c855SPrzemek Kitszel /**
13435de6c855SPrzemek Kitszel  * ice_vc_ena_vlan_stripping
13445de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
13455de6c855SPrzemek Kitszel  *
13465de6c855SPrzemek Kitszel  * Enable VLAN header stripping for a given VF
13475de6c855SPrzemek Kitszel  */
13485de6c855SPrzemek Kitszel static int ice_vc_ena_vlan_stripping(struct ice_vf *vf)
13495de6c855SPrzemek Kitszel {
13505de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
13515de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
13525de6c855SPrzemek Kitszel 
13535de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
13545de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13555de6c855SPrzemek Kitszel 		goto error_param;
13565de6c855SPrzemek Kitszel 	}
13575de6c855SPrzemek Kitszel 
13585de6c855SPrzemek Kitszel 	if (!ice_vf_vlan_offload_ena(vf->driver_caps)) {
13595de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13605de6c855SPrzemek Kitszel 		goto error_param;
13615de6c855SPrzemek Kitszel 	}
13625de6c855SPrzemek Kitszel 
13635de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
13645de6c855SPrzemek Kitszel 	if (!vsi) {
13655de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13665de6c855SPrzemek Kitszel 		goto error_param;
13675de6c855SPrzemek Kitszel 	}
13685de6c855SPrzemek Kitszel 
13695de6c855SPrzemek Kitszel 	if (vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q))
13705de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13715de6c855SPrzemek Kitszel 	else
13725de6c855SPrzemek Kitszel 		vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA;
13735de6c855SPrzemek Kitszel 
13745de6c855SPrzemek Kitszel error_param:
13755de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
13765de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
13775de6c855SPrzemek Kitszel }
13785de6c855SPrzemek Kitszel 
13795de6c855SPrzemek Kitszel /**
13805de6c855SPrzemek Kitszel  * ice_vc_dis_vlan_stripping
13815de6c855SPrzemek Kitszel  * @vf: pointer to the VF info
13825de6c855SPrzemek Kitszel  *
13835de6c855SPrzemek Kitszel  * Disable VLAN header stripping for a given VF
13845de6c855SPrzemek Kitszel  */
13855de6c855SPrzemek Kitszel static int ice_vc_dis_vlan_stripping(struct ice_vf *vf)
13865de6c855SPrzemek Kitszel {
13875de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
13885de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
13895de6c855SPrzemek Kitszel 
13905de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
13915de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13925de6c855SPrzemek Kitszel 		goto error_param;
13935de6c855SPrzemek Kitszel 	}
13945de6c855SPrzemek Kitszel 
13955de6c855SPrzemek Kitszel 	if (!ice_vf_vlan_offload_ena(vf->driver_caps)) {
13965de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13975de6c855SPrzemek Kitszel 		goto error_param;
13985de6c855SPrzemek Kitszel 	}
13995de6c855SPrzemek Kitszel 
14005de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
14015de6c855SPrzemek Kitszel 	if (!vsi) {
14025de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
14035de6c855SPrzemek Kitszel 		goto error_param;
14045de6c855SPrzemek Kitszel 	}
14055de6c855SPrzemek Kitszel 
14065de6c855SPrzemek Kitszel 	if (vsi->inner_vlan_ops.dis_stripping(vsi))
14075de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
14085de6c855SPrzemek Kitszel 	else
14095de6c855SPrzemek Kitszel 		vf->vlan_strip_ena &= ~ICE_INNER_VLAN_STRIP_ENA;
14105de6c855SPrzemek Kitszel 
14115de6c855SPrzemek Kitszel error_param:
14125de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
14135de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
14145de6c855SPrzemek Kitszel }
14155de6c855SPrzemek Kitszel 
14165de6c855SPrzemek Kitszel /**
14175de6c855SPrzemek Kitszel  * ice_vc_query_rxdid - query RXDID supported by DDP package
14185de6c855SPrzemek Kitszel  * @vf: pointer to VF info
14195de6c855SPrzemek Kitszel  *
14205de6c855SPrzemek Kitszel  * Called from VF to query a bitmap of supported flexible
14215de6c855SPrzemek Kitszel  * descriptor RXDIDs of a DDP package.
14225de6c855SPrzemek Kitszel  */
14235de6c855SPrzemek Kitszel static int ice_vc_query_rxdid(struct ice_vf *vf)
14245de6c855SPrzemek Kitszel {
14255de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
14265de6c855SPrzemek Kitszel 	struct ice_pf *pf = vf->pf;
14275de6c855SPrzemek Kitszel 	u64 rxdid;
14285de6c855SPrzemek Kitszel 
14295de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
14305de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
14315de6c855SPrzemek Kitszel 		goto err;
14325de6c855SPrzemek Kitszel 	}
14335de6c855SPrzemek Kitszel 
14345de6c855SPrzemek Kitszel 	if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)) {
14355de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
14365de6c855SPrzemek Kitszel 		goto err;
14375de6c855SPrzemek Kitszel 	}
14385de6c855SPrzemek Kitszel 
14395de6c855SPrzemek Kitszel 	rxdid = pf->supported_rxdids;
14405de6c855SPrzemek Kitszel 
14415de6c855SPrzemek Kitszel err:
14425de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS,
14435de6c855SPrzemek Kitszel 				     v_ret, (u8 *)&rxdid, sizeof(rxdid));
14445de6c855SPrzemek Kitszel }
14455de6c855SPrzemek Kitszel 
14465de6c855SPrzemek Kitszel /**
14475de6c855SPrzemek Kitszel  * ice_vf_init_vlan_stripping - enable/disable VLAN stripping on initialization
14485de6c855SPrzemek Kitszel  * @vf: VF to enable/disable VLAN stripping for on initialization
14495de6c855SPrzemek Kitszel  *
14505de6c855SPrzemek Kitszel  * Set the default for VLAN stripping based on whether a port VLAN is configured
14515de6c855SPrzemek Kitszel  * and the current VLAN mode of the device.
14525de6c855SPrzemek Kitszel  */
14535de6c855SPrzemek Kitszel static int ice_vf_init_vlan_stripping(struct ice_vf *vf)
14545de6c855SPrzemek Kitszel {
14555de6c855SPrzemek Kitszel 	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
14565de6c855SPrzemek Kitszel 
14575de6c855SPrzemek Kitszel 	vf->vlan_strip_ena = 0;
14585de6c855SPrzemek Kitszel 
14595de6c855SPrzemek Kitszel 	if (!vsi)
14605de6c855SPrzemek Kitszel 		return -EINVAL;
14615de6c855SPrzemek Kitszel 
14625de6c855SPrzemek Kitszel 	/* don't modify stripping if port VLAN is configured in SVM since the
14635de6c855SPrzemek Kitszel 	 * port VLAN is based on the inner/single VLAN in SVM
14645de6c855SPrzemek Kitszel 	 */
14655de6c855SPrzemek Kitszel 	if (ice_vf_is_port_vlan_ena(vf) && !ice_is_dvm_ena(&vsi->back->hw))
14665de6c855SPrzemek Kitszel 		return 0;
14675de6c855SPrzemek Kitszel 
14685de6c855SPrzemek Kitszel 	if (ice_vf_vlan_offload_ena(vf->driver_caps)) {
14695de6c855SPrzemek Kitszel 		int err;
14705de6c855SPrzemek Kitszel 
14715de6c855SPrzemek Kitszel 		err = vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q);
14725de6c855SPrzemek Kitszel 		if (!err)
14735de6c855SPrzemek Kitszel 			vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA;
14745de6c855SPrzemek Kitszel 		return err;
14755de6c855SPrzemek Kitszel 	}
14765de6c855SPrzemek Kitszel 
14775de6c855SPrzemek Kitszel 	return vsi->inner_vlan_ops.dis_stripping(vsi);
14785de6c855SPrzemek Kitszel }
14795de6c855SPrzemek Kitszel 
14805de6c855SPrzemek Kitszel static u16 ice_vc_get_max_vlan_fltrs(struct ice_vf *vf)
14815de6c855SPrzemek Kitszel {
14825de6c855SPrzemek Kitszel 	if (vf->trusted)
14835de6c855SPrzemek Kitszel 		return VLAN_N_VID;
14845de6c855SPrzemek Kitszel 	else
14855de6c855SPrzemek Kitszel 		return ICE_MAX_VLAN_PER_VF;
14865de6c855SPrzemek Kitszel }
14875de6c855SPrzemek Kitszel 
14885de6c855SPrzemek Kitszel /**
14895de6c855SPrzemek Kitszel  * ice_vf_outer_vlan_not_allowed - check if outer VLAN can be used
14905de6c855SPrzemek Kitszel  * @vf: VF that being checked for
14915de6c855SPrzemek Kitszel  *
14925de6c855SPrzemek Kitszel  * When the device is in double VLAN mode, check whether or not the outer VLAN
14935de6c855SPrzemek Kitszel  * is allowed.
14945de6c855SPrzemek Kitszel  */
14955de6c855SPrzemek Kitszel static bool ice_vf_outer_vlan_not_allowed(struct ice_vf *vf)
14965de6c855SPrzemek Kitszel {
14975de6c855SPrzemek Kitszel 	if (ice_vf_is_port_vlan_ena(vf))
14985de6c855SPrzemek Kitszel 		return true;
14995de6c855SPrzemek Kitszel 
15005de6c855SPrzemek Kitszel 	return false;
15015de6c855SPrzemek Kitszel }
15025de6c855SPrzemek Kitszel 
15035de6c855SPrzemek Kitszel /**
15045de6c855SPrzemek Kitszel  * ice_vc_set_dvm_caps - set VLAN capabilities when the device is in DVM
15055de6c855SPrzemek Kitszel  * @vf: VF that capabilities are being set for
15065de6c855SPrzemek Kitszel  * @caps: VLAN capabilities to populate
15075de6c855SPrzemek Kitszel  *
15085de6c855SPrzemek Kitszel  * Determine VLAN capabilities support based on whether a port VLAN is
15095de6c855SPrzemek Kitszel  * configured. If a port VLAN is configured then the VF should use the inner
15105de6c855SPrzemek Kitszel  * filtering/offload capabilities since the port VLAN is using the outer VLAN
15115de6c855SPrzemek Kitszel  * capabilies.
15125de6c855SPrzemek Kitszel  */
15135de6c855SPrzemek Kitszel static void
15145de6c855SPrzemek Kitszel ice_vc_set_dvm_caps(struct ice_vf *vf, struct virtchnl_vlan_caps *caps)
15155de6c855SPrzemek Kitszel {
15165de6c855SPrzemek Kitszel 	struct virtchnl_vlan_supported_caps *supported_caps;
15175de6c855SPrzemek Kitszel 
15185de6c855SPrzemek Kitszel 	if (ice_vf_outer_vlan_not_allowed(vf)) {
15195de6c855SPrzemek Kitszel 		/* until support for inner VLAN filtering is added when a port
15205de6c855SPrzemek Kitszel 		 * VLAN is configured, only support software offloaded inner
15215de6c855SPrzemek Kitszel 		 * VLANs when a port VLAN is confgured in DVM
15225de6c855SPrzemek Kitszel 		 */
15235de6c855SPrzemek Kitszel 		supported_caps = &caps->filtering.filtering_support;
15245de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
15255de6c855SPrzemek Kitszel 
15265de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.stripping_support;
15275de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
15285de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TOGGLE |
15295de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
15305de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
15315de6c855SPrzemek Kitszel 
15325de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.insertion_support;
15335de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
15345de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TOGGLE |
15355de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
15365de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
15375de6c855SPrzemek Kitszel 
15385de6c855SPrzemek Kitszel 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
15395de6c855SPrzemek Kitszel 		caps->offloads.ethertype_match =
15405de6c855SPrzemek Kitszel 			VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION;
15415de6c855SPrzemek Kitszel 	} else {
15425de6c855SPrzemek Kitszel 		supported_caps = &caps->filtering.filtering_support;
15435de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
15445de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_ETHERTYPE_8100 |
15455de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_88A8 |
15465de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_9100 |
15475de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_AND;
15485de6c855SPrzemek Kitszel 		caps->filtering.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100 |
15495de6c855SPrzemek Kitszel 						 VIRTCHNL_VLAN_ETHERTYPE_88A8 |
15505de6c855SPrzemek Kitszel 						 VIRTCHNL_VLAN_ETHERTYPE_9100;
15515de6c855SPrzemek Kitszel 
15525de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.stripping_support;
15535de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_TOGGLE |
15545de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
15555de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
15565de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_TOGGLE |
15575de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
15585de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_88A8 |
15595de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_9100 |
15605de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_XOR |
15615de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2;
15625de6c855SPrzemek Kitszel 
15635de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.insertion_support;
15645de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_TOGGLE |
15655de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
15665de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
15675de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_TOGGLE |
15685de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
15695de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_88A8 |
15705de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_9100 |
15715de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_ETHERTYPE_XOR |
15725de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2;
15735de6c855SPrzemek Kitszel 
15745de6c855SPrzemek Kitszel 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
15755de6c855SPrzemek Kitszel 
15765de6c855SPrzemek Kitszel 		caps->offloads.ethertype_match =
15775de6c855SPrzemek Kitszel 			VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION;
15785de6c855SPrzemek Kitszel 	}
15795de6c855SPrzemek Kitszel 
15805de6c855SPrzemek Kitszel 	caps->filtering.max_filters = ice_vc_get_max_vlan_fltrs(vf);
15815de6c855SPrzemek Kitszel }
15825de6c855SPrzemek Kitszel 
15835de6c855SPrzemek Kitszel /**
15845de6c855SPrzemek Kitszel  * ice_vc_set_svm_caps - set VLAN capabilities when the device is in SVM
15855de6c855SPrzemek Kitszel  * @vf: VF that capabilities are being set for
15865de6c855SPrzemek Kitszel  * @caps: VLAN capabilities to populate
15875de6c855SPrzemek Kitszel  *
15885de6c855SPrzemek Kitszel  * Determine VLAN capabilities support based on whether a port VLAN is
15895de6c855SPrzemek Kitszel  * configured. If a port VLAN is configured then the VF does not have any VLAN
15905de6c855SPrzemek Kitszel  * filtering or offload capabilities since the port VLAN is using the inner VLAN
15915de6c855SPrzemek Kitszel  * capabilities in single VLAN mode (SVM). Otherwise allow the VF to use inner
15925de6c855SPrzemek Kitszel  * VLAN fitlering and offload capabilities.
15935de6c855SPrzemek Kitszel  */
15945de6c855SPrzemek Kitszel static void
15955de6c855SPrzemek Kitszel ice_vc_set_svm_caps(struct ice_vf *vf, struct virtchnl_vlan_caps *caps)
15965de6c855SPrzemek Kitszel {
15975de6c855SPrzemek Kitszel 	struct virtchnl_vlan_supported_caps *supported_caps;
15985de6c855SPrzemek Kitszel 
15995de6c855SPrzemek Kitszel 	if (ice_vf_is_port_vlan_ena(vf)) {
16005de6c855SPrzemek Kitszel 		supported_caps = &caps->filtering.filtering_support;
16015de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
16025de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
16035de6c855SPrzemek Kitszel 
16045de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.stripping_support;
16055de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
16065de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
16075de6c855SPrzemek Kitszel 
16085de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.insertion_support;
16095de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
16105de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
16115de6c855SPrzemek Kitszel 
16125de6c855SPrzemek Kitszel 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_UNSUPPORTED;
16135de6c855SPrzemek Kitszel 		caps->offloads.ethertype_match = VIRTCHNL_VLAN_UNSUPPORTED;
16145de6c855SPrzemek Kitszel 		caps->filtering.max_filters = 0;
16155de6c855SPrzemek Kitszel 	} else {
16165de6c855SPrzemek Kitszel 		supported_caps = &caps->filtering.filtering_support;
16175de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100;
16185de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
16195de6c855SPrzemek Kitszel 		caps->filtering.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
16205de6c855SPrzemek Kitszel 
16215de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.stripping_support;
16225de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
16235de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TOGGLE |
16245de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
16255de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
16265de6c855SPrzemek Kitszel 
16275de6c855SPrzemek Kitszel 		supported_caps = &caps->offloads.insertion_support;
16285de6c855SPrzemek Kitszel 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
16295de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TOGGLE |
16305de6c855SPrzemek Kitszel 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
16315de6c855SPrzemek Kitszel 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
16325de6c855SPrzemek Kitszel 
16335de6c855SPrzemek Kitszel 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
16345de6c855SPrzemek Kitszel 		caps->offloads.ethertype_match =
16355de6c855SPrzemek Kitszel 			VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION;
16365de6c855SPrzemek Kitszel 		caps->filtering.max_filters = ice_vc_get_max_vlan_fltrs(vf);
16375de6c855SPrzemek Kitszel 	}
16385de6c855SPrzemek Kitszel }
16395de6c855SPrzemek Kitszel 
16405de6c855SPrzemek Kitszel /**
16415de6c855SPrzemek Kitszel  * ice_vc_get_offload_vlan_v2_caps - determine VF's VLAN capabilities
16425de6c855SPrzemek Kitszel  * @vf: VF to determine VLAN capabilities for
16435de6c855SPrzemek Kitszel  *
16445de6c855SPrzemek Kitszel  * This will only be called if the VF and PF successfully negotiated
16455de6c855SPrzemek Kitszel  * VIRTCHNL_VF_OFFLOAD_VLAN_V2.
16465de6c855SPrzemek Kitszel  *
16475de6c855SPrzemek Kitszel  * Set VLAN capabilities based on the current VLAN mode and whether a port VLAN
16485de6c855SPrzemek Kitszel  * is configured or not.
16495de6c855SPrzemek Kitszel  */
16505de6c855SPrzemek Kitszel static int ice_vc_get_offload_vlan_v2_caps(struct ice_vf *vf)
16515de6c855SPrzemek Kitszel {
16525de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
16535de6c855SPrzemek Kitszel 	struct virtchnl_vlan_caps *caps = NULL;
16545de6c855SPrzemek Kitszel 	int err, len = 0;
16555de6c855SPrzemek Kitszel 
16565de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
16575de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
16585de6c855SPrzemek Kitszel 		goto out;
16595de6c855SPrzemek Kitszel 	}
16605de6c855SPrzemek Kitszel 
16615de6c855SPrzemek Kitszel 	caps = kzalloc(sizeof(*caps), GFP_KERNEL);
16625de6c855SPrzemek Kitszel 	if (!caps) {
16635de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
16645de6c855SPrzemek Kitszel 		goto out;
16655de6c855SPrzemek Kitszel 	}
16665de6c855SPrzemek Kitszel 	len = sizeof(*caps);
16675de6c855SPrzemek Kitszel 
16685de6c855SPrzemek Kitszel 	if (ice_is_dvm_ena(&vf->pf->hw))
16695de6c855SPrzemek Kitszel 		ice_vc_set_dvm_caps(vf, caps);
16705de6c855SPrzemek Kitszel 	else
16715de6c855SPrzemek Kitszel 		ice_vc_set_svm_caps(vf, caps);
16725de6c855SPrzemek Kitszel 
16735de6c855SPrzemek Kitszel 	/* store negotiated caps to prevent invalid VF messages */
16745de6c855SPrzemek Kitszel 	memcpy(&vf->vlan_v2_caps, caps, sizeof(*caps));
16755de6c855SPrzemek Kitszel 
16765de6c855SPrzemek Kitszel out:
16775de6c855SPrzemek Kitszel 	err = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS,
16785de6c855SPrzemek Kitszel 				    v_ret, (u8 *)caps, len);
16795de6c855SPrzemek Kitszel 	kfree(caps);
16805de6c855SPrzemek Kitszel 	return err;
16815de6c855SPrzemek Kitszel }
16825de6c855SPrzemek Kitszel 
16835de6c855SPrzemek Kitszel /**
16845de6c855SPrzemek Kitszel  * ice_vc_validate_vlan_tpid - validate VLAN TPID
16855de6c855SPrzemek Kitszel  * @filtering_caps: negotiated/supported VLAN filtering capabilities
16865de6c855SPrzemek Kitszel  * @tpid: VLAN TPID used for validation
16875de6c855SPrzemek Kitszel  *
16885de6c855SPrzemek Kitszel  * Convert the VLAN TPID to a VIRTCHNL_VLAN_ETHERTYPE_* and then compare against
16895de6c855SPrzemek Kitszel  * the negotiated/supported filtering caps to see if the VLAN TPID is valid.
16905de6c855SPrzemek Kitszel  */
16915de6c855SPrzemek Kitszel static bool ice_vc_validate_vlan_tpid(u16 filtering_caps, u16 tpid)
16925de6c855SPrzemek Kitszel {
16935de6c855SPrzemek Kitszel 	enum virtchnl_vlan_support vlan_ethertype = VIRTCHNL_VLAN_UNSUPPORTED;
16945de6c855SPrzemek Kitszel 
16955de6c855SPrzemek Kitszel 	switch (tpid) {
16965de6c855SPrzemek Kitszel 	case ETH_P_8021Q:
16975de6c855SPrzemek Kitszel 		vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
16985de6c855SPrzemek Kitszel 		break;
16995de6c855SPrzemek Kitszel 	case ETH_P_8021AD:
17005de6c855SPrzemek Kitszel 		vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_88A8;
17015de6c855SPrzemek Kitszel 		break;
17025de6c855SPrzemek Kitszel 	case ETH_P_QINQ1:
17035de6c855SPrzemek Kitszel 		vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_9100;
17045de6c855SPrzemek Kitszel 		break;
17055de6c855SPrzemek Kitszel 	}
17065de6c855SPrzemek Kitszel 
17075de6c855SPrzemek Kitszel 	if (!(filtering_caps & vlan_ethertype))
17085de6c855SPrzemek Kitszel 		return false;
17095de6c855SPrzemek Kitszel 
17105de6c855SPrzemek Kitszel 	return true;
17115de6c855SPrzemek Kitszel }
17125de6c855SPrzemek Kitszel 
17135de6c855SPrzemek Kitszel /**
17145de6c855SPrzemek Kitszel  * ice_vc_is_valid_vlan - validate the virtchnl_vlan
17155de6c855SPrzemek Kitszel  * @vc_vlan: virtchnl_vlan to validate
17165de6c855SPrzemek Kitszel  *
17175de6c855SPrzemek Kitszel  * If the VLAN TCI and VLAN TPID are 0, then this filter is invalid, so return
17185de6c855SPrzemek Kitszel  * false. Otherwise return true.
17195de6c855SPrzemek Kitszel  */
17205de6c855SPrzemek Kitszel static bool ice_vc_is_valid_vlan(struct virtchnl_vlan *vc_vlan)
17215de6c855SPrzemek Kitszel {
17225de6c855SPrzemek Kitszel 	if (!vc_vlan->tci || !vc_vlan->tpid)
17235de6c855SPrzemek Kitszel 		return false;
17245de6c855SPrzemek Kitszel 
17255de6c855SPrzemek Kitszel 	return true;
17265de6c855SPrzemek Kitszel }
17275de6c855SPrzemek Kitszel 
17285de6c855SPrzemek Kitszel /**
17295de6c855SPrzemek Kitszel  * ice_vc_validate_vlan_filter_list - validate the filter list from the VF
17305de6c855SPrzemek Kitszel  * @vfc: negotiated/supported VLAN filtering capabilities
17315de6c855SPrzemek Kitszel  * @vfl: VLAN filter list from VF to validate
17325de6c855SPrzemek Kitszel  *
17335de6c855SPrzemek Kitszel  * Validate all of the filters in the VLAN filter list from the VF. If any of
17345de6c855SPrzemek Kitszel  * the checks fail then return false. Otherwise return true.
17355de6c855SPrzemek Kitszel  */
17365de6c855SPrzemek Kitszel static bool
17375de6c855SPrzemek Kitszel ice_vc_validate_vlan_filter_list(struct virtchnl_vlan_filtering_caps *vfc,
17385de6c855SPrzemek Kitszel 				 struct virtchnl_vlan_filter_list_v2 *vfl)
17395de6c855SPrzemek Kitszel {
17405de6c855SPrzemek Kitszel 	u16 i;
17415de6c855SPrzemek Kitszel 
17425de6c855SPrzemek Kitszel 	if (!vfl->num_elements)
17435de6c855SPrzemek Kitszel 		return false;
17445de6c855SPrzemek Kitszel 
17455de6c855SPrzemek Kitszel 	for (i = 0; i < vfl->num_elements; i++) {
17465de6c855SPrzemek Kitszel 		struct virtchnl_vlan_supported_caps *filtering_support =
17475de6c855SPrzemek Kitszel 			&vfc->filtering_support;
17485de6c855SPrzemek Kitszel 		struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i];
17495de6c855SPrzemek Kitszel 		struct virtchnl_vlan *outer = &vlan_fltr->outer;
17505de6c855SPrzemek Kitszel 		struct virtchnl_vlan *inner = &vlan_fltr->inner;
17515de6c855SPrzemek Kitszel 
17525de6c855SPrzemek Kitszel 		if ((ice_vc_is_valid_vlan(outer) &&
17535de6c855SPrzemek Kitszel 		     filtering_support->outer == VIRTCHNL_VLAN_UNSUPPORTED) ||
17545de6c855SPrzemek Kitszel 		    (ice_vc_is_valid_vlan(inner) &&
17555de6c855SPrzemek Kitszel 		     filtering_support->inner == VIRTCHNL_VLAN_UNSUPPORTED))
17565de6c855SPrzemek Kitszel 			return false;
17575de6c855SPrzemek Kitszel 
17585de6c855SPrzemek Kitszel 		if ((outer->tci_mask &&
17595de6c855SPrzemek Kitszel 		     !(filtering_support->outer & VIRTCHNL_VLAN_FILTER_MASK)) ||
17605de6c855SPrzemek Kitszel 		    (inner->tci_mask &&
17615de6c855SPrzemek Kitszel 		     !(filtering_support->inner & VIRTCHNL_VLAN_FILTER_MASK)))
17625de6c855SPrzemek Kitszel 			return false;
17635de6c855SPrzemek Kitszel 
17645de6c855SPrzemek Kitszel 		if (((outer->tci & VLAN_PRIO_MASK) &&
17655de6c855SPrzemek Kitszel 		     !(filtering_support->outer & VIRTCHNL_VLAN_PRIO)) ||
17665de6c855SPrzemek Kitszel 		    ((inner->tci & VLAN_PRIO_MASK) &&
17675de6c855SPrzemek Kitszel 		     !(filtering_support->inner & VIRTCHNL_VLAN_PRIO)))
17685de6c855SPrzemek Kitszel 			return false;
17695de6c855SPrzemek Kitszel 
17705de6c855SPrzemek Kitszel 		if ((ice_vc_is_valid_vlan(outer) &&
17715de6c855SPrzemek Kitszel 		     !ice_vc_validate_vlan_tpid(filtering_support->outer,
17725de6c855SPrzemek Kitszel 						outer->tpid)) ||
17735de6c855SPrzemek Kitszel 		    (ice_vc_is_valid_vlan(inner) &&
17745de6c855SPrzemek Kitszel 		     !ice_vc_validate_vlan_tpid(filtering_support->inner,
17755de6c855SPrzemek Kitszel 						inner->tpid)))
17765de6c855SPrzemek Kitszel 			return false;
17775de6c855SPrzemek Kitszel 	}
17785de6c855SPrzemek Kitszel 
17795de6c855SPrzemek Kitszel 	return true;
17805de6c855SPrzemek Kitszel }
17815de6c855SPrzemek Kitszel 
17825de6c855SPrzemek Kitszel /**
17835de6c855SPrzemek Kitszel  * ice_vc_to_vlan - transform from struct virtchnl_vlan to struct ice_vlan
17845de6c855SPrzemek Kitszel  * @vc_vlan: struct virtchnl_vlan to transform
17855de6c855SPrzemek Kitszel  */
17865de6c855SPrzemek Kitszel static struct ice_vlan ice_vc_to_vlan(struct virtchnl_vlan *vc_vlan)
17875de6c855SPrzemek Kitszel {
17885de6c855SPrzemek Kitszel 	struct ice_vlan vlan = { 0 };
17895de6c855SPrzemek Kitszel 
17905de6c855SPrzemek Kitszel 	vlan.prio = FIELD_GET(VLAN_PRIO_MASK, vc_vlan->tci);
17915de6c855SPrzemek Kitszel 	vlan.vid = vc_vlan->tci & VLAN_VID_MASK;
17925de6c855SPrzemek Kitszel 	vlan.tpid = vc_vlan->tpid;
17935de6c855SPrzemek Kitszel 
17945de6c855SPrzemek Kitszel 	return vlan;
17955de6c855SPrzemek Kitszel }
17965de6c855SPrzemek Kitszel 
17975de6c855SPrzemek Kitszel /**
17985de6c855SPrzemek Kitszel  * ice_vc_vlan_action - action to perform on the virthcnl_vlan
17995de6c855SPrzemek Kitszel  * @vsi: VF's VSI used to perform the action
18005de6c855SPrzemek Kitszel  * @vlan_action: function to perform the action with (i.e. add/del)
18015de6c855SPrzemek Kitszel  * @vlan: VLAN filter to perform the action with
18025de6c855SPrzemek Kitszel  */
18035de6c855SPrzemek Kitszel static int
18045de6c855SPrzemek Kitszel ice_vc_vlan_action(struct ice_vsi *vsi,
18055de6c855SPrzemek Kitszel 		   int (*vlan_action)(struct ice_vsi *, struct ice_vlan *),
18065de6c855SPrzemek Kitszel 		   struct ice_vlan *vlan)
18075de6c855SPrzemek Kitszel {
18085de6c855SPrzemek Kitszel 	int err;
18095de6c855SPrzemek Kitszel 
18105de6c855SPrzemek Kitszel 	err = vlan_action(vsi, vlan);
18115de6c855SPrzemek Kitszel 	if (err)
18125de6c855SPrzemek Kitszel 		return err;
18135de6c855SPrzemek Kitszel 
18145de6c855SPrzemek Kitszel 	return 0;
18155de6c855SPrzemek Kitszel }
18165de6c855SPrzemek Kitszel 
18175de6c855SPrzemek Kitszel /**
18185de6c855SPrzemek Kitszel  * ice_vc_del_vlans - delete VLAN(s) from the virtchnl filter list
18195de6c855SPrzemek Kitszel  * @vf: VF used to delete the VLAN(s)
18205de6c855SPrzemek Kitszel  * @vsi: VF's VSI used to delete the VLAN(s)
18215de6c855SPrzemek Kitszel  * @vfl: virthchnl filter list used to delete the filters
18225de6c855SPrzemek Kitszel  */
18235de6c855SPrzemek Kitszel static int
18245de6c855SPrzemek Kitszel ice_vc_del_vlans(struct ice_vf *vf, struct ice_vsi *vsi,
18255de6c855SPrzemek Kitszel 		 struct virtchnl_vlan_filter_list_v2 *vfl)
18265de6c855SPrzemek Kitszel {
18275de6c855SPrzemek Kitszel 	bool vlan_promisc = ice_is_vlan_promisc_allowed(vf);
18285de6c855SPrzemek Kitszel 	int err;
18295de6c855SPrzemek Kitszel 	u16 i;
18305de6c855SPrzemek Kitszel 
18315de6c855SPrzemek Kitszel 	for (i = 0; i < vfl->num_elements; i++) {
18325de6c855SPrzemek Kitszel 		struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i];
18335de6c855SPrzemek Kitszel 		struct virtchnl_vlan *vc_vlan;
18345de6c855SPrzemek Kitszel 
18355de6c855SPrzemek Kitszel 		vc_vlan = &vlan_fltr->outer;
18365de6c855SPrzemek Kitszel 		if (ice_vc_is_valid_vlan(vc_vlan)) {
18375de6c855SPrzemek Kitszel 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
18385de6c855SPrzemek Kitszel 
18395de6c855SPrzemek Kitszel 			err = ice_vc_vlan_action(vsi,
18405de6c855SPrzemek Kitszel 						 vsi->outer_vlan_ops.del_vlan,
18415de6c855SPrzemek Kitszel 						 &vlan);
18425de6c855SPrzemek Kitszel 			if (err)
18435de6c855SPrzemek Kitszel 				return err;
18445de6c855SPrzemek Kitszel 
18455de6c855SPrzemek Kitszel 			if (vlan_promisc)
18465de6c855SPrzemek Kitszel 				ice_vf_dis_vlan_promisc(vsi, &vlan);
18475de6c855SPrzemek Kitszel 
18485de6c855SPrzemek Kitszel 			/* Disable VLAN filtering when only VLAN 0 is left */
18495de6c855SPrzemek Kitszel 			if (!ice_vsi_has_non_zero_vlans(vsi) && ice_is_dvm_ena(&vsi->back->hw)) {
18505de6c855SPrzemek Kitszel 				err = vsi->outer_vlan_ops.dis_tx_filtering(vsi);
18515de6c855SPrzemek Kitszel 				if (err)
18525de6c855SPrzemek Kitszel 					return err;
18535de6c855SPrzemek Kitszel 			}
18545de6c855SPrzemek Kitszel 		}
18555de6c855SPrzemek Kitszel 
18565de6c855SPrzemek Kitszel 		vc_vlan = &vlan_fltr->inner;
18575de6c855SPrzemek Kitszel 		if (ice_vc_is_valid_vlan(vc_vlan)) {
18585de6c855SPrzemek Kitszel 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
18595de6c855SPrzemek Kitszel 
18605de6c855SPrzemek Kitszel 			err = ice_vc_vlan_action(vsi,
18615de6c855SPrzemek Kitszel 						 vsi->inner_vlan_ops.del_vlan,
18625de6c855SPrzemek Kitszel 						 &vlan);
18635de6c855SPrzemek Kitszel 			if (err)
18645de6c855SPrzemek Kitszel 				return err;
18655de6c855SPrzemek Kitszel 
18665de6c855SPrzemek Kitszel 			/* no support for VLAN promiscuous on inner VLAN unless
18675de6c855SPrzemek Kitszel 			 * we are in Single VLAN Mode (SVM)
18685de6c855SPrzemek Kitszel 			 */
18695de6c855SPrzemek Kitszel 			if (!ice_is_dvm_ena(&vsi->back->hw)) {
18705de6c855SPrzemek Kitszel 				if (vlan_promisc)
18715de6c855SPrzemek Kitszel 					ice_vf_dis_vlan_promisc(vsi, &vlan);
18725de6c855SPrzemek Kitszel 
18735de6c855SPrzemek Kitszel 				/* Disable VLAN filtering when only VLAN 0 is left */
18745de6c855SPrzemek Kitszel 				if (!ice_vsi_has_non_zero_vlans(vsi)) {
18755de6c855SPrzemek Kitszel 					err = vsi->inner_vlan_ops.dis_tx_filtering(vsi);
18765de6c855SPrzemek Kitszel 					if (err)
18775de6c855SPrzemek Kitszel 						return err;
18785de6c855SPrzemek Kitszel 				}
18795de6c855SPrzemek Kitszel 			}
18805de6c855SPrzemek Kitszel 		}
18815de6c855SPrzemek Kitszel 	}
18825de6c855SPrzemek Kitszel 
18835de6c855SPrzemek Kitszel 	return 0;
18845de6c855SPrzemek Kitszel }
18855de6c855SPrzemek Kitszel 
18865de6c855SPrzemek Kitszel /**
18875de6c855SPrzemek Kitszel  * ice_vc_remove_vlan_v2_msg - virtchnl handler for VIRTCHNL_OP_DEL_VLAN_V2
18885de6c855SPrzemek Kitszel  * @vf: VF the message was received from
18895de6c855SPrzemek Kitszel  * @msg: message received from the VF
18905de6c855SPrzemek Kitszel  */
18915de6c855SPrzemek Kitszel static int ice_vc_remove_vlan_v2_msg(struct ice_vf *vf, u8 *msg)
18925de6c855SPrzemek Kitszel {
18935de6c855SPrzemek Kitszel 	struct virtchnl_vlan_filter_list_v2 *vfl =
18945de6c855SPrzemek Kitszel 		(struct virtchnl_vlan_filter_list_v2 *)msg;
18955de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
18965de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
18975de6c855SPrzemek Kitszel 
18985de6c855SPrzemek Kitszel 	if (!ice_vc_validate_vlan_filter_list(&vf->vlan_v2_caps.filtering,
18995de6c855SPrzemek Kitszel 					      vfl)) {
19005de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
19015de6c855SPrzemek Kitszel 		goto out;
19025de6c855SPrzemek Kitszel 	}
19035de6c855SPrzemek Kitszel 
19045de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, vfl->vport_id)) {
19055de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
19065de6c855SPrzemek Kitszel 		goto out;
19075de6c855SPrzemek Kitszel 	}
19085de6c855SPrzemek Kitszel 
19095de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
19105de6c855SPrzemek Kitszel 	if (!vsi) {
19115de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
19125de6c855SPrzemek Kitszel 		goto out;
19135de6c855SPrzemek Kitszel 	}
19145de6c855SPrzemek Kitszel 
19155de6c855SPrzemek Kitszel 	if (ice_vc_del_vlans(vf, vsi, vfl))
19165de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
19175de6c855SPrzemek Kitszel 
19185de6c855SPrzemek Kitszel out:
19195de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN_V2, v_ret, NULL,
19205de6c855SPrzemek Kitszel 				     0);
19215de6c855SPrzemek Kitszel }
19225de6c855SPrzemek Kitszel 
19235de6c855SPrzemek Kitszel /**
19245de6c855SPrzemek Kitszel  * ice_vc_add_vlans - add VLAN(s) from the virtchnl filter list
19255de6c855SPrzemek Kitszel  * @vf: VF used to add the VLAN(s)
19265de6c855SPrzemek Kitszel  * @vsi: VF's VSI used to add the VLAN(s)
19275de6c855SPrzemek Kitszel  * @vfl: virthchnl filter list used to add the filters
19285de6c855SPrzemek Kitszel  */
19295de6c855SPrzemek Kitszel static int
19305de6c855SPrzemek Kitszel ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi,
19315de6c855SPrzemek Kitszel 		 struct virtchnl_vlan_filter_list_v2 *vfl)
19325de6c855SPrzemek Kitszel {
19335de6c855SPrzemek Kitszel 	bool vlan_promisc = ice_is_vlan_promisc_allowed(vf);
19345de6c855SPrzemek Kitszel 	int err;
19355de6c855SPrzemek Kitszel 	u16 i;
19365de6c855SPrzemek Kitszel 
19375de6c855SPrzemek Kitszel 	for (i = 0; i < vfl->num_elements; i++) {
19385de6c855SPrzemek Kitszel 		struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i];
19395de6c855SPrzemek Kitszel 		struct virtchnl_vlan *vc_vlan;
19405de6c855SPrzemek Kitszel 
19415de6c855SPrzemek Kitszel 		vc_vlan = &vlan_fltr->outer;
19425de6c855SPrzemek Kitszel 		if (ice_vc_is_valid_vlan(vc_vlan)) {
19435de6c855SPrzemek Kitszel 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
19445de6c855SPrzemek Kitszel 
19455de6c855SPrzemek Kitszel 			err = ice_vc_vlan_action(vsi,
19465de6c855SPrzemek Kitszel 						 vsi->outer_vlan_ops.add_vlan,
19475de6c855SPrzemek Kitszel 						 &vlan);
19485de6c855SPrzemek Kitszel 			if (err)
19495de6c855SPrzemek Kitszel 				return err;
19505de6c855SPrzemek Kitszel 
19515de6c855SPrzemek Kitszel 			if (vlan_promisc) {
19525de6c855SPrzemek Kitszel 				err = ice_vf_ena_vlan_promisc(vf, vsi, &vlan);
19535de6c855SPrzemek Kitszel 				if (err)
19545de6c855SPrzemek Kitszel 					return err;
19555de6c855SPrzemek Kitszel 			}
19565de6c855SPrzemek Kitszel 
19575de6c855SPrzemek Kitszel 			/* Enable VLAN filtering on first non-zero VLAN */
19585de6c855SPrzemek Kitszel 			if (vf->spoofchk && vlan.vid && ice_is_dvm_ena(&vsi->back->hw)) {
19595de6c855SPrzemek Kitszel 				err = vsi->outer_vlan_ops.ena_tx_filtering(vsi);
19605de6c855SPrzemek Kitszel 				if (err)
19615de6c855SPrzemek Kitszel 					return err;
19625de6c855SPrzemek Kitszel 			}
19635de6c855SPrzemek Kitszel 		}
19645de6c855SPrzemek Kitszel 
19655de6c855SPrzemek Kitszel 		vc_vlan = &vlan_fltr->inner;
19665de6c855SPrzemek Kitszel 		if (ice_vc_is_valid_vlan(vc_vlan)) {
19675de6c855SPrzemek Kitszel 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
19685de6c855SPrzemek Kitszel 
19695de6c855SPrzemek Kitszel 			err = ice_vc_vlan_action(vsi,
19705de6c855SPrzemek Kitszel 						 vsi->inner_vlan_ops.add_vlan,
19715de6c855SPrzemek Kitszel 						 &vlan);
19725de6c855SPrzemek Kitszel 			if (err)
19735de6c855SPrzemek Kitszel 				return err;
19745de6c855SPrzemek Kitszel 
19755de6c855SPrzemek Kitszel 			/* no support for VLAN promiscuous on inner VLAN unless
19765de6c855SPrzemek Kitszel 			 * we are in Single VLAN Mode (SVM)
19775de6c855SPrzemek Kitszel 			 */
19785de6c855SPrzemek Kitszel 			if (!ice_is_dvm_ena(&vsi->back->hw)) {
19795de6c855SPrzemek Kitszel 				if (vlan_promisc) {
19805de6c855SPrzemek Kitszel 					err = ice_vf_ena_vlan_promisc(vf, vsi,
19815de6c855SPrzemek Kitszel 								      &vlan);
19825de6c855SPrzemek Kitszel 					if (err)
19835de6c855SPrzemek Kitszel 						return err;
19845de6c855SPrzemek Kitszel 				}
19855de6c855SPrzemek Kitszel 
19865de6c855SPrzemek Kitszel 				/* Enable VLAN filtering on first non-zero VLAN */
19875de6c855SPrzemek Kitszel 				if (vf->spoofchk && vlan.vid) {
19885de6c855SPrzemek Kitszel 					err = vsi->inner_vlan_ops.ena_tx_filtering(vsi);
19895de6c855SPrzemek Kitszel 					if (err)
19905de6c855SPrzemek Kitszel 						return err;
19915de6c855SPrzemek Kitszel 				}
19925de6c855SPrzemek Kitszel 			}
19935de6c855SPrzemek Kitszel 		}
19945de6c855SPrzemek Kitszel 	}
19955de6c855SPrzemek Kitszel 
19965de6c855SPrzemek Kitszel 	return 0;
19975de6c855SPrzemek Kitszel }
19985de6c855SPrzemek Kitszel 
19995de6c855SPrzemek Kitszel /**
20005de6c855SPrzemek Kitszel  * ice_vc_validate_add_vlan_filter_list - validate add filter list from the VF
20015de6c855SPrzemek Kitszel  * @vsi: VF VSI used to get number of existing VLAN filters
20025de6c855SPrzemek Kitszel  * @vfc: negotiated/supported VLAN filtering capabilities
20035de6c855SPrzemek Kitszel  * @vfl: VLAN filter list from VF to validate
20045de6c855SPrzemek Kitszel  *
20055de6c855SPrzemek Kitszel  * Validate all of the filters in the VLAN filter list from the VF during the
20065de6c855SPrzemek Kitszel  * VIRTCHNL_OP_ADD_VLAN_V2 opcode. If any of the checks fail then return false.
20075de6c855SPrzemek Kitszel  * Otherwise return true.
20085de6c855SPrzemek Kitszel  */
20095de6c855SPrzemek Kitszel static bool
20105de6c855SPrzemek Kitszel ice_vc_validate_add_vlan_filter_list(struct ice_vsi *vsi,
20115de6c855SPrzemek Kitszel 				     struct virtchnl_vlan_filtering_caps *vfc,
20125de6c855SPrzemek Kitszel 				     struct virtchnl_vlan_filter_list_v2 *vfl)
20135de6c855SPrzemek Kitszel {
20145de6c855SPrzemek Kitszel 	u16 num_requested_filters = ice_vsi_num_non_zero_vlans(vsi) +
20155de6c855SPrzemek Kitszel 		vfl->num_elements;
20165de6c855SPrzemek Kitszel 
20175de6c855SPrzemek Kitszel 	if (num_requested_filters > vfc->max_filters)
20185de6c855SPrzemek Kitszel 		return false;
20195de6c855SPrzemek Kitszel 
20205de6c855SPrzemek Kitszel 	return ice_vc_validate_vlan_filter_list(vfc, vfl);
20215de6c855SPrzemek Kitszel }
20225de6c855SPrzemek Kitszel 
20235de6c855SPrzemek Kitszel /**
20245de6c855SPrzemek Kitszel  * ice_vc_add_vlan_v2_msg - virtchnl handler for VIRTCHNL_OP_ADD_VLAN_V2
20255de6c855SPrzemek Kitszel  * @vf: VF the message was received from
20265de6c855SPrzemek Kitszel  * @msg: message received from the VF
20275de6c855SPrzemek Kitszel  */
20285de6c855SPrzemek Kitszel static int ice_vc_add_vlan_v2_msg(struct ice_vf *vf, u8 *msg)
20295de6c855SPrzemek Kitszel {
20305de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
20315de6c855SPrzemek Kitszel 	struct virtchnl_vlan_filter_list_v2 *vfl =
20325de6c855SPrzemek Kitszel 		(struct virtchnl_vlan_filter_list_v2 *)msg;
20335de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
20345de6c855SPrzemek Kitszel 
20355de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
20365de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
20375de6c855SPrzemek Kitszel 		goto out;
20385de6c855SPrzemek Kitszel 	}
20395de6c855SPrzemek Kitszel 
20405de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, vfl->vport_id)) {
20415de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
20425de6c855SPrzemek Kitszel 		goto out;
20435de6c855SPrzemek Kitszel 	}
20445de6c855SPrzemek Kitszel 
20455de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
20465de6c855SPrzemek Kitszel 	if (!vsi) {
20475de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
20485de6c855SPrzemek Kitszel 		goto out;
20495de6c855SPrzemek Kitszel 	}
20505de6c855SPrzemek Kitszel 
20515de6c855SPrzemek Kitszel 	if (!ice_vc_validate_add_vlan_filter_list(vsi,
20525de6c855SPrzemek Kitszel 						  &vf->vlan_v2_caps.filtering,
20535de6c855SPrzemek Kitszel 						  vfl)) {
20545de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
20555de6c855SPrzemek Kitszel 		goto out;
20565de6c855SPrzemek Kitszel 	}
20575de6c855SPrzemek Kitszel 
20585de6c855SPrzemek Kitszel 	if (ice_vc_add_vlans(vf, vsi, vfl))
20595de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
20605de6c855SPrzemek Kitszel 
20615de6c855SPrzemek Kitszel out:
20625de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN_V2, v_ret, NULL,
20635de6c855SPrzemek Kitszel 				     0);
20645de6c855SPrzemek Kitszel }
20655de6c855SPrzemek Kitszel 
20665de6c855SPrzemek Kitszel /**
20675de6c855SPrzemek Kitszel  * ice_vc_valid_vlan_setting - validate VLAN setting
20685de6c855SPrzemek Kitszel  * @negotiated_settings: negotiated VLAN settings during VF init
20695de6c855SPrzemek Kitszel  * @ethertype_setting: ethertype(s) requested for the VLAN setting
20705de6c855SPrzemek Kitszel  */
20715de6c855SPrzemek Kitszel static bool
20725de6c855SPrzemek Kitszel ice_vc_valid_vlan_setting(u32 negotiated_settings, u32 ethertype_setting)
20735de6c855SPrzemek Kitszel {
20745de6c855SPrzemek Kitszel 	if (ethertype_setting && !(negotiated_settings & ethertype_setting))
20755de6c855SPrzemek Kitszel 		return false;
20765de6c855SPrzemek Kitszel 
20775de6c855SPrzemek Kitszel 	/* only allow a single VIRTCHNL_VLAN_ETHERTYPE if
20785de6c855SPrzemek Kitszel 	 * VIRTHCNL_VLAN_ETHERTYPE_AND is not negotiated/supported
20795de6c855SPrzemek Kitszel 	 */
20805de6c855SPrzemek Kitszel 	if (!(negotiated_settings & VIRTCHNL_VLAN_ETHERTYPE_AND) &&
20815de6c855SPrzemek Kitszel 	    hweight32(ethertype_setting) > 1)
20825de6c855SPrzemek Kitszel 		return false;
20835de6c855SPrzemek Kitszel 
20845de6c855SPrzemek Kitszel 	/* ability to modify the VLAN setting was not negotiated */
20855de6c855SPrzemek Kitszel 	if (!(negotiated_settings & VIRTCHNL_VLAN_TOGGLE))
20865de6c855SPrzemek Kitszel 		return false;
20875de6c855SPrzemek Kitszel 
20885de6c855SPrzemek Kitszel 	return true;
20895de6c855SPrzemek Kitszel }
20905de6c855SPrzemek Kitszel 
20915de6c855SPrzemek Kitszel /**
20925de6c855SPrzemek Kitszel  * ice_vc_valid_vlan_setting_msg - validate the VLAN setting message
20935de6c855SPrzemek Kitszel  * @caps: negotiated VLAN settings during VF init
20945de6c855SPrzemek Kitszel  * @msg: message to validate
20955de6c855SPrzemek Kitszel  *
20965de6c855SPrzemek Kitszel  * Used to validate any VLAN virtchnl message sent as a
20975de6c855SPrzemek Kitszel  * virtchnl_vlan_setting structure. Validates the message against the
20985de6c855SPrzemek Kitszel  * negotiated/supported caps during VF driver init.
20995de6c855SPrzemek Kitszel  */
21005de6c855SPrzemek Kitszel static bool
21015de6c855SPrzemek Kitszel ice_vc_valid_vlan_setting_msg(struct virtchnl_vlan_supported_caps *caps,
21025de6c855SPrzemek Kitszel 			      struct virtchnl_vlan_setting *msg)
21035de6c855SPrzemek Kitszel {
21045de6c855SPrzemek Kitszel 	if ((!msg->outer_ethertype_setting &&
21055de6c855SPrzemek Kitszel 	     !msg->inner_ethertype_setting) ||
21065de6c855SPrzemek Kitszel 	    (!caps->outer && !caps->inner))
21075de6c855SPrzemek Kitszel 		return false;
21085de6c855SPrzemek Kitszel 
21095de6c855SPrzemek Kitszel 	if (msg->outer_ethertype_setting &&
21105de6c855SPrzemek Kitszel 	    !ice_vc_valid_vlan_setting(caps->outer,
21115de6c855SPrzemek Kitszel 				       msg->outer_ethertype_setting))
21125de6c855SPrzemek Kitszel 		return false;
21135de6c855SPrzemek Kitszel 
21145de6c855SPrzemek Kitszel 	if (msg->inner_ethertype_setting &&
21155de6c855SPrzemek Kitszel 	    !ice_vc_valid_vlan_setting(caps->inner,
21165de6c855SPrzemek Kitszel 				       msg->inner_ethertype_setting))
21175de6c855SPrzemek Kitszel 		return false;
21185de6c855SPrzemek Kitszel 
21195de6c855SPrzemek Kitszel 	return true;
21205de6c855SPrzemek Kitszel }
21215de6c855SPrzemek Kitszel 
21225de6c855SPrzemek Kitszel /**
21235de6c855SPrzemek Kitszel  * ice_vc_get_tpid - transform from VIRTCHNL_VLAN_ETHERTYPE_* to VLAN TPID
21245de6c855SPrzemek Kitszel  * @ethertype_setting: VIRTCHNL_VLAN_ETHERTYPE_* used to get VLAN TPID
21255de6c855SPrzemek Kitszel  * @tpid: VLAN TPID to populate
21265de6c855SPrzemek Kitszel  */
21275de6c855SPrzemek Kitszel static int ice_vc_get_tpid(u32 ethertype_setting, u16 *tpid)
21285de6c855SPrzemek Kitszel {
21295de6c855SPrzemek Kitszel 	switch (ethertype_setting) {
21305de6c855SPrzemek Kitszel 	case VIRTCHNL_VLAN_ETHERTYPE_8100:
21315de6c855SPrzemek Kitszel 		*tpid = ETH_P_8021Q;
21325de6c855SPrzemek Kitszel 		break;
21335de6c855SPrzemek Kitszel 	case VIRTCHNL_VLAN_ETHERTYPE_88A8:
21345de6c855SPrzemek Kitszel 		*tpid = ETH_P_8021AD;
21355de6c855SPrzemek Kitszel 		break;
21365de6c855SPrzemek Kitszel 	case VIRTCHNL_VLAN_ETHERTYPE_9100:
21375de6c855SPrzemek Kitszel 		*tpid = ETH_P_QINQ1;
21385de6c855SPrzemek Kitszel 		break;
21395de6c855SPrzemek Kitszel 	default:
21405de6c855SPrzemek Kitszel 		*tpid = 0;
21415de6c855SPrzemek Kitszel 		return -EINVAL;
21425de6c855SPrzemek Kitszel 	}
21435de6c855SPrzemek Kitszel 
21445de6c855SPrzemek Kitszel 	return 0;
21455de6c855SPrzemek Kitszel }
21465de6c855SPrzemek Kitszel 
21475de6c855SPrzemek Kitszel /**
21485de6c855SPrzemek Kitszel  * ice_vc_ena_vlan_offload - enable VLAN offload based on the ethertype_setting
21495de6c855SPrzemek Kitszel  * @vsi: VF's VSI used to enable the VLAN offload
21505de6c855SPrzemek Kitszel  * @ena_offload: function used to enable the VLAN offload
21515de6c855SPrzemek Kitszel  * @ethertype_setting: VIRTCHNL_VLAN_ETHERTYPE_* to enable offloads for
21525de6c855SPrzemek Kitszel  */
21535de6c855SPrzemek Kitszel static int
21545de6c855SPrzemek Kitszel ice_vc_ena_vlan_offload(struct ice_vsi *vsi,
21555de6c855SPrzemek Kitszel 			int (*ena_offload)(struct ice_vsi *vsi, u16 tpid),
21565de6c855SPrzemek Kitszel 			u32 ethertype_setting)
21575de6c855SPrzemek Kitszel {
21585de6c855SPrzemek Kitszel 	u16 tpid;
21595de6c855SPrzemek Kitszel 	int err;
21605de6c855SPrzemek Kitszel 
21615de6c855SPrzemek Kitszel 	err = ice_vc_get_tpid(ethertype_setting, &tpid);
21625de6c855SPrzemek Kitszel 	if (err)
21635de6c855SPrzemek Kitszel 		return err;
21645de6c855SPrzemek Kitszel 
21655de6c855SPrzemek Kitszel 	err = ena_offload(vsi, tpid);
21665de6c855SPrzemek Kitszel 	if (err)
21675de6c855SPrzemek Kitszel 		return err;
21685de6c855SPrzemek Kitszel 
21695de6c855SPrzemek Kitszel 	return 0;
21705de6c855SPrzemek Kitszel }
21715de6c855SPrzemek Kitszel 
21725de6c855SPrzemek Kitszel /**
21735de6c855SPrzemek Kitszel  * ice_vc_ena_vlan_stripping_v2_msg
21745de6c855SPrzemek Kitszel  * @vf: VF the message was received from
21755de6c855SPrzemek Kitszel  * @msg: message received from the VF
21765de6c855SPrzemek Kitszel  *
21775de6c855SPrzemek Kitszel  * virthcnl handler for VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2
21785de6c855SPrzemek Kitszel  */
21795de6c855SPrzemek Kitszel static int ice_vc_ena_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
21805de6c855SPrzemek Kitszel {
21815de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
21825de6c855SPrzemek Kitszel 	struct virtchnl_vlan_supported_caps *stripping_support;
21835de6c855SPrzemek Kitszel 	struct virtchnl_vlan_setting *strip_msg =
21845de6c855SPrzemek Kitszel 		(struct virtchnl_vlan_setting *)msg;
21855de6c855SPrzemek Kitszel 	u32 ethertype_setting;
21865de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
21875de6c855SPrzemek Kitszel 
21885de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
21895de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
21905de6c855SPrzemek Kitszel 		goto out;
21915de6c855SPrzemek Kitszel 	}
21925de6c855SPrzemek Kitszel 
21935de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, strip_msg->vport_id)) {
21945de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
21955de6c855SPrzemek Kitszel 		goto out;
21965de6c855SPrzemek Kitszel 	}
21975de6c855SPrzemek Kitszel 
21985de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
21995de6c855SPrzemek Kitszel 	if (!vsi) {
22005de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22015de6c855SPrzemek Kitszel 		goto out;
22025de6c855SPrzemek Kitszel 	}
22035de6c855SPrzemek Kitszel 
22045de6c855SPrzemek Kitszel 	stripping_support = &vf->vlan_v2_caps.offloads.stripping_support;
22055de6c855SPrzemek Kitszel 	if (!ice_vc_valid_vlan_setting_msg(stripping_support, strip_msg)) {
22065de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22075de6c855SPrzemek Kitszel 		goto out;
22085de6c855SPrzemek Kitszel 	}
22095de6c855SPrzemek Kitszel 
22105de6c855SPrzemek Kitszel 	if (ice_vsi_is_rxq_crc_strip_dis(vsi)) {
22115de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
22125de6c855SPrzemek Kitszel 		goto out;
22135de6c855SPrzemek Kitszel 	}
22145de6c855SPrzemek Kitszel 
22155de6c855SPrzemek Kitszel 	ethertype_setting = strip_msg->outer_ethertype_setting;
22165de6c855SPrzemek Kitszel 	if (ethertype_setting) {
22175de6c855SPrzemek Kitszel 		if (ice_vc_ena_vlan_offload(vsi,
22185de6c855SPrzemek Kitszel 					    vsi->outer_vlan_ops.ena_stripping,
22195de6c855SPrzemek Kitszel 					    ethertype_setting)) {
22205de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22215de6c855SPrzemek Kitszel 			goto out;
22225de6c855SPrzemek Kitszel 		} else {
22235de6c855SPrzemek Kitszel 			enum ice_l2tsel l2tsel =
22245de6c855SPrzemek Kitszel 				ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG2_2ND;
22255de6c855SPrzemek Kitszel 
22265de6c855SPrzemek Kitszel 			/* PF tells the VF that the outer VLAN tag is always
22275de6c855SPrzemek Kitszel 			 * extracted to VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 and
22285de6c855SPrzemek Kitszel 			 * inner is always extracted to
22295de6c855SPrzemek Kitszel 			 * VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1. This is needed to
22305de6c855SPrzemek Kitszel 			 * support outer stripping so the first tag always ends
22315de6c855SPrzemek Kitszel 			 * up in L2TAG2_2ND and the second/inner tag, if
22325de6c855SPrzemek Kitszel 			 * enabled, is extracted in L2TAG1.
22335de6c855SPrzemek Kitszel 			 */
22345de6c855SPrzemek Kitszel 			ice_vsi_update_l2tsel(vsi, l2tsel);
22355de6c855SPrzemek Kitszel 
22365de6c855SPrzemek Kitszel 			vf->vlan_strip_ena |= ICE_OUTER_VLAN_STRIP_ENA;
22375de6c855SPrzemek Kitszel 		}
22385de6c855SPrzemek Kitszel 	}
22395de6c855SPrzemek Kitszel 
22405de6c855SPrzemek Kitszel 	ethertype_setting = strip_msg->inner_ethertype_setting;
22415de6c855SPrzemek Kitszel 	if (ethertype_setting &&
22425de6c855SPrzemek Kitszel 	    ice_vc_ena_vlan_offload(vsi, vsi->inner_vlan_ops.ena_stripping,
22435de6c855SPrzemek Kitszel 				    ethertype_setting)) {
22445de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22455de6c855SPrzemek Kitszel 		goto out;
22465de6c855SPrzemek Kitszel 	}
22475de6c855SPrzemek Kitszel 
22485de6c855SPrzemek Kitszel 	if (ethertype_setting)
22495de6c855SPrzemek Kitszel 		vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA;
22505de6c855SPrzemek Kitszel 
22515de6c855SPrzemek Kitszel out:
22525de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2,
22535de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
22545de6c855SPrzemek Kitszel }
22555de6c855SPrzemek Kitszel 
22565de6c855SPrzemek Kitszel /**
22575de6c855SPrzemek Kitszel  * ice_vc_dis_vlan_stripping_v2_msg
22585de6c855SPrzemek Kitszel  * @vf: VF the message was received from
22595de6c855SPrzemek Kitszel  * @msg: message received from the VF
22605de6c855SPrzemek Kitszel  *
22615de6c855SPrzemek Kitszel  * virthcnl handler for VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2
22625de6c855SPrzemek Kitszel  */
22635de6c855SPrzemek Kitszel static int ice_vc_dis_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
22645de6c855SPrzemek Kitszel {
22655de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
22665de6c855SPrzemek Kitszel 	struct virtchnl_vlan_supported_caps *stripping_support;
22675de6c855SPrzemek Kitszel 	struct virtchnl_vlan_setting *strip_msg =
22685de6c855SPrzemek Kitszel 		(struct virtchnl_vlan_setting *)msg;
22695de6c855SPrzemek Kitszel 	u32 ethertype_setting;
22705de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
22715de6c855SPrzemek Kitszel 
22725de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
22735de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22745de6c855SPrzemek Kitszel 		goto out;
22755de6c855SPrzemek Kitszel 	}
22765de6c855SPrzemek Kitszel 
22775de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, strip_msg->vport_id)) {
22785de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22795de6c855SPrzemek Kitszel 		goto out;
22805de6c855SPrzemek Kitszel 	}
22815de6c855SPrzemek Kitszel 
22825de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
22835de6c855SPrzemek Kitszel 	if (!vsi) {
22845de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22855de6c855SPrzemek Kitszel 		goto out;
22865de6c855SPrzemek Kitszel 	}
22875de6c855SPrzemek Kitszel 
22885de6c855SPrzemek Kitszel 	stripping_support = &vf->vlan_v2_caps.offloads.stripping_support;
22895de6c855SPrzemek Kitszel 	if (!ice_vc_valid_vlan_setting_msg(stripping_support, strip_msg)) {
22905de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22915de6c855SPrzemek Kitszel 		goto out;
22925de6c855SPrzemek Kitszel 	}
22935de6c855SPrzemek Kitszel 
22945de6c855SPrzemek Kitszel 	ethertype_setting = strip_msg->outer_ethertype_setting;
22955de6c855SPrzemek Kitszel 	if (ethertype_setting) {
22965de6c855SPrzemek Kitszel 		if (vsi->outer_vlan_ops.dis_stripping(vsi)) {
22975de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
22985de6c855SPrzemek Kitszel 			goto out;
22995de6c855SPrzemek Kitszel 		} else {
23005de6c855SPrzemek Kitszel 			enum ice_l2tsel l2tsel =
23015de6c855SPrzemek Kitszel 				ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG1;
23025de6c855SPrzemek Kitszel 
23035de6c855SPrzemek Kitszel 			/* PF tells the VF that the outer VLAN tag is always
23045de6c855SPrzemek Kitszel 			 * extracted to VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 and
23055de6c855SPrzemek Kitszel 			 * inner is always extracted to
23065de6c855SPrzemek Kitszel 			 * VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1. This is needed to
23075de6c855SPrzemek Kitszel 			 * support inner stripping while outer stripping is
23085de6c855SPrzemek Kitszel 			 * disabled so that the first and only tag is extracted
23095de6c855SPrzemek Kitszel 			 * in L2TAG1.
23105de6c855SPrzemek Kitszel 			 */
23115de6c855SPrzemek Kitszel 			ice_vsi_update_l2tsel(vsi, l2tsel);
23125de6c855SPrzemek Kitszel 
23135de6c855SPrzemek Kitszel 			vf->vlan_strip_ena &= ~ICE_OUTER_VLAN_STRIP_ENA;
23145de6c855SPrzemek Kitszel 		}
23155de6c855SPrzemek Kitszel 	}
23165de6c855SPrzemek Kitszel 
23175de6c855SPrzemek Kitszel 	ethertype_setting = strip_msg->inner_ethertype_setting;
23185de6c855SPrzemek Kitszel 	if (ethertype_setting && vsi->inner_vlan_ops.dis_stripping(vsi)) {
23195de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23205de6c855SPrzemek Kitszel 		goto out;
23215de6c855SPrzemek Kitszel 	}
23225de6c855SPrzemek Kitszel 
23235de6c855SPrzemek Kitszel 	if (ethertype_setting)
23245de6c855SPrzemek Kitszel 		vf->vlan_strip_ena &= ~ICE_INNER_VLAN_STRIP_ENA;
23255de6c855SPrzemek Kitszel 
23265de6c855SPrzemek Kitszel out:
23275de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2,
23285de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
23295de6c855SPrzemek Kitszel }
23305de6c855SPrzemek Kitszel 
23315de6c855SPrzemek Kitszel /**
23325de6c855SPrzemek Kitszel  * ice_vc_ena_vlan_insertion_v2_msg
23335de6c855SPrzemek Kitszel  * @vf: VF the message was received from
23345de6c855SPrzemek Kitszel  * @msg: message received from the VF
23355de6c855SPrzemek Kitszel  *
23365de6c855SPrzemek Kitszel  * virthcnl handler for VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2
23375de6c855SPrzemek Kitszel  */
23385de6c855SPrzemek Kitszel static int ice_vc_ena_vlan_insertion_v2_msg(struct ice_vf *vf, u8 *msg)
23395de6c855SPrzemek Kitszel {
23405de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
23415de6c855SPrzemek Kitszel 	struct virtchnl_vlan_supported_caps *insertion_support;
23425de6c855SPrzemek Kitszel 	struct virtchnl_vlan_setting *insertion_msg =
23435de6c855SPrzemek Kitszel 		(struct virtchnl_vlan_setting *)msg;
23445de6c855SPrzemek Kitszel 	u32 ethertype_setting;
23455de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
23465de6c855SPrzemek Kitszel 
23475de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
23485de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23495de6c855SPrzemek Kitszel 		goto out;
23505de6c855SPrzemek Kitszel 	}
23515de6c855SPrzemek Kitszel 
23525de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, insertion_msg->vport_id)) {
23535de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23545de6c855SPrzemek Kitszel 		goto out;
23555de6c855SPrzemek Kitszel 	}
23565de6c855SPrzemek Kitszel 
23575de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
23585de6c855SPrzemek Kitszel 	if (!vsi) {
23595de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23605de6c855SPrzemek Kitszel 		goto out;
23615de6c855SPrzemek Kitszel 	}
23625de6c855SPrzemek Kitszel 
23635de6c855SPrzemek Kitszel 	insertion_support = &vf->vlan_v2_caps.offloads.insertion_support;
23645de6c855SPrzemek Kitszel 	if (!ice_vc_valid_vlan_setting_msg(insertion_support, insertion_msg)) {
23655de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23665de6c855SPrzemek Kitszel 		goto out;
23675de6c855SPrzemek Kitszel 	}
23685de6c855SPrzemek Kitszel 
23695de6c855SPrzemek Kitszel 	ethertype_setting = insertion_msg->outer_ethertype_setting;
23705de6c855SPrzemek Kitszel 	if (ethertype_setting &&
23715de6c855SPrzemek Kitszel 	    ice_vc_ena_vlan_offload(vsi, vsi->outer_vlan_ops.ena_insertion,
23725de6c855SPrzemek Kitszel 				    ethertype_setting)) {
23735de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23745de6c855SPrzemek Kitszel 		goto out;
23755de6c855SPrzemek Kitszel 	}
23765de6c855SPrzemek Kitszel 
23775de6c855SPrzemek Kitszel 	ethertype_setting = insertion_msg->inner_ethertype_setting;
23785de6c855SPrzemek Kitszel 	if (ethertype_setting &&
23795de6c855SPrzemek Kitszel 	    ice_vc_ena_vlan_offload(vsi, vsi->inner_vlan_ops.ena_insertion,
23805de6c855SPrzemek Kitszel 				    ethertype_setting)) {
23815de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
23825de6c855SPrzemek Kitszel 		goto out;
23835de6c855SPrzemek Kitszel 	}
23845de6c855SPrzemek Kitszel 
23855de6c855SPrzemek Kitszel out:
23865de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2,
23875de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
23885de6c855SPrzemek Kitszel }
23895de6c855SPrzemek Kitszel 
23905de6c855SPrzemek Kitszel /**
23915de6c855SPrzemek Kitszel  * ice_vc_dis_vlan_insertion_v2_msg
23925de6c855SPrzemek Kitszel  * @vf: VF the message was received from
23935de6c855SPrzemek Kitszel  * @msg: message received from the VF
23945de6c855SPrzemek Kitszel  *
23955de6c855SPrzemek Kitszel  * virthcnl handler for VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2
23965de6c855SPrzemek Kitszel  */
23975de6c855SPrzemek Kitszel static int ice_vc_dis_vlan_insertion_v2_msg(struct ice_vf *vf, u8 *msg)
23985de6c855SPrzemek Kitszel {
23995de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
24005de6c855SPrzemek Kitszel 	struct virtchnl_vlan_supported_caps *insertion_support;
24015de6c855SPrzemek Kitszel 	struct virtchnl_vlan_setting *insertion_msg =
24025de6c855SPrzemek Kitszel 		(struct virtchnl_vlan_setting *)msg;
24035de6c855SPrzemek Kitszel 	u32 ethertype_setting;
24045de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
24055de6c855SPrzemek Kitszel 
24065de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
24075de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24085de6c855SPrzemek Kitszel 		goto out;
24095de6c855SPrzemek Kitszel 	}
24105de6c855SPrzemek Kitszel 
24115de6c855SPrzemek Kitszel 	if (!ice_vc_isvalid_vsi_id(vf, insertion_msg->vport_id)) {
24125de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24135de6c855SPrzemek Kitszel 		goto out;
24145de6c855SPrzemek Kitszel 	}
24155de6c855SPrzemek Kitszel 
24165de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
24175de6c855SPrzemek Kitszel 	if (!vsi) {
24185de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24195de6c855SPrzemek Kitszel 		goto out;
24205de6c855SPrzemek Kitszel 	}
24215de6c855SPrzemek Kitszel 
24225de6c855SPrzemek Kitszel 	insertion_support = &vf->vlan_v2_caps.offloads.insertion_support;
24235de6c855SPrzemek Kitszel 	if (!ice_vc_valid_vlan_setting_msg(insertion_support, insertion_msg)) {
24245de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24255de6c855SPrzemek Kitszel 		goto out;
24265de6c855SPrzemek Kitszel 	}
24275de6c855SPrzemek Kitszel 
24285de6c855SPrzemek Kitszel 	ethertype_setting = insertion_msg->outer_ethertype_setting;
24295de6c855SPrzemek Kitszel 	if (ethertype_setting && vsi->outer_vlan_ops.dis_insertion(vsi)) {
24305de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24315de6c855SPrzemek Kitszel 		goto out;
24325de6c855SPrzemek Kitszel 	}
24335de6c855SPrzemek Kitszel 
24345de6c855SPrzemek Kitszel 	ethertype_setting = insertion_msg->inner_ethertype_setting;
24355de6c855SPrzemek Kitszel 	if (ethertype_setting && vsi->inner_vlan_ops.dis_insertion(vsi)) {
24365de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24375de6c855SPrzemek Kitszel 		goto out;
24385de6c855SPrzemek Kitszel 	}
24395de6c855SPrzemek Kitszel 
24405de6c855SPrzemek Kitszel out:
24415de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2,
24425de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
24435de6c855SPrzemek Kitszel }
24445de6c855SPrzemek Kitszel 
24455de6c855SPrzemek Kitszel static int ice_vc_get_ptp_cap(struct ice_vf *vf,
24465de6c855SPrzemek Kitszel 			      const struct virtchnl_ptp_caps *msg)
24475de6c855SPrzemek Kitszel {
24485de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24495de6c855SPrzemek Kitszel 	u32 caps = VIRTCHNL_1588_PTP_CAP_RX_TSTAMP |
24505de6c855SPrzemek Kitszel 		   VIRTCHNL_1588_PTP_CAP_READ_PHC;
24515de6c855SPrzemek Kitszel 
24525de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
24535de6c855SPrzemek Kitszel 		goto err;
24545de6c855SPrzemek Kitszel 
24555de6c855SPrzemek Kitszel 	v_ret = VIRTCHNL_STATUS_SUCCESS;
24565de6c855SPrzemek Kitszel 
24575de6c855SPrzemek Kitszel 	if (msg->caps & caps)
24585de6c855SPrzemek Kitszel 		vf->ptp_caps = caps;
24595de6c855SPrzemek Kitszel 
24605de6c855SPrzemek Kitszel err:
24615de6c855SPrzemek Kitszel 	/* send the response back to the VF */
24625de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_1588_PTP_GET_CAPS, v_ret,
24635de6c855SPrzemek Kitszel 				     (u8 *)&vf->ptp_caps,
24645de6c855SPrzemek Kitszel 				     sizeof(struct virtchnl_ptp_caps));
24655de6c855SPrzemek Kitszel }
24665de6c855SPrzemek Kitszel 
24675de6c855SPrzemek Kitszel static int ice_vc_get_phc_time(struct ice_vf *vf)
24685de6c855SPrzemek Kitszel {
24695de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM;
24705de6c855SPrzemek Kitszel 	struct virtchnl_phc_time *phc_time = NULL;
24715de6c855SPrzemek Kitszel 	struct ice_pf *pf = vf->pf;
24725de6c855SPrzemek Kitszel 	u32 len = 0;
24735de6c855SPrzemek Kitszel 	int ret;
24745de6c855SPrzemek Kitszel 
24755de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
24765de6c855SPrzemek Kitszel 		goto err;
24775de6c855SPrzemek Kitszel 
24785de6c855SPrzemek Kitszel 	v_ret = VIRTCHNL_STATUS_SUCCESS;
24795de6c855SPrzemek Kitszel 
24805de6c855SPrzemek Kitszel 	phc_time = kzalloc(sizeof(*phc_time), GFP_KERNEL);
24815de6c855SPrzemek Kitszel 	if (!phc_time) {
24825de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
24835de6c855SPrzemek Kitszel 		goto err;
24845de6c855SPrzemek Kitszel 	}
24855de6c855SPrzemek Kitszel 
24865de6c855SPrzemek Kitszel 	len = sizeof(*phc_time);
24875de6c855SPrzemek Kitszel 
24885de6c855SPrzemek Kitszel 	phc_time->time = ice_ptp_read_src_clk_reg(pf, NULL);
24895de6c855SPrzemek Kitszel 
24905de6c855SPrzemek Kitszel err:
24915de6c855SPrzemek Kitszel 	/* send the response back to the VF */
24925de6c855SPrzemek Kitszel 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_1588_PTP_GET_TIME, v_ret,
24935de6c855SPrzemek Kitszel 				    (u8 *)phc_time, len);
24945de6c855SPrzemek Kitszel 	kfree(phc_time);
24955de6c855SPrzemek Kitszel 	return ret;
24965de6c855SPrzemek Kitszel }
24975de6c855SPrzemek Kitszel 
24985de6c855SPrzemek Kitszel static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
24995de6c855SPrzemek Kitszel 	.get_ver_msg = ice_vc_get_ver_msg,
25005de6c855SPrzemek Kitszel 	.get_vf_res_msg = ice_vc_get_vf_res_msg,
25015de6c855SPrzemek Kitszel 	.reset_vf = ice_vc_reset_vf_msg,
25025de6c855SPrzemek Kitszel 	.add_mac_addr_msg = ice_vc_add_mac_addr_msg,
25035de6c855SPrzemek Kitszel 	.del_mac_addr_msg = ice_vc_del_mac_addr_msg,
25045de6c855SPrzemek Kitszel 	.cfg_qs_msg = ice_vc_cfg_qs_msg,
25055de6c855SPrzemek Kitszel 	.ena_qs_msg = ice_vc_ena_qs_msg,
25065de6c855SPrzemek Kitszel 	.dis_qs_msg = ice_vc_dis_qs_msg,
25075de6c855SPrzemek Kitszel 	.request_qs_msg = ice_vc_request_qs_msg,
25085de6c855SPrzemek Kitszel 	.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
25095de6c855SPrzemek Kitszel 	.config_rss_key = ice_vc_config_rss_key,
25105de6c855SPrzemek Kitszel 	.config_rss_lut = ice_vc_config_rss_lut,
25115de6c855SPrzemek Kitszel 	.config_rss_hfunc = ice_vc_config_rss_hfunc,
25125de6c855SPrzemek Kitszel 	.get_stats_msg = ice_vc_get_stats_msg,
25135de6c855SPrzemek Kitszel 	.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,
25145de6c855SPrzemek Kitszel 	.add_vlan_msg = ice_vc_add_vlan_msg,
25155de6c855SPrzemek Kitszel 	.remove_vlan_msg = ice_vc_remove_vlan_msg,
25165de6c855SPrzemek Kitszel 	.query_rxdid = ice_vc_query_rxdid,
25175de6c855SPrzemek Kitszel 	.get_rss_hashcfg = ice_vc_get_rss_hashcfg,
25185de6c855SPrzemek Kitszel 	.set_rss_hashcfg = ice_vc_set_rss_hashcfg,
25195de6c855SPrzemek Kitszel 	.ena_vlan_stripping = ice_vc_ena_vlan_stripping,
25205de6c855SPrzemek Kitszel 	.dis_vlan_stripping = ice_vc_dis_vlan_stripping,
25215de6c855SPrzemek Kitszel 	.handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
25225de6c855SPrzemek Kitszel 	.add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
25235de6c855SPrzemek Kitszel 	.del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
25245de6c855SPrzemek Kitszel 	.get_offload_vlan_v2_caps = ice_vc_get_offload_vlan_v2_caps,
25255de6c855SPrzemek Kitszel 	.add_vlan_v2_msg = ice_vc_add_vlan_v2_msg,
25265de6c855SPrzemek Kitszel 	.remove_vlan_v2_msg = ice_vc_remove_vlan_v2_msg,
25275de6c855SPrzemek Kitszel 	.ena_vlan_stripping_v2_msg = ice_vc_ena_vlan_stripping_v2_msg,
25285de6c855SPrzemek Kitszel 	.dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg,
25295de6c855SPrzemek Kitszel 	.ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg,
25305de6c855SPrzemek Kitszel 	.dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg,
25315de6c855SPrzemek Kitszel 	.get_qos_caps = ice_vc_get_qos_caps,
25325de6c855SPrzemek Kitszel 	.cfg_q_bw = ice_vc_cfg_q_bw,
25335de6c855SPrzemek Kitszel 	.cfg_q_quanta = ice_vc_cfg_q_quanta,
25345de6c855SPrzemek Kitszel 	.get_ptp_cap = ice_vc_get_ptp_cap,
25355de6c855SPrzemek Kitszel 	.get_phc_time = ice_vc_get_phc_time,
25365de6c855SPrzemek Kitszel 	/* If you add a new op here please make sure to add it to
25375de6c855SPrzemek Kitszel 	 * ice_virtchnl_repr_ops as well.
25385de6c855SPrzemek Kitszel 	 */
25395de6c855SPrzemek Kitszel };
25405de6c855SPrzemek Kitszel 
25415de6c855SPrzemek Kitszel /**
25425de6c855SPrzemek Kitszel  * ice_virtchnl_set_dflt_ops - Switch to default virtchnl ops
25435de6c855SPrzemek Kitszel  * @vf: the VF to switch ops
25445de6c855SPrzemek Kitszel  */
25455de6c855SPrzemek Kitszel void ice_virtchnl_set_dflt_ops(struct ice_vf *vf)
25465de6c855SPrzemek Kitszel {
25475de6c855SPrzemek Kitszel 	vf->virtchnl_ops = &ice_virtchnl_dflt_ops;
25485de6c855SPrzemek Kitszel }
25495de6c855SPrzemek Kitszel 
25505de6c855SPrzemek Kitszel /**
25515de6c855SPrzemek Kitszel  * ice_vc_repr_add_mac
25525de6c855SPrzemek Kitszel  * @vf: pointer to VF
25535de6c855SPrzemek Kitszel  * @msg: virtchannel message
25545de6c855SPrzemek Kitszel  *
25555de6c855SPrzemek Kitszel  * When port representors are created, we do not add MAC rule
25565de6c855SPrzemek Kitszel  * to firmware, we store it so that PF could report same
25575de6c855SPrzemek Kitszel  * MAC as VF.
25585de6c855SPrzemek Kitszel  */
25595de6c855SPrzemek Kitszel static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
25605de6c855SPrzemek Kitszel {
25615de6c855SPrzemek Kitszel 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
25625de6c855SPrzemek Kitszel 	struct virtchnl_ether_addr_list *al =
25635de6c855SPrzemek Kitszel 	    (struct virtchnl_ether_addr_list *)msg;
25645de6c855SPrzemek Kitszel 	struct ice_vsi *vsi;
25655de6c855SPrzemek Kitszel 	struct ice_pf *pf;
25665de6c855SPrzemek Kitszel 	int i;
25675de6c855SPrzemek Kitszel 
25685de6c855SPrzemek Kitszel 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
25695de6c855SPrzemek Kitszel 	    !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
25705de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
25715de6c855SPrzemek Kitszel 		goto handle_mac_exit;
25725de6c855SPrzemek Kitszel 	}
25735de6c855SPrzemek Kitszel 
25745de6c855SPrzemek Kitszel 	pf = vf->pf;
25755de6c855SPrzemek Kitszel 
25765de6c855SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
25775de6c855SPrzemek Kitszel 	if (!vsi) {
25785de6c855SPrzemek Kitszel 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
25795de6c855SPrzemek Kitszel 		goto handle_mac_exit;
25805de6c855SPrzemek Kitszel 	}
25815de6c855SPrzemek Kitszel 
25825de6c855SPrzemek Kitszel 	for (i = 0; i < al->num_elements; i++) {
25835de6c855SPrzemek Kitszel 		u8 *mac_addr = al->list[i].addr;
25845de6c855SPrzemek Kitszel 
25855de6c855SPrzemek Kitszel 		if (!is_unicast_ether_addr(mac_addr) ||
25865de6c855SPrzemek Kitszel 		    ether_addr_equal(mac_addr, vf->hw_lan_addr))
25875de6c855SPrzemek Kitszel 			continue;
25885de6c855SPrzemek Kitszel 
25895de6c855SPrzemek Kitszel 		if (vf->pf_set_mac) {
25905de6c855SPrzemek Kitszel 			dev_err(ice_pf_to_dev(pf), "VF attempting to override administratively set MAC address\n");
25915de6c855SPrzemek Kitszel 			v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
25925de6c855SPrzemek Kitszel 			goto handle_mac_exit;
25935de6c855SPrzemek Kitszel 		}
25945de6c855SPrzemek Kitszel 
25955de6c855SPrzemek Kitszel 		ice_vfhw_mac_add(vf, &al->list[i]);
25965de6c855SPrzemek Kitszel 		break;
25975de6c855SPrzemek Kitszel 	}
25985de6c855SPrzemek Kitszel 
25995de6c855SPrzemek Kitszel handle_mac_exit:
26005de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
26015de6c855SPrzemek Kitszel 				     v_ret, NULL, 0);
26025de6c855SPrzemek Kitszel }
26035de6c855SPrzemek Kitszel 
26045de6c855SPrzemek Kitszel /**
26055de6c855SPrzemek Kitszel  * ice_vc_repr_del_mac - response with success for deleting MAC
26065de6c855SPrzemek Kitszel  * @vf: pointer to VF
26075de6c855SPrzemek Kitszel  * @msg: virtchannel message
26085de6c855SPrzemek Kitszel  *
26095de6c855SPrzemek Kitszel  * Respond with success to not break normal VF flow.
26105de6c855SPrzemek Kitszel  * For legacy VF driver try to update cached MAC address.
26115de6c855SPrzemek Kitszel  */
26125de6c855SPrzemek Kitszel static int
26135de6c855SPrzemek Kitszel ice_vc_repr_del_mac(struct ice_vf __always_unused *vf, u8 __always_unused *msg)
26145de6c855SPrzemek Kitszel {
26155de6c855SPrzemek Kitszel 	struct virtchnl_ether_addr_list *al =
26165de6c855SPrzemek Kitszel 		(struct virtchnl_ether_addr_list *)msg;
26175de6c855SPrzemek Kitszel 
26185de6c855SPrzemek Kitszel 	ice_update_legacy_cached_mac(vf, &al->list[0]);
26195de6c855SPrzemek Kitszel 
26205de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
26215de6c855SPrzemek Kitszel 				     VIRTCHNL_STATUS_SUCCESS, NULL, 0);
26225de6c855SPrzemek Kitszel }
26235de6c855SPrzemek Kitszel 
26245de6c855SPrzemek Kitszel static int
26255de6c855SPrzemek Kitszel ice_vc_repr_cfg_promiscuous_mode(struct ice_vf *vf, u8 __always_unused *msg)
26265de6c855SPrzemek Kitszel {
26275de6c855SPrzemek Kitszel 	dev_dbg(ice_pf_to_dev(vf->pf),
26285de6c855SPrzemek Kitszel 		"Can't config promiscuous mode in switchdev mode for VF %d\n",
26295de6c855SPrzemek Kitszel 		vf->vf_id);
26305de6c855SPrzemek Kitszel 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
26315de6c855SPrzemek Kitszel 				     VIRTCHNL_STATUS_ERR_NOT_SUPPORTED,
26325de6c855SPrzemek Kitszel 				     NULL, 0);
26335de6c855SPrzemek Kitszel }
26345de6c855SPrzemek Kitszel 
26355de6c855SPrzemek Kitszel static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
26365de6c855SPrzemek Kitszel 	.get_ver_msg = ice_vc_get_ver_msg,
26375de6c855SPrzemek Kitszel 	.get_vf_res_msg = ice_vc_get_vf_res_msg,
26385de6c855SPrzemek Kitszel 	.reset_vf = ice_vc_reset_vf_msg,
26395de6c855SPrzemek Kitszel 	.add_mac_addr_msg = ice_vc_repr_add_mac,
26405de6c855SPrzemek Kitszel 	.del_mac_addr_msg = ice_vc_repr_del_mac,
26415de6c855SPrzemek Kitszel 	.cfg_qs_msg = ice_vc_cfg_qs_msg,
26425de6c855SPrzemek Kitszel 	.ena_qs_msg = ice_vc_ena_qs_msg,
26435de6c855SPrzemek Kitszel 	.dis_qs_msg = ice_vc_dis_qs_msg,
26445de6c855SPrzemek Kitszel 	.request_qs_msg = ice_vc_request_qs_msg,
26455de6c855SPrzemek Kitszel 	.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
26465de6c855SPrzemek Kitszel 	.config_rss_key = ice_vc_config_rss_key,
26475de6c855SPrzemek Kitszel 	.config_rss_lut = ice_vc_config_rss_lut,
26485de6c855SPrzemek Kitszel 	.config_rss_hfunc = ice_vc_config_rss_hfunc,
26495de6c855SPrzemek Kitszel 	.get_stats_msg = ice_vc_get_stats_msg,
26505de6c855SPrzemek Kitszel 	.cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode,
26515de6c855SPrzemek Kitszel 	.add_vlan_msg = ice_vc_add_vlan_msg,
26525de6c855SPrzemek Kitszel 	.remove_vlan_msg = ice_vc_remove_vlan_msg,
26535de6c855SPrzemek Kitszel 	.query_rxdid = ice_vc_query_rxdid,
26545de6c855SPrzemek Kitszel 	.get_rss_hashcfg = ice_vc_get_rss_hashcfg,
26555de6c855SPrzemek Kitszel 	.set_rss_hashcfg = ice_vc_set_rss_hashcfg,
26565de6c855SPrzemek Kitszel 	.ena_vlan_stripping = ice_vc_ena_vlan_stripping,
26575de6c855SPrzemek Kitszel 	.dis_vlan_stripping = ice_vc_dis_vlan_stripping,
26585de6c855SPrzemek Kitszel 	.handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
26595de6c855SPrzemek Kitszel 	.add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
26605de6c855SPrzemek Kitszel 	.del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
26615de6c855SPrzemek Kitszel 	.get_offload_vlan_v2_caps = ice_vc_get_offload_vlan_v2_caps,
26625de6c855SPrzemek Kitszel 	.add_vlan_v2_msg = ice_vc_add_vlan_v2_msg,
26635de6c855SPrzemek Kitszel 	.remove_vlan_v2_msg = ice_vc_remove_vlan_v2_msg,
26645de6c855SPrzemek Kitszel 	.ena_vlan_stripping_v2_msg = ice_vc_ena_vlan_stripping_v2_msg,
26655de6c855SPrzemek Kitszel 	.dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg,
26665de6c855SPrzemek Kitszel 	.ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg,
26675de6c855SPrzemek Kitszel 	.dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg,
26685de6c855SPrzemek Kitszel 	.get_qos_caps = ice_vc_get_qos_caps,
26695de6c855SPrzemek Kitszel 	.cfg_q_bw = ice_vc_cfg_q_bw,
26705de6c855SPrzemek Kitszel 	.cfg_q_quanta = ice_vc_cfg_q_quanta,
26715de6c855SPrzemek Kitszel 	.get_ptp_cap = ice_vc_get_ptp_cap,
26725de6c855SPrzemek Kitszel 	.get_phc_time = ice_vc_get_phc_time,
26735de6c855SPrzemek Kitszel };
26745de6c855SPrzemek Kitszel 
26755de6c855SPrzemek Kitszel /**
26765de6c855SPrzemek Kitszel  * ice_virtchnl_set_repr_ops - Switch to representor virtchnl ops
26775de6c855SPrzemek Kitszel  * @vf: the VF to switch ops
26785de6c855SPrzemek Kitszel  */
26795de6c855SPrzemek Kitszel void ice_virtchnl_set_repr_ops(struct ice_vf *vf)
26805de6c855SPrzemek Kitszel {
26815de6c855SPrzemek Kitszel 	vf->virtchnl_ops = &ice_virtchnl_repr_ops;
26825de6c855SPrzemek Kitszel }
26835de6c855SPrzemek Kitszel 
26845de6c855SPrzemek Kitszel /**
26855de6c855SPrzemek Kitszel  * ice_is_malicious_vf - check if this vf might be overflowing mailbox
26865de6c855SPrzemek Kitszel  * @vf: the VF to check
26875de6c855SPrzemek Kitszel  * @mbxdata: data about the state of the mailbox
26885de6c855SPrzemek Kitszel  *
26895de6c855SPrzemek Kitszel  * Detect if a given VF might be malicious and attempting to overflow the PF
26905de6c855SPrzemek Kitszel  * mailbox. If so, log a warning message and ignore this event.
26915de6c855SPrzemek Kitszel  */
26925de6c855SPrzemek Kitszel static bool
26935de6c855SPrzemek Kitszel ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata)
26945de6c855SPrzemek Kitszel {
26955de6c855SPrzemek Kitszel 	bool report_malvf = false;
26965de6c855SPrzemek Kitszel 	struct device *dev;
26975de6c855SPrzemek Kitszel 	struct ice_pf *pf;
26985de6c855SPrzemek Kitszel 	int status;
26995de6c855SPrzemek Kitszel 
27005de6c855SPrzemek Kitszel 	pf = vf->pf;
27015de6c855SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
27025de6c855SPrzemek Kitszel 
27035de6c855SPrzemek Kitszel 	if (test_bit(ICE_VF_STATE_DIS, vf->vf_states))
27045de6c855SPrzemek Kitszel 		return vf->mbx_info.malicious;
27055de6c855SPrzemek Kitszel 
27065de6c855SPrzemek Kitszel 	/* check to see if we have a newly malicious VF */
27075de6c855SPrzemek Kitszel 	status = ice_mbx_vf_state_handler(&pf->hw, mbxdata, &vf->mbx_info,
27085de6c855SPrzemek Kitszel 					  &report_malvf);
27095de6c855SPrzemek Kitszel 	if (status)
27105de6c855SPrzemek Kitszel 		dev_warn_ratelimited(dev, "Unable to check status of mailbox overflow for VF %u MAC %pM, status %d\n",
27115de6c855SPrzemek Kitszel 				     vf->vf_id, vf->dev_lan_addr, status);
27125de6c855SPrzemek Kitszel 
27135de6c855SPrzemek Kitszel 	if (report_malvf) {
27145de6c855SPrzemek Kitszel 		struct ice_vsi *pf_vsi = ice_get_main_vsi(pf);
27155de6c855SPrzemek Kitszel 		u8 zero_addr[ETH_ALEN] = {};
27165de6c855SPrzemek Kitszel 
27175de6c855SPrzemek Kitszel 		dev_warn(dev, "VF MAC %pM on PF MAC %pM is generating asynchronous messages and may be overflowing the PF message queue. Please see the Adapter User Guide for more information\n",
27185de6c855SPrzemek Kitszel 			 vf->dev_lan_addr,
27195de6c855SPrzemek Kitszel 			 pf_vsi ? pf_vsi->netdev->dev_addr : zero_addr);
27205de6c855SPrzemek Kitszel 	}
27215de6c855SPrzemek Kitszel 
27225de6c855SPrzemek Kitszel 	return vf->mbx_info.malicious;
27235de6c855SPrzemek Kitszel }
27245de6c855SPrzemek Kitszel 
27255de6c855SPrzemek Kitszel /**
27265de6c855SPrzemek Kitszel  * ice_vc_process_vf_msg - Process request from VF
27275de6c855SPrzemek Kitszel  * @pf: pointer to the PF structure
27285de6c855SPrzemek Kitszel  * @event: pointer to the AQ event
27295de6c855SPrzemek Kitszel  * @mbxdata: information used to detect VF attempting mailbox overflow
27305de6c855SPrzemek Kitszel  *
27315de6c855SPrzemek Kitszel  * Called from the common asq/arq handler to process request from VF. When this
27325de6c855SPrzemek Kitszel  * flow is used for devices with hardware VF to PF message queue overflow
27335de6c855SPrzemek Kitszel  * support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and ice_is_malicious_vf
27345de6c855SPrzemek Kitszel  * check is skipped.
27355de6c855SPrzemek Kitszel  */
27365de6c855SPrzemek Kitszel void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
27375de6c855SPrzemek Kitszel 			   struct ice_mbx_data *mbxdata)
27385de6c855SPrzemek Kitszel {
27395de6c855SPrzemek Kitszel 	u32 v_opcode = le32_to_cpu(event->desc.cookie_high);
27405de6c855SPrzemek Kitszel 	s16 vf_id = le16_to_cpu(event->desc.retval);
27415de6c855SPrzemek Kitszel 	const struct ice_virtchnl_ops *ops;
27425de6c855SPrzemek Kitszel 	u16 msglen = event->msg_len;
27435de6c855SPrzemek Kitszel 	u8 *msg = event->msg_buf;
27445de6c855SPrzemek Kitszel 	struct ice_vf *vf = NULL;
27455de6c855SPrzemek Kitszel 	struct device *dev;
27465de6c855SPrzemek Kitszel 	int err = 0;
27475de6c855SPrzemek Kitszel 
27485de6c855SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
27495de6c855SPrzemek Kitszel 
27505de6c855SPrzemek Kitszel 	vf = ice_get_vf_by_id(pf, vf_id);
27515de6c855SPrzemek Kitszel 	if (!vf) {
27525de6c855SPrzemek Kitszel 		dev_err(dev, "Unable to locate VF for message from VF ID %d, opcode %d, len %d\n",
27535de6c855SPrzemek Kitszel 			vf_id, v_opcode, msglen);
27545de6c855SPrzemek Kitszel 		return;
27555de6c855SPrzemek Kitszel 	}
27565de6c855SPrzemek Kitszel 
27575de6c855SPrzemek Kitszel 	mutex_lock(&vf->cfg_lock);
27585de6c855SPrzemek Kitszel 
27595de6c855SPrzemek Kitszel 	/* Check if the VF is trying to overflow the mailbox */
27605de6c855SPrzemek Kitszel 	if (mbxdata && ice_is_malicious_vf(vf, mbxdata))
27615de6c855SPrzemek Kitszel 		goto finish;
27625de6c855SPrzemek Kitszel 
27635de6c855SPrzemek Kitszel 	/* Check if VF is disabled. */
27645de6c855SPrzemek Kitszel 	if (test_bit(ICE_VF_STATE_DIS, vf->vf_states)) {
27655de6c855SPrzemek Kitszel 		err = -EPERM;
27665de6c855SPrzemek Kitszel 		goto error_handler;
27675de6c855SPrzemek Kitszel 	}
27685de6c855SPrzemek Kitszel 
27695de6c855SPrzemek Kitszel 	ops = vf->virtchnl_ops;
27705de6c855SPrzemek Kitszel 
27715de6c855SPrzemek Kitszel 	/* Perform basic checks on the msg */
27725de6c855SPrzemek Kitszel 	err = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen);
27735de6c855SPrzemek Kitszel 	if (err) {
27745de6c855SPrzemek Kitszel 		if (err == VIRTCHNL_STATUS_ERR_PARAM)
27755de6c855SPrzemek Kitszel 			err = -EPERM;
27765de6c855SPrzemek Kitszel 		else
27775de6c855SPrzemek Kitszel 			err = -EINVAL;
27785de6c855SPrzemek Kitszel 	}
27795de6c855SPrzemek Kitszel 
27805de6c855SPrzemek Kitszel error_handler:
27815de6c855SPrzemek Kitszel 	if (err) {
27825de6c855SPrzemek Kitszel 		ice_vc_send_msg_to_vf(vf, v_opcode, VIRTCHNL_STATUS_ERR_PARAM,
27835de6c855SPrzemek Kitszel 				      NULL, 0);
27845de6c855SPrzemek Kitszel 		dev_err(dev, "Invalid message from VF %d, opcode %d, len %d, error %d\n",
27855de6c855SPrzemek Kitszel 			vf_id, v_opcode, msglen, err);
27865de6c855SPrzemek Kitszel 		goto finish;
27875de6c855SPrzemek Kitszel 	}
27885de6c855SPrzemek Kitszel 
27895de6c855SPrzemek Kitszel 	if (!ice_vc_is_opcode_allowed(vf, v_opcode)) {
27905de6c855SPrzemek Kitszel 		ice_vc_send_msg_to_vf(vf, v_opcode,
27915de6c855SPrzemek Kitszel 				      VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL,
27925de6c855SPrzemek Kitszel 				      0);
27935de6c855SPrzemek Kitszel 		goto finish;
27945de6c855SPrzemek Kitszel 	}
27955de6c855SPrzemek Kitszel 
27965de6c855SPrzemek Kitszel 	switch (v_opcode) {
27975de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_VERSION:
27985de6c855SPrzemek Kitszel 		err = ops->get_ver_msg(vf, msg);
27995de6c855SPrzemek Kitszel 		break;
28005de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_GET_VF_RESOURCES:
28015de6c855SPrzemek Kitszel 		err = ops->get_vf_res_msg(vf, msg);
28025de6c855SPrzemek Kitszel 		if (ice_vf_init_vlan_stripping(vf))
28035de6c855SPrzemek Kitszel 			dev_dbg(dev, "Failed to initialize VLAN stripping for VF %d\n",
28045de6c855SPrzemek Kitszel 				vf->vf_id);
28055de6c855SPrzemek Kitszel 		ice_vc_notify_vf_link_state(vf);
28065de6c855SPrzemek Kitszel 		break;
28075de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_RESET_VF:
28085de6c855SPrzemek Kitszel 		ops->reset_vf(vf);
28095de6c855SPrzemek Kitszel 		break;
28105de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ADD_ETH_ADDR:
28115de6c855SPrzemek Kitszel 		err = ops->add_mac_addr_msg(vf, msg);
28125de6c855SPrzemek Kitszel 		break;
28135de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DEL_ETH_ADDR:
28145de6c855SPrzemek Kitszel 		err = ops->del_mac_addr_msg(vf, msg);
28155de6c855SPrzemek Kitszel 		break;
28165de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
28175de6c855SPrzemek Kitszel 		err = ops->cfg_qs_msg(vf, msg);
28185de6c855SPrzemek Kitszel 		break;
28195de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ENABLE_QUEUES:
28205de6c855SPrzemek Kitszel 		err = ops->ena_qs_msg(vf, msg);
28215de6c855SPrzemek Kitszel 		ice_vc_notify_vf_link_state(vf);
28225de6c855SPrzemek Kitszel 		break;
28235de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DISABLE_QUEUES:
28245de6c855SPrzemek Kitszel 		err = ops->dis_qs_msg(vf, msg);
28255de6c855SPrzemek Kitszel 		break;
28265de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_REQUEST_QUEUES:
28275de6c855SPrzemek Kitszel 		err = ops->request_qs_msg(vf, msg);
28285de6c855SPrzemek Kitszel 		break;
28295de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
28305de6c855SPrzemek Kitszel 		err = ops->cfg_irq_map_msg(vf, msg);
28315de6c855SPrzemek Kitszel 		break;
28325de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_RSS_KEY:
28335de6c855SPrzemek Kitszel 		err = ops->config_rss_key(vf, msg);
28345de6c855SPrzemek Kitszel 		break;
28355de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_RSS_LUT:
28365de6c855SPrzemek Kitszel 		err = ops->config_rss_lut(vf, msg);
28375de6c855SPrzemek Kitszel 		break;
28385de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
28395de6c855SPrzemek Kitszel 		err = ops->config_rss_hfunc(vf, msg);
28405de6c855SPrzemek Kitszel 		break;
28415de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_GET_STATS:
28425de6c855SPrzemek Kitszel 		err = ops->get_stats_msg(vf, msg);
28435de6c855SPrzemek Kitszel 		break;
28445de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
28455de6c855SPrzemek Kitszel 		err = ops->cfg_promiscuous_mode_msg(vf, msg);
28465de6c855SPrzemek Kitszel 		break;
28475de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ADD_VLAN:
28485de6c855SPrzemek Kitszel 		err = ops->add_vlan_msg(vf, msg);
28495de6c855SPrzemek Kitszel 		break;
28505de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DEL_VLAN:
28515de6c855SPrzemek Kitszel 		err = ops->remove_vlan_msg(vf, msg);
28525de6c855SPrzemek Kitszel 		break;
28535de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS:
28545de6c855SPrzemek Kitszel 		err = ops->query_rxdid(vf);
28555de6c855SPrzemek Kitszel 		break;
28565de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_GET_RSS_HASHCFG_CAPS:
28575de6c855SPrzemek Kitszel 		err = ops->get_rss_hashcfg(vf);
28585de6c855SPrzemek Kitszel 		break;
28595de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_SET_RSS_HASHCFG:
28605de6c855SPrzemek Kitszel 		err = ops->set_rss_hashcfg(vf, msg);
28615de6c855SPrzemek Kitszel 		break;
28625de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
28635de6c855SPrzemek Kitszel 		err = ops->ena_vlan_stripping(vf);
28645de6c855SPrzemek Kitszel 		break;
28655de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
28665de6c855SPrzemek Kitszel 		err = ops->dis_vlan_stripping(vf);
28675de6c855SPrzemek Kitszel 		break;
28685de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ADD_FDIR_FILTER:
28695de6c855SPrzemek Kitszel 		err = ops->add_fdir_fltr_msg(vf, msg);
28705de6c855SPrzemek Kitszel 		break;
28715de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DEL_FDIR_FILTER:
28725de6c855SPrzemek Kitszel 		err = ops->del_fdir_fltr_msg(vf, msg);
28735de6c855SPrzemek Kitszel 		break;
28745de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ADD_RSS_CFG:
28755de6c855SPrzemek Kitszel 		err = ops->handle_rss_cfg_msg(vf, msg, true);
28765de6c855SPrzemek Kitszel 		break;
28775de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DEL_RSS_CFG:
28785de6c855SPrzemek Kitszel 		err = ops->handle_rss_cfg_msg(vf, msg, false);
28795de6c855SPrzemek Kitszel 		break;
28805de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS:
28815de6c855SPrzemek Kitszel 		err = ops->get_offload_vlan_v2_caps(vf);
28825de6c855SPrzemek Kitszel 		break;
28835de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ADD_VLAN_V2:
28845de6c855SPrzemek Kitszel 		err = ops->add_vlan_v2_msg(vf, msg);
28855de6c855SPrzemek Kitszel 		break;
28865de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DEL_VLAN_V2:
28875de6c855SPrzemek Kitszel 		err = ops->remove_vlan_v2_msg(vf, msg);
28885de6c855SPrzemek Kitszel 		break;
28895de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2:
28905de6c855SPrzemek Kitszel 		err = ops->ena_vlan_stripping_v2_msg(vf, msg);
28915de6c855SPrzemek Kitszel 		break;
28925de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2:
28935de6c855SPrzemek Kitszel 		err = ops->dis_vlan_stripping_v2_msg(vf, msg);
28945de6c855SPrzemek Kitszel 		break;
28955de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2:
28965de6c855SPrzemek Kitszel 		err = ops->ena_vlan_insertion_v2_msg(vf, msg);
28975de6c855SPrzemek Kitszel 		break;
28985de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2:
28995de6c855SPrzemek Kitszel 		err = ops->dis_vlan_insertion_v2_msg(vf, msg);
29005de6c855SPrzemek Kitszel 		break;
29015de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_GET_QOS_CAPS:
29025de6c855SPrzemek Kitszel 		err = ops->get_qos_caps(vf);
29035de6c855SPrzemek Kitszel 		break;
29045de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_QUEUE_BW:
29055de6c855SPrzemek Kitszel 		err = ops->cfg_q_bw(vf, msg);
29065de6c855SPrzemek Kitszel 		break;
29075de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_CONFIG_QUANTA:
29085de6c855SPrzemek Kitszel 		err = ops->cfg_q_quanta(vf, msg);
29095de6c855SPrzemek Kitszel 		break;
29105de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_1588_PTP_GET_CAPS:
29115de6c855SPrzemek Kitszel 		err = ops->get_ptp_cap(vf, (const void *)msg);
29125de6c855SPrzemek Kitszel 		break;
29135de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_1588_PTP_GET_TIME:
29145de6c855SPrzemek Kitszel 		err = ops->get_phc_time(vf);
29155de6c855SPrzemek Kitszel 		break;
29165de6c855SPrzemek Kitszel 	case VIRTCHNL_OP_UNKNOWN:
29175de6c855SPrzemek Kitszel 	default:
29185de6c855SPrzemek Kitszel 		dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode,
29195de6c855SPrzemek Kitszel 			vf_id);
29205de6c855SPrzemek Kitszel 		err = ice_vc_send_msg_to_vf(vf, v_opcode,
29215de6c855SPrzemek Kitszel 					    VIRTCHNL_STATUS_ERR_NOT_SUPPORTED,
29225de6c855SPrzemek Kitszel 					    NULL, 0);
29235de6c855SPrzemek Kitszel 		break;
29245de6c855SPrzemek Kitszel 	}
29255de6c855SPrzemek Kitszel 	if (err) {
29265de6c855SPrzemek Kitszel 		/* Helper function cares less about error return values here
29275de6c855SPrzemek Kitszel 		 * as it is busy with pending work.
29285de6c855SPrzemek Kitszel 		 */
29295de6c855SPrzemek Kitszel 		dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n",
29305de6c855SPrzemek Kitszel 			 vf_id, v_opcode, err);
29315de6c855SPrzemek Kitszel 	}
29325de6c855SPrzemek Kitszel 
29335de6c855SPrzemek Kitszel finish:
29345de6c855SPrzemek Kitszel 	mutex_unlock(&vf->cfg_lock);
29355de6c855SPrzemek Kitszel 	ice_put_vf(vf);
29365de6c855SPrzemek Kitszel }
2937