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