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