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