1*5de6c855SPrzemek Kitszel // SPDX-License-Identifier: GPL-2.0 2*5de6c855SPrzemek Kitszel /* Copyright (C) 2021-2023, Intel Corporation. */ 3*5de6c855SPrzemek Kitszel 4*5de6c855SPrzemek Kitszel #include "ice.h" 5*5de6c855SPrzemek Kitszel #include "ice_base.h" 6*5de6c855SPrzemek Kitszel #include "ice_lib.h" 7*5de6c855SPrzemek Kitszel #include "ice_flow.h" 8*5de6c855SPrzemek Kitszel #include "ice_vf_lib_private.h" 9*5de6c855SPrzemek Kitszel 10*5de6c855SPrzemek Kitszel #define to_fltr_conf_from_desc(p) \ 11*5de6c855SPrzemek Kitszel container_of(p, struct virtchnl_fdir_fltr_conf, input) 12*5de6c855SPrzemek Kitszel 13*5de6c855SPrzemek Kitszel #define GTPU_TEID_OFFSET 4 14*5de6c855SPrzemek Kitszel #define GTPU_EH_QFI_OFFSET 1 15*5de6c855SPrzemek Kitszel #define GTPU_EH_QFI_MASK 0x3F 16*5de6c855SPrzemek Kitszel #define PFCP_S_OFFSET 0 17*5de6c855SPrzemek Kitszel #define PFCP_S_MASK 0x1 18*5de6c855SPrzemek Kitszel #define PFCP_PORT_NR 8805 19*5de6c855SPrzemek Kitszel 20*5de6c855SPrzemek Kitszel #define FDIR_INSET_FLAG_ESP_S 0 21*5de6c855SPrzemek Kitszel #define FDIR_INSET_FLAG_ESP_M BIT_ULL(FDIR_INSET_FLAG_ESP_S) 22*5de6c855SPrzemek Kitszel #define FDIR_INSET_FLAG_ESP_UDP BIT_ULL(FDIR_INSET_FLAG_ESP_S) 23*5de6c855SPrzemek Kitszel #define FDIR_INSET_FLAG_ESP_IPSEC (0ULL << FDIR_INSET_FLAG_ESP_S) 24*5de6c855SPrzemek Kitszel 25*5de6c855SPrzemek Kitszel enum ice_fdir_tunnel_type { 26*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_NONE = 0, 27*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GTPU, 28*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GTPU_EH, 29*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_ECPRI, 30*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GTPU_INNER, 31*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GTPU_EH_INNER, 32*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GRE, 33*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GTPOGRE, 34*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GTPOGRE_INNER, 35*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_GRE_INNER, 36*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_L2TPV2, 37*5de6c855SPrzemek Kitszel ICE_FDIR_TUNNEL_TYPE_L2TPV2_INNER, 38*5de6c855SPrzemek Kitszel }; 39*5de6c855SPrzemek Kitszel 40*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf { 41*5de6c855SPrzemek Kitszel struct ice_fdir_fltr input; 42*5de6c855SPrzemek Kitszel enum ice_fdir_tunnel_type ttype; 43*5de6c855SPrzemek Kitszel u64 inset_flag; 44*5de6c855SPrzemek Kitszel u32 flow_id; 45*5de6c855SPrzemek Kitszel 46*5de6c855SPrzemek Kitszel struct ice_parser_profile *prof; 47*5de6c855SPrzemek Kitszel bool parser_ena; 48*5de6c855SPrzemek Kitszel u8 *pkt_buf; 49*5de6c855SPrzemek Kitszel u8 pkt_len; 50*5de6c855SPrzemek Kitszel }; 51*5de6c855SPrzemek Kitszel 52*5de6c855SPrzemek Kitszel struct virtchnl_fdir_inset_map { 53*5de6c855SPrzemek Kitszel enum virtchnl_proto_hdr_field field; 54*5de6c855SPrzemek Kitszel enum ice_flow_field fld; 55*5de6c855SPrzemek Kitszel u64 flag; 56*5de6c855SPrzemek Kitszel u64 mask; 57*5de6c855SPrzemek Kitszel }; 58*5de6c855SPrzemek Kitszel 59*5de6c855SPrzemek Kitszel static const struct virtchnl_fdir_inset_map fdir_inset_map[] = { 60*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE, ICE_FLOW_FIELD_IDX_ETH_TYPE, 0, 0}, 61*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV4_SRC, ICE_FLOW_FIELD_IDX_IPV4_SA, 0, 0}, 62*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV4_DST, ICE_FLOW_FIELD_IDX_IPV4_DA, 0, 0}, 63*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV4_DSCP, ICE_FLOW_FIELD_IDX_IPV4_DSCP, 0, 0}, 64*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV4_TTL, ICE_FLOW_FIELD_IDX_IPV4_TTL, 0, 0}, 65*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV4_PROT, ICE_FLOW_FIELD_IDX_IPV4_PROT, 0, 0}, 66*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV6_SRC, ICE_FLOW_FIELD_IDX_IPV6_SA, 0, 0}, 67*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV6_DST, ICE_FLOW_FIELD_IDX_IPV6_DA, 0, 0}, 68*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV6_TC, ICE_FLOW_FIELD_IDX_IPV6_DSCP, 0, 0}, 69*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT, ICE_FLOW_FIELD_IDX_IPV6_TTL, 0, 0}, 70*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_IPV6_PROT, ICE_FLOW_FIELD_IDX_IPV6_PROT, 0, 0}, 71*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_UDP_SRC_PORT, ICE_FLOW_FIELD_IDX_UDP_SRC_PORT, 0, 0}, 72*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_UDP_DST_PORT, ICE_FLOW_FIELD_IDX_UDP_DST_PORT, 0, 0}, 73*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_TCP_SRC_PORT, ICE_FLOW_FIELD_IDX_TCP_SRC_PORT, 0, 0}, 74*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_TCP_DST_PORT, ICE_FLOW_FIELD_IDX_TCP_DST_PORT, 0, 0}, 75*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT, ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT, 0, 0}, 76*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_SCTP_DST_PORT, ICE_FLOW_FIELD_IDX_SCTP_DST_PORT, 0, 0}, 77*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_GTPU_IP_TEID, ICE_FLOW_FIELD_IDX_GTPU_IP_TEID, 0, 0}, 78*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_GTPU_EH_QFI, ICE_FLOW_FIELD_IDX_GTPU_EH_QFI, 0, 0}, 79*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI, 80*5de6c855SPrzemek Kitszel FDIR_INSET_FLAG_ESP_IPSEC, FDIR_INSET_FLAG_ESP_M}, 81*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI, 82*5de6c855SPrzemek Kitszel FDIR_INSET_FLAG_ESP_UDP, FDIR_INSET_FLAG_ESP_M}, 83*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_AH_SPI, ICE_FLOW_FIELD_IDX_AH_SPI, 0, 0}, 84*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID, ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID, 0, 0}, 85*5de6c855SPrzemek Kitszel {VIRTCHNL_PROTO_HDR_PFCP_S_FIELD, ICE_FLOW_FIELD_IDX_UDP_DST_PORT, 0, 0}, 86*5de6c855SPrzemek Kitszel }; 87*5de6c855SPrzemek Kitszel 88*5de6c855SPrzemek Kitszel /** 89*5de6c855SPrzemek Kitszel * ice_vc_fdir_param_check 90*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 91*5de6c855SPrzemek Kitszel * @vsi_id: VF relative VSI ID 92*5de6c855SPrzemek Kitszel * 93*5de6c855SPrzemek Kitszel * Check for the valid VSI ID, PF's state and VF's state 94*5de6c855SPrzemek Kitszel * 95*5de6c855SPrzemek Kitszel * Return: 0 on success, and -EINVAL on error. 96*5de6c855SPrzemek Kitszel */ 97*5de6c855SPrzemek Kitszel static int 98*5de6c855SPrzemek Kitszel ice_vc_fdir_param_check(struct ice_vf *vf, u16 vsi_id) 99*5de6c855SPrzemek Kitszel { 100*5de6c855SPrzemek Kitszel struct ice_pf *pf = vf->pf; 101*5de6c855SPrzemek Kitszel 102*5de6c855SPrzemek Kitszel if (!test_bit(ICE_FLAG_FD_ENA, pf->flags)) 103*5de6c855SPrzemek Kitszel return -EINVAL; 104*5de6c855SPrzemek Kitszel 105*5de6c855SPrzemek Kitszel if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) 106*5de6c855SPrzemek Kitszel return -EINVAL; 107*5de6c855SPrzemek Kitszel 108*5de6c855SPrzemek Kitszel if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF)) 109*5de6c855SPrzemek Kitszel return -EINVAL; 110*5de6c855SPrzemek Kitszel 111*5de6c855SPrzemek Kitszel if (!ice_vc_isvalid_vsi_id(vf, vsi_id)) 112*5de6c855SPrzemek Kitszel return -EINVAL; 113*5de6c855SPrzemek Kitszel 114*5de6c855SPrzemek Kitszel if (!ice_get_vf_vsi(vf)) 115*5de6c855SPrzemek Kitszel return -EINVAL; 116*5de6c855SPrzemek Kitszel 117*5de6c855SPrzemek Kitszel return 0; 118*5de6c855SPrzemek Kitszel } 119*5de6c855SPrzemek Kitszel 120*5de6c855SPrzemek Kitszel /** 121*5de6c855SPrzemek Kitszel * ice_vf_start_ctrl_vsi 122*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 123*5de6c855SPrzemek Kitszel * 124*5de6c855SPrzemek Kitszel * Allocate ctrl_vsi for the first time and open the ctrl_vsi port for VF 125*5de6c855SPrzemek Kitszel * 126*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 127*5de6c855SPrzemek Kitszel */ 128*5de6c855SPrzemek Kitszel static int ice_vf_start_ctrl_vsi(struct ice_vf *vf) 129*5de6c855SPrzemek Kitszel { 130*5de6c855SPrzemek Kitszel struct ice_pf *pf = vf->pf; 131*5de6c855SPrzemek Kitszel struct ice_vsi *ctrl_vsi; 132*5de6c855SPrzemek Kitszel struct device *dev; 133*5de6c855SPrzemek Kitszel int err; 134*5de6c855SPrzemek Kitszel 135*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 136*5de6c855SPrzemek Kitszel if (vf->ctrl_vsi_idx != ICE_NO_VSI) 137*5de6c855SPrzemek Kitszel return -EEXIST; 138*5de6c855SPrzemek Kitszel 139*5de6c855SPrzemek Kitszel ctrl_vsi = ice_vf_ctrl_vsi_setup(vf); 140*5de6c855SPrzemek Kitszel if (!ctrl_vsi) { 141*5de6c855SPrzemek Kitszel dev_dbg(dev, "Could not setup control VSI for VF %d\n", 142*5de6c855SPrzemek Kitszel vf->vf_id); 143*5de6c855SPrzemek Kitszel return -ENOMEM; 144*5de6c855SPrzemek Kitszel } 145*5de6c855SPrzemek Kitszel 146*5de6c855SPrzemek Kitszel err = ice_vsi_open_ctrl(ctrl_vsi); 147*5de6c855SPrzemek Kitszel if (err) { 148*5de6c855SPrzemek Kitszel dev_dbg(dev, "Could not open control VSI for VF %d\n", 149*5de6c855SPrzemek Kitszel vf->vf_id); 150*5de6c855SPrzemek Kitszel goto err_vsi_open; 151*5de6c855SPrzemek Kitszel } 152*5de6c855SPrzemek Kitszel 153*5de6c855SPrzemek Kitszel return 0; 154*5de6c855SPrzemek Kitszel 155*5de6c855SPrzemek Kitszel err_vsi_open: 156*5de6c855SPrzemek Kitszel ice_vsi_release(ctrl_vsi); 157*5de6c855SPrzemek Kitszel if (vf->ctrl_vsi_idx != ICE_NO_VSI) { 158*5de6c855SPrzemek Kitszel pf->vsi[vf->ctrl_vsi_idx] = NULL; 159*5de6c855SPrzemek Kitszel vf->ctrl_vsi_idx = ICE_NO_VSI; 160*5de6c855SPrzemek Kitszel } 161*5de6c855SPrzemek Kitszel return err; 162*5de6c855SPrzemek Kitszel } 163*5de6c855SPrzemek Kitszel 164*5de6c855SPrzemek Kitszel /** 165*5de6c855SPrzemek Kitszel * ice_vc_fdir_alloc_prof - allocate profile for this filter flow type 166*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 167*5de6c855SPrzemek Kitszel * @flow: filter flow type 168*5de6c855SPrzemek Kitszel * 169*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 170*5de6c855SPrzemek Kitszel */ 171*5de6c855SPrzemek Kitszel static int 172*5de6c855SPrzemek Kitszel ice_vc_fdir_alloc_prof(struct ice_vf *vf, enum ice_fltr_ptype flow) 173*5de6c855SPrzemek Kitszel { 174*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 175*5de6c855SPrzemek Kitszel 176*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof) { 177*5de6c855SPrzemek Kitszel fdir->fdir_prof = devm_kcalloc(ice_pf_to_dev(vf->pf), 178*5de6c855SPrzemek Kitszel ICE_FLTR_PTYPE_MAX, 179*5de6c855SPrzemek Kitszel sizeof(*fdir->fdir_prof), 180*5de6c855SPrzemek Kitszel GFP_KERNEL); 181*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof) 182*5de6c855SPrzemek Kitszel return -ENOMEM; 183*5de6c855SPrzemek Kitszel } 184*5de6c855SPrzemek Kitszel 185*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof[flow]) { 186*5de6c855SPrzemek Kitszel fdir->fdir_prof[flow] = devm_kzalloc(ice_pf_to_dev(vf->pf), 187*5de6c855SPrzemek Kitszel sizeof(**fdir->fdir_prof), 188*5de6c855SPrzemek Kitszel GFP_KERNEL); 189*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof[flow]) 190*5de6c855SPrzemek Kitszel return -ENOMEM; 191*5de6c855SPrzemek Kitszel } 192*5de6c855SPrzemek Kitszel 193*5de6c855SPrzemek Kitszel return 0; 194*5de6c855SPrzemek Kitszel } 195*5de6c855SPrzemek Kitszel 196*5de6c855SPrzemek Kitszel /** 197*5de6c855SPrzemek Kitszel * ice_vc_fdir_free_prof - free profile for this filter flow type 198*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 199*5de6c855SPrzemek Kitszel * @flow: filter flow type 200*5de6c855SPrzemek Kitszel */ 201*5de6c855SPrzemek Kitszel static void 202*5de6c855SPrzemek Kitszel ice_vc_fdir_free_prof(struct ice_vf *vf, enum ice_fltr_ptype flow) 203*5de6c855SPrzemek Kitszel { 204*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 205*5de6c855SPrzemek Kitszel 206*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof) 207*5de6c855SPrzemek Kitszel return; 208*5de6c855SPrzemek Kitszel 209*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof[flow]) 210*5de6c855SPrzemek Kitszel return; 211*5de6c855SPrzemek Kitszel 212*5de6c855SPrzemek Kitszel devm_kfree(ice_pf_to_dev(vf->pf), fdir->fdir_prof[flow]); 213*5de6c855SPrzemek Kitszel fdir->fdir_prof[flow] = NULL; 214*5de6c855SPrzemek Kitszel } 215*5de6c855SPrzemek Kitszel 216*5de6c855SPrzemek Kitszel /** 217*5de6c855SPrzemek Kitszel * ice_vc_fdir_free_prof_all - free all the profile for this VF 218*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 219*5de6c855SPrzemek Kitszel */ 220*5de6c855SPrzemek Kitszel static void ice_vc_fdir_free_prof_all(struct ice_vf *vf) 221*5de6c855SPrzemek Kitszel { 222*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 223*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow; 224*5de6c855SPrzemek Kitszel 225*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof) 226*5de6c855SPrzemek Kitszel return; 227*5de6c855SPrzemek Kitszel 228*5de6c855SPrzemek Kitszel for (flow = ICE_FLTR_PTYPE_NONF_NONE; flow < ICE_FLTR_PTYPE_MAX; flow++) 229*5de6c855SPrzemek Kitszel ice_vc_fdir_free_prof(vf, flow); 230*5de6c855SPrzemek Kitszel 231*5de6c855SPrzemek Kitszel devm_kfree(ice_pf_to_dev(vf->pf), fdir->fdir_prof); 232*5de6c855SPrzemek Kitszel fdir->fdir_prof = NULL; 233*5de6c855SPrzemek Kitszel } 234*5de6c855SPrzemek Kitszel 235*5de6c855SPrzemek Kitszel /** 236*5de6c855SPrzemek Kitszel * ice_vc_fdir_parse_flow_fld 237*5de6c855SPrzemek Kitszel * @proto_hdr: virtual channel protocol filter header 238*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 239*5de6c855SPrzemek Kitszel * @fld: field type array 240*5de6c855SPrzemek Kitszel * @fld_cnt: field counter 241*5de6c855SPrzemek Kitszel * 242*5de6c855SPrzemek Kitszel * Parse the virtual channel filter header and store them into field type array 243*5de6c855SPrzemek Kitszel * 244*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 245*5de6c855SPrzemek Kitszel */ 246*5de6c855SPrzemek Kitszel static int 247*5de6c855SPrzemek Kitszel ice_vc_fdir_parse_flow_fld(struct virtchnl_proto_hdr *proto_hdr, 248*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, 249*5de6c855SPrzemek Kitszel enum ice_flow_field *fld, int *fld_cnt) 250*5de6c855SPrzemek Kitszel { 251*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdr hdr; 252*5de6c855SPrzemek Kitszel u32 i; 253*5de6c855SPrzemek Kitszel 254*5de6c855SPrzemek Kitszel memcpy(&hdr, proto_hdr, sizeof(hdr)); 255*5de6c855SPrzemek Kitszel 256*5de6c855SPrzemek Kitszel for (i = 0; (i < ARRAY_SIZE(fdir_inset_map)) && 257*5de6c855SPrzemek Kitszel VIRTCHNL_GET_PROTO_HDR_FIELD(&hdr); i++) 258*5de6c855SPrzemek Kitszel if (VIRTCHNL_TEST_PROTO_HDR(&hdr, fdir_inset_map[i].field)) { 259*5de6c855SPrzemek Kitszel if (fdir_inset_map[i].mask && 260*5de6c855SPrzemek Kitszel ((fdir_inset_map[i].mask & conf->inset_flag) != 261*5de6c855SPrzemek Kitszel fdir_inset_map[i].flag)) 262*5de6c855SPrzemek Kitszel continue; 263*5de6c855SPrzemek Kitszel 264*5de6c855SPrzemek Kitszel fld[*fld_cnt] = fdir_inset_map[i].fld; 265*5de6c855SPrzemek Kitszel *fld_cnt += 1; 266*5de6c855SPrzemek Kitszel if (*fld_cnt >= ICE_FLOW_FIELD_IDX_MAX) 267*5de6c855SPrzemek Kitszel return -EINVAL; 268*5de6c855SPrzemek Kitszel VIRTCHNL_DEL_PROTO_HDR_FIELD(&hdr, 269*5de6c855SPrzemek Kitszel fdir_inset_map[i].field); 270*5de6c855SPrzemek Kitszel } 271*5de6c855SPrzemek Kitszel 272*5de6c855SPrzemek Kitszel return 0; 273*5de6c855SPrzemek Kitszel } 274*5de6c855SPrzemek Kitszel 275*5de6c855SPrzemek Kitszel /** 276*5de6c855SPrzemek Kitszel * ice_vc_fdir_set_flow_fld 277*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 278*5de6c855SPrzemek Kitszel * @fltr: virtual channel add cmd buffer 279*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 280*5de6c855SPrzemek Kitszel * @seg: array of one or more packet segments that describe the flow 281*5de6c855SPrzemek Kitszel * 282*5de6c855SPrzemek Kitszel * Parse the virtual channel add msg buffer's field vector and store them into 283*5de6c855SPrzemek Kitszel * flow's packet segment field 284*5de6c855SPrzemek Kitszel * 285*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 286*5de6c855SPrzemek Kitszel */ 287*5de6c855SPrzemek Kitszel static int 288*5de6c855SPrzemek Kitszel ice_vc_fdir_set_flow_fld(struct ice_vf *vf, struct virtchnl_fdir_add *fltr, 289*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, 290*5de6c855SPrzemek Kitszel struct ice_flow_seg_info *seg) 291*5de6c855SPrzemek Kitszel { 292*5de6c855SPrzemek Kitszel struct virtchnl_fdir_rule *rule = &fltr->rule_cfg; 293*5de6c855SPrzemek Kitszel enum ice_flow_field fld[ICE_FLOW_FIELD_IDX_MAX]; 294*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 295*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdrs *proto; 296*5de6c855SPrzemek Kitszel int fld_cnt = 0; 297*5de6c855SPrzemek Kitszel int i; 298*5de6c855SPrzemek Kitszel 299*5de6c855SPrzemek Kitszel proto = &rule->proto_hdrs; 300*5de6c855SPrzemek Kitszel for (i = 0; i < proto->count; i++) { 301*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdr *hdr = &proto->proto_hdr[i]; 302*5de6c855SPrzemek Kitszel int ret; 303*5de6c855SPrzemek Kitszel 304*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_parse_flow_fld(hdr, conf, fld, &fld_cnt); 305*5de6c855SPrzemek Kitszel if (ret) 306*5de6c855SPrzemek Kitszel return ret; 307*5de6c855SPrzemek Kitszel } 308*5de6c855SPrzemek Kitszel 309*5de6c855SPrzemek Kitszel if (fld_cnt == 0) { 310*5de6c855SPrzemek Kitszel dev_dbg(dev, "Empty input set for VF %d\n", vf->vf_id); 311*5de6c855SPrzemek Kitszel return -EINVAL; 312*5de6c855SPrzemek Kitszel } 313*5de6c855SPrzemek Kitszel 314*5de6c855SPrzemek Kitszel for (i = 0; i < fld_cnt; i++) 315*5de6c855SPrzemek Kitszel ice_flow_set_fld(seg, fld[i], 316*5de6c855SPrzemek Kitszel ICE_FLOW_FLD_OFF_INVAL, 317*5de6c855SPrzemek Kitszel ICE_FLOW_FLD_OFF_INVAL, 318*5de6c855SPrzemek Kitszel ICE_FLOW_FLD_OFF_INVAL, false); 319*5de6c855SPrzemek Kitszel 320*5de6c855SPrzemek Kitszel return 0; 321*5de6c855SPrzemek Kitszel } 322*5de6c855SPrzemek Kitszel 323*5de6c855SPrzemek Kitszel /** 324*5de6c855SPrzemek Kitszel * ice_vc_fdir_set_flow_hdr - config the flow's packet segment header 325*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 326*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 327*5de6c855SPrzemek Kitszel * @seg: array of one or more packet segments that describe the flow 328*5de6c855SPrzemek Kitszel * 329*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 330*5de6c855SPrzemek Kitszel */ 331*5de6c855SPrzemek Kitszel static int 332*5de6c855SPrzemek Kitszel ice_vc_fdir_set_flow_hdr(struct ice_vf *vf, 333*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, 334*5de6c855SPrzemek Kitszel struct ice_flow_seg_info *seg) 335*5de6c855SPrzemek Kitszel { 336*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow = conf->input.flow_type; 337*5de6c855SPrzemek Kitszel enum ice_fdir_tunnel_type ttype = conf->ttype; 338*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 339*5de6c855SPrzemek Kitszel 340*5de6c855SPrzemek Kitszel switch (flow) { 341*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NON_IP_L2: 342*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ETH_NON_IP); 343*5de6c855SPrzemek Kitszel break; 344*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV3: 345*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV3 | 346*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 347*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 348*5de6c855SPrzemek Kitszel break; 349*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_ESP: 350*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ESP | 351*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 352*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 353*5de6c855SPrzemek Kitszel break; 354*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_AH: 355*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_AH | 356*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 357*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 358*5de6c855SPrzemek Kitszel break; 359*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_NAT_T_ESP: 360*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_NAT_T_ESP | 361*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 362*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 363*5de6c855SPrzemek Kitszel break; 364*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_PFCP_NODE: 365*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_NODE | 366*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 367*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 368*5de6c855SPrzemek Kitszel break; 369*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_PFCP_SESSION: 370*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_SESSION | 371*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 372*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 373*5de6c855SPrzemek Kitszel break; 374*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_OTHER: 375*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV4 | 376*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 377*5de6c855SPrzemek Kitszel break; 378*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_TCP: 379*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP | 380*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 381*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 382*5de6c855SPrzemek Kitszel break; 383*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_UDP: 384*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP | 385*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 386*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 387*5de6c855SPrzemek Kitszel break; 388*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_UDP: 389*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP: 390*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP: 391*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER: 392*5de6c855SPrzemek Kitszel if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU) { 393*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_IP | 394*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 395*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 396*5de6c855SPrzemek Kitszel } else if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_EH) { 397*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_EH | 398*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_GTPU_IP | 399*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 400*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 401*5de6c855SPrzemek Kitszel } else { 402*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid tunnel type 0x%x for VF %d\n", 403*5de6c855SPrzemek Kitszel flow, vf->vf_id); 404*5de6c855SPrzemek Kitszel return -EINVAL; 405*5de6c855SPrzemek Kitszel } 406*5de6c855SPrzemek Kitszel break; 407*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_SCTP: 408*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_SCTP | 409*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV4 | 410*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 411*5de6c855SPrzemek Kitszel break; 412*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV3: 413*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV3 | 414*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 415*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 416*5de6c855SPrzemek Kitszel break; 417*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_ESP: 418*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ESP | 419*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 420*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 421*5de6c855SPrzemek Kitszel break; 422*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_AH: 423*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_AH | 424*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 425*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 426*5de6c855SPrzemek Kitszel break; 427*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_NAT_T_ESP: 428*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_NAT_T_ESP | 429*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 430*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 431*5de6c855SPrzemek Kitszel break; 432*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_PFCP_NODE: 433*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_NODE | 434*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 435*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 436*5de6c855SPrzemek Kitszel break; 437*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_PFCP_SESSION: 438*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_SESSION | 439*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 440*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 441*5de6c855SPrzemek Kitszel break; 442*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_OTHER: 443*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV6 | 444*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 445*5de6c855SPrzemek Kitszel break; 446*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_TCP: 447*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP | 448*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 449*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 450*5de6c855SPrzemek Kitszel break; 451*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_UDP: 452*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP | 453*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 454*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 455*5de6c855SPrzemek Kitszel break; 456*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_SCTP: 457*5de6c855SPrzemek Kitszel ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_SCTP | 458*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV6 | 459*5de6c855SPrzemek Kitszel ICE_FLOW_SEG_HDR_IPV_OTHER); 460*5de6c855SPrzemek Kitszel break; 461*5de6c855SPrzemek Kitszel default: 462*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid flow type 0x%x for VF %d failed\n", 463*5de6c855SPrzemek Kitszel flow, vf->vf_id); 464*5de6c855SPrzemek Kitszel return -EINVAL; 465*5de6c855SPrzemek Kitszel } 466*5de6c855SPrzemek Kitszel 467*5de6c855SPrzemek Kitszel return 0; 468*5de6c855SPrzemek Kitszel } 469*5de6c855SPrzemek Kitszel 470*5de6c855SPrzemek Kitszel /** 471*5de6c855SPrzemek Kitszel * ice_vc_fdir_rem_prof - remove profile for this filter flow type 472*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 473*5de6c855SPrzemek Kitszel * @flow: filter flow type 474*5de6c855SPrzemek Kitszel * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter 475*5de6c855SPrzemek Kitszel */ 476*5de6c855SPrzemek Kitszel static void 477*5de6c855SPrzemek Kitszel ice_vc_fdir_rem_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, int tun) 478*5de6c855SPrzemek Kitszel { 479*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 480*5de6c855SPrzemek Kitszel struct ice_fd_hw_prof *vf_prof; 481*5de6c855SPrzemek Kitszel struct ice_pf *pf = vf->pf; 482*5de6c855SPrzemek Kitszel struct ice_vsi *vf_vsi; 483*5de6c855SPrzemek Kitszel struct device *dev; 484*5de6c855SPrzemek Kitszel struct ice_hw *hw; 485*5de6c855SPrzemek Kitszel u64 prof_id; 486*5de6c855SPrzemek Kitszel int i; 487*5de6c855SPrzemek Kitszel 488*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 489*5de6c855SPrzemek Kitszel hw = &pf->hw; 490*5de6c855SPrzemek Kitszel if (!fdir->fdir_prof || !fdir->fdir_prof[flow]) 491*5de6c855SPrzemek Kitszel return; 492*5de6c855SPrzemek Kitszel 493*5de6c855SPrzemek Kitszel vf_prof = fdir->fdir_prof[flow]; 494*5de6c855SPrzemek Kitszel prof_id = vf_prof->prof_id[tun]; 495*5de6c855SPrzemek Kitszel 496*5de6c855SPrzemek Kitszel vf_vsi = ice_get_vf_vsi(vf); 497*5de6c855SPrzemek Kitszel if (!vf_vsi) { 498*5de6c855SPrzemek Kitszel dev_dbg(dev, "NULL vf %d vsi pointer\n", vf->vf_id); 499*5de6c855SPrzemek Kitszel return; 500*5de6c855SPrzemek Kitszel } 501*5de6c855SPrzemek Kitszel 502*5de6c855SPrzemek Kitszel if (!fdir->prof_entry_cnt[flow][tun]) 503*5de6c855SPrzemek Kitszel return; 504*5de6c855SPrzemek Kitszel 505*5de6c855SPrzemek Kitszel for (i = 0; i < fdir->prof_entry_cnt[flow][tun]; i++) 506*5de6c855SPrzemek Kitszel if (vf_prof->entry_h[i][tun]) { 507*5de6c855SPrzemek Kitszel u16 vsi_num = ice_get_hw_vsi_num(hw, vf_prof->vsi_h[i]); 508*5de6c855SPrzemek Kitszel 509*5de6c855SPrzemek Kitszel ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof_id); 510*5de6c855SPrzemek Kitszel ice_flow_rem_entry(hw, ICE_BLK_FD, 511*5de6c855SPrzemek Kitszel vf_prof->entry_h[i][tun]); 512*5de6c855SPrzemek Kitszel vf_prof->entry_h[i][tun] = 0; 513*5de6c855SPrzemek Kitszel } 514*5de6c855SPrzemek Kitszel 515*5de6c855SPrzemek Kitszel ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id); 516*5de6c855SPrzemek Kitszel devm_kfree(dev, vf_prof->fdir_seg[tun]); 517*5de6c855SPrzemek Kitszel vf_prof->fdir_seg[tun] = NULL; 518*5de6c855SPrzemek Kitszel 519*5de6c855SPrzemek Kitszel for (i = 0; i < vf_prof->cnt; i++) 520*5de6c855SPrzemek Kitszel vf_prof->vsi_h[i] = 0; 521*5de6c855SPrzemek Kitszel 522*5de6c855SPrzemek Kitszel fdir->prof_entry_cnt[flow][tun] = 0; 523*5de6c855SPrzemek Kitszel } 524*5de6c855SPrzemek Kitszel 525*5de6c855SPrzemek Kitszel /** 526*5de6c855SPrzemek Kitszel * ice_vc_fdir_rem_prof_all - remove profile for this VF 527*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 528*5de6c855SPrzemek Kitszel */ 529*5de6c855SPrzemek Kitszel static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf) 530*5de6c855SPrzemek Kitszel { 531*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow; 532*5de6c855SPrzemek Kitszel 533*5de6c855SPrzemek Kitszel for (flow = ICE_FLTR_PTYPE_NONF_NONE; 534*5de6c855SPrzemek Kitszel flow < ICE_FLTR_PTYPE_MAX; flow++) { 535*5de6c855SPrzemek Kitszel ice_vc_fdir_rem_prof(vf, flow, 0); 536*5de6c855SPrzemek Kitszel ice_vc_fdir_rem_prof(vf, flow, 1); 537*5de6c855SPrzemek Kitszel } 538*5de6c855SPrzemek Kitszel } 539*5de6c855SPrzemek Kitszel 540*5de6c855SPrzemek Kitszel /** 541*5de6c855SPrzemek Kitszel * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR 542*5de6c855SPrzemek Kitszel * @fdir: pointer to the VF FDIR structure 543*5de6c855SPrzemek Kitszel */ 544*5de6c855SPrzemek Kitszel static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir) 545*5de6c855SPrzemek Kitszel { 546*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow; 547*5de6c855SPrzemek Kitszel 548*5de6c855SPrzemek Kitszel for (flow = ICE_FLTR_PTYPE_NONF_NONE; 549*5de6c855SPrzemek Kitszel flow < ICE_FLTR_PTYPE_MAX; flow++) { 550*5de6c855SPrzemek Kitszel fdir->fdir_fltr_cnt[flow][0] = 0; 551*5de6c855SPrzemek Kitszel fdir->fdir_fltr_cnt[flow][1] = 0; 552*5de6c855SPrzemek Kitszel } 553*5de6c855SPrzemek Kitszel 554*5de6c855SPrzemek Kitszel fdir->fdir_fltr_cnt_total = 0; 555*5de6c855SPrzemek Kitszel } 556*5de6c855SPrzemek Kitszel 557*5de6c855SPrzemek Kitszel /** 558*5de6c855SPrzemek Kitszel * ice_vc_fdir_has_prof_conflict 559*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 560*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 561*5de6c855SPrzemek Kitszel * 562*5de6c855SPrzemek Kitszel * Check if @conf has conflicting profile with existing profiles 563*5de6c855SPrzemek Kitszel * 564*5de6c855SPrzemek Kitszel * Return: true on success, and false on error. 565*5de6c855SPrzemek Kitszel */ 566*5de6c855SPrzemek Kitszel static bool 567*5de6c855SPrzemek Kitszel ice_vc_fdir_has_prof_conflict(struct ice_vf *vf, 568*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf) 569*5de6c855SPrzemek Kitszel { 570*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *desc; 571*5de6c855SPrzemek Kitszel 572*5de6c855SPrzemek Kitszel list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) { 573*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *existing_conf; 574*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow_type_a, flow_type_b; 575*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *a, *b; 576*5de6c855SPrzemek Kitszel 577*5de6c855SPrzemek Kitszel existing_conf = to_fltr_conf_from_desc(desc); 578*5de6c855SPrzemek Kitszel a = &existing_conf->input; 579*5de6c855SPrzemek Kitszel b = &conf->input; 580*5de6c855SPrzemek Kitszel flow_type_a = a->flow_type; 581*5de6c855SPrzemek Kitszel flow_type_b = b->flow_type; 582*5de6c855SPrzemek Kitszel 583*5de6c855SPrzemek Kitszel /* No need to compare two rules with different tunnel types or 584*5de6c855SPrzemek Kitszel * with the same protocol type. 585*5de6c855SPrzemek Kitszel */ 586*5de6c855SPrzemek Kitszel if (existing_conf->ttype != conf->ttype || 587*5de6c855SPrzemek Kitszel flow_type_a == flow_type_b) 588*5de6c855SPrzemek Kitszel continue; 589*5de6c855SPrzemek Kitszel 590*5de6c855SPrzemek Kitszel switch (flow_type_a) { 591*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_UDP: 592*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_TCP: 593*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_SCTP: 594*5de6c855SPrzemek Kitszel if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) 595*5de6c855SPrzemek Kitszel return true; 596*5de6c855SPrzemek Kitszel break; 597*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV4_OTHER: 598*5de6c855SPrzemek Kitszel if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_UDP || 599*5de6c855SPrzemek Kitszel flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_TCP || 600*5de6c855SPrzemek Kitszel flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) 601*5de6c855SPrzemek Kitszel return true; 602*5de6c855SPrzemek Kitszel break; 603*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_UDP: 604*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_TCP: 605*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_SCTP: 606*5de6c855SPrzemek Kitszel if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) 607*5de6c855SPrzemek Kitszel return true; 608*5de6c855SPrzemek Kitszel break; 609*5de6c855SPrzemek Kitszel case ICE_FLTR_PTYPE_NONF_IPV6_OTHER: 610*5de6c855SPrzemek Kitszel if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_UDP || 611*5de6c855SPrzemek Kitszel flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_TCP || 612*5de6c855SPrzemek Kitszel flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) 613*5de6c855SPrzemek Kitszel return true; 614*5de6c855SPrzemek Kitszel break; 615*5de6c855SPrzemek Kitszel default: 616*5de6c855SPrzemek Kitszel break; 617*5de6c855SPrzemek Kitszel } 618*5de6c855SPrzemek Kitszel } 619*5de6c855SPrzemek Kitszel 620*5de6c855SPrzemek Kitszel return false; 621*5de6c855SPrzemek Kitszel } 622*5de6c855SPrzemek Kitszel 623*5de6c855SPrzemek Kitszel /** 624*5de6c855SPrzemek Kitszel * ice_vc_fdir_write_flow_prof 625*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 626*5de6c855SPrzemek Kitszel * @flow: filter flow type 627*5de6c855SPrzemek Kitszel * @seg: array of one or more packet segments that describe the flow 628*5de6c855SPrzemek Kitszel * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter 629*5de6c855SPrzemek Kitszel * 630*5de6c855SPrzemek Kitszel * Write the flow's profile config and packet segment into the hardware 631*5de6c855SPrzemek Kitszel * 632*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 633*5de6c855SPrzemek Kitszel */ 634*5de6c855SPrzemek Kitszel static int 635*5de6c855SPrzemek Kitszel ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, 636*5de6c855SPrzemek Kitszel struct ice_flow_seg_info *seg, int tun) 637*5de6c855SPrzemek Kitszel { 638*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 639*5de6c855SPrzemek Kitszel struct ice_vsi *vf_vsi, *ctrl_vsi; 640*5de6c855SPrzemek Kitszel struct ice_flow_seg_info *old_seg; 641*5de6c855SPrzemek Kitszel struct ice_flow_prof *prof = NULL; 642*5de6c855SPrzemek Kitszel struct ice_fd_hw_prof *vf_prof; 643*5de6c855SPrzemek Kitszel struct device *dev; 644*5de6c855SPrzemek Kitszel struct ice_pf *pf; 645*5de6c855SPrzemek Kitszel struct ice_hw *hw; 646*5de6c855SPrzemek Kitszel u64 entry1_h = 0; 647*5de6c855SPrzemek Kitszel u64 entry2_h = 0; 648*5de6c855SPrzemek Kitszel int ret; 649*5de6c855SPrzemek Kitszel 650*5de6c855SPrzemek Kitszel pf = vf->pf; 651*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 652*5de6c855SPrzemek Kitszel hw = &pf->hw; 653*5de6c855SPrzemek Kitszel vf_vsi = ice_get_vf_vsi(vf); 654*5de6c855SPrzemek Kitszel if (!vf_vsi) 655*5de6c855SPrzemek Kitszel return -EINVAL; 656*5de6c855SPrzemek Kitszel 657*5de6c855SPrzemek Kitszel ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx]; 658*5de6c855SPrzemek Kitszel if (!ctrl_vsi) 659*5de6c855SPrzemek Kitszel return -EINVAL; 660*5de6c855SPrzemek Kitszel 661*5de6c855SPrzemek Kitszel vf_prof = fdir->fdir_prof[flow]; 662*5de6c855SPrzemek Kitszel old_seg = vf_prof->fdir_seg[tun]; 663*5de6c855SPrzemek Kitszel if (old_seg) { 664*5de6c855SPrzemek Kitszel if (!memcmp(old_seg, seg, sizeof(*seg))) { 665*5de6c855SPrzemek Kitszel dev_dbg(dev, "Duplicated profile for VF %d!\n", 666*5de6c855SPrzemek Kitszel vf->vf_id); 667*5de6c855SPrzemek Kitszel return -EEXIST; 668*5de6c855SPrzemek Kitszel } 669*5de6c855SPrzemek Kitszel 670*5de6c855SPrzemek Kitszel if (fdir->fdir_fltr_cnt[flow][tun]) { 671*5de6c855SPrzemek Kitszel ret = -EINVAL; 672*5de6c855SPrzemek Kitszel dev_dbg(dev, "Input set conflicts for VF %d\n", 673*5de6c855SPrzemek Kitszel vf->vf_id); 674*5de6c855SPrzemek Kitszel goto err_exit; 675*5de6c855SPrzemek Kitszel } 676*5de6c855SPrzemek Kitszel 677*5de6c855SPrzemek Kitszel /* remove previously allocated profile */ 678*5de6c855SPrzemek Kitszel ice_vc_fdir_rem_prof(vf, flow, tun); 679*5de6c855SPrzemek Kitszel } 680*5de6c855SPrzemek Kitszel 681*5de6c855SPrzemek Kitszel ret = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg, 682*5de6c855SPrzemek Kitszel tun + 1, false, &prof); 683*5de6c855SPrzemek Kitszel if (ret) { 684*5de6c855SPrzemek Kitszel dev_dbg(dev, "Could not add VSI flow 0x%x for VF %d\n", 685*5de6c855SPrzemek Kitszel flow, vf->vf_id); 686*5de6c855SPrzemek Kitszel goto err_exit; 687*5de6c855SPrzemek Kitszel } 688*5de6c855SPrzemek Kitszel 689*5de6c855SPrzemek Kitszel ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx, 690*5de6c855SPrzemek Kitszel vf_vsi->idx, ICE_FLOW_PRIO_NORMAL, 691*5de6c855SPrzemek Kitszel seg, &entry1_h); 692*5de6c855SPrzemek Kitszel if (ret) { 693*5de6c855SPrzemek Kitszel dev_dbg(dev, "Could not add flow 0x%x VSI entry for VF %d\n", 694*5de6c855SPrzemek Kitszel flow, vf->vf_id); 695*5de6c855SPrzemek Kitszel goto err_prof; 696*5de6c855SPrzemek Kitszel } 697*5de6c855SPrzemek Kitszel 698*5de6c855SPrzemek Kitszel ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx, 699*5de6c855SPrzemek Kitszel ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL, 700*5de6c855SPrzemek Kitszel seg, &entry2_h); 701*5de6c855SPrzemek Kitszel if (ret) { 702*5de6c855SPrzemek Kitszel dev_dbg(dev, 703*5de6c855SPrzemek Kitszel "Could not add flow 0x%x Ctrl VSI entry for VF %d\n", 704*5de6c855SPrzemek Kitszel flow, vf->vf_id); 705*5de6c855SPrzemek Kitszel goto err_entry_1; 706*5de6c855SPrzemek Kitszel } 707*5de6c855SPrzemek Kitszel 708*5de6c855SPrzemek Kitszel vf_prof->fdir_seg[tun] = seg; 709*5de6c855SPrzemek Kitszel vf_prof->cnt = 0; 710*5de6c855SPrzemek Kitszel fdir->prof_entry_cnt[flow][tun] = 0; 711*5de6c855SPrzemek Kitszel 712*5de6c855SPrzemek Kitszel vf_prof->entry_h[vf_prof->cnt][tun] = entry1_h; 713*5de6c855SPrzemek Kitszel vf_prof->vsi_h[vf_prof->cnt] = vf_vsi->idx; 714*5de6c855SPrzemek Kitszel vf_prof->cnt++; 715*5de6c855SPrzemek Kitszel fdir->prof_entry_cnt[flow][tun]++; 716*5de6c855SPrzemek Kitszel 717*5de6c855SPrzemek Kitszel vf_prof->entry_h[vf_prof->cnt][tun] = entry2_h; 718*5de6c855SPrzemek Kitszel vf_prof->vsi_h[vf_prof->cnt] = ctrl_vsi->idx; 719*5de6c855SPrzemek Kitszel vf_prof->cnt++; 720*5de6c855SPrzemek Kitszel fdir->prof_entry_cnt[flow][tun]++; 721*5de6c855SPrzemek Kitszel 722*5de6c855SPrzemek Kitszel vf_prof->prof_id[tun] = prof->id; 723*5de6c855SPrzemek Kitszel 724*5de6c855SPrzemek Kitszel return 0; 725*5de6c855SPrzemek Kitszel 726*5de6c855SPrzemek Kitszel err_entry_1: 727*5de6c855SPrzemek Kitszel ice_rem_prof_id_flow(hw, ICE_BLK_FD, 728*5de6c855SPrzemek Kitszel ice_get_hw_vsi_num(hw, vf_vsi->idx), prof->id); 729*5de6c855SPrzemek Kitszel ice_flow_rem_entry(hw, ICE_BLK_FD, entry1_h); 730*5de6c855SPrzemek Kitszel err_prof: 731*5de6c855SPrzemek Kitszel ice_flow_rem_prof(hw, ICE_BLK_FD, prof->id); 732*5de6c855SPrzemek Kitszel err_exit: 733*5de6c855SPrzemek Kitszel return ret; 734*5de6c855SPrzemek Kitszel } 735*5de6c855SPrzemek Kitszel 736*5de6c855SPrzemek Kitszel /** 737*5de6c855SPrzemek Kitszel * ice_vc_fdir_config_input_set 738*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 739*5de6c855SPrzemek Kitszel * @fltr: virtual channel add cmd buffer 740*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 741*5de6c855SPrzemek Kitszel * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter 742*5de6c855SPrzemek Kitszel * 743*5de6c855SPrzemek Kitszel * Config the input set type and value for virtual channel add msg buffer 744*5de6c855SPrzemek Kitszel * 745*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 746*5de6c855SPrzemek Kitszel */ 747*5de6c855SPrzemek Kitszel static int 748*5de6c855SPrzemek Kitszel ice_vc_fdir_config_input_set(struct ice_vf *vf, struct virtchnl_fdir_add *fltr, 749*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, int tun) 750*5de6c855SPrzemek Kitszel { 751*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input = &conf->input; 752*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 753*5de6c855SPrzemek Kitszel struct ice_flow_seg_info *seg; 754*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow; 755*5de6c855SPrzemek Kitszel int ret; 756*5de6c855SPrzemek Kitszel 757*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_has_prof_conflict(vf, conf); 758*5de6c855SPrzemek Kitszel if (ret) { 759*5de6c855SPrzemek Kitszel dev_dbg(dev, "Found flow profile conflict for VF %d\n", 760*5de6c855SPrzemek Kitszel vf->vf_id); 761*5de6c855SPrzemek Kitszel return ret; 762*5de6c855SPrzemek Kitszel } 763*5de6c855SPrzemek Kitszel 764*5de6c855SPrzemek Kitszel flow = input->flow_type; 765*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_alloc_prof(vf, flow); 766*5de6c855SPrzemek Kitszel if (ret) { 767*5de6c855SPrzemek Kitszel dev_dbg(dev, "Alloc flow prof for VF %d failed\n", vf->vf_id); 768*5de6c855SPrzemek Kitszel return ret; 769*5de6c855SPrzemek Kitszel } 770*5de6c855SPrzemek Kitszel 771*5de6c855SPrzemek Kitszel seg = devm_kzalloc(dev, sizeof(*seg), GFP_KERNEL); 772*5de6c855SPrzemek Kitszel if (!seg) 773*5de6c855SPrzemek Kitszel return -ENOMEM; 774*5de6c855SPrzemek Kitszel 775*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_set_flow_fld(vf, fltr, conf, seg); 776*5de6c855SPrzemek Kitszel if (ret) { 777*5de6c855SPrzemek Kitszel dev_dbg(dev, "Set flow field for VF %d failed\n", vf->vf_id); 778*5de6c855SPrzemek Kitszel goto err_exit; 779*5de6c855SPrzemek Kitszel } 780*5de6c855SPrzemek Kitszel 781*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_set_flow_hdr(vf, conf, seg); 782*5de6c855SPrzemek Kitszel if (ret) { 783*5de6c855SPrzemek Kitszel dev_dbg(dev, "Set flow hdr for VF %d failed\n", vf->vf_id); 784*5de6c855SPrzemek Kitszel goto err_exit; 785*5de6c855SPrzemek Kitszel } 786*5de6c855SPrzemek Kitszel 787*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_write_flow_prof(vf, flow, seg, tun); 788*5de6c855SPrzemek Kitszel if (ret == -EEXIST) { 789*5de6c855SPrzemek Kitszel devm_kfree(dev, seg); 790*5de6c855SPrzemek Kitszel } else if (ret) { 791*5de6c855SPrzemek Kitszel dev_dbg(dev, "Write flow profile for VF %d failed\n", 792*5de6c855SPrzemek Kitszel vf->vf_id); 793*5de6c855SPrzemek Kitszel goto err_exit; 794*5de6c855SPrzemek Kitszel } 795*5de6c855SPrzemek Kitszel 796*5de6c855SPrzemek Kitszel return 0; 797*5de6c855SPrzemek Kitszel 798*5de6c855SPrzemek Kitszel err_exit: 799*5de6c855SPrzemek Kitszel devm_kfree(dev, seg); 800*5de6c855SPrzemek Kitszel return ret; 801*5de6c855SPrzemek Kitszel } 802*5de6c855SPrzemek Kitszel 803*5de6c855SPrzemek Kitszel /** 804*5de6c855SPrzemek Kitszel * ice_vc_fdir_is_raw_flow - check if FDIR flow is raw (binary) 805*5de6c855SPrzemek Kitszel * @proto: virtchnl protocol headers 806*5de6c855SPrzemek Kitszel * 807*5de6c855SPrzemek Kitszel * Check if the FDIR rule is raw flow (protocol agnostic flow) or not. Note 808*5de6c855SPrzemek Kitszel * that common FDIR rule must have non-zero proto->count. Thus, we choose the 809*5de6c855SPrzemek Kitszel * tunnel_level and count of proto as the indicators. If both tunnel_level and 810*5de6c855SPrzemek Kitszel * count of proto are zero, this FDIR rule will be regarded as raw flow. 811*5de6c855SPrzemek Kitszel * 812*5de6c855SPrzemek Kitszel * Returns: true if headers describe raw flow, false otherwise. 813*5de6c855SPrzemek Kitszel */ 814*5de6c855SPrzemek Kitszel static bool 815*5de6c855SPrzemek Kitszel ice_vc_fdir_is_raw_flow(struct virtchnl_proto_hdrs *proto) 816*5de6c855SPrzemek Kitszel { 817*5de6c855SPrzemek Kitszel return (proto->tunnel_level == 0 && proto->count == 0); 818*5de6c855SPrzemek Kitszel } 819*5de6c855SPrzemek Kitszel 820*5de6c855SPrzemek Kitszel /** 821*5de6c855SPrzemek Kitszel * ice_vc_fdir_parse_raw - parse a virtchnl raw FDIR rule 822*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 823*5de6c855SPrzemek Kitszel * @proto: virtchnl protocol headers 824*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 825*5de6c855SPrzemek Kitszel * 826*5de6c855SPrzemek Kitszel * Parse the virtual channel filter's raw flow and store it in @conf 827*5de6c855SPrzemek Kitszel * 828*5de6c855SPrzemek Kitszel * Return: 0 on success or negative errno on failure. 829*5de6c855SPrzemek Kitszel */ 830*5de6c855SPrzemek Kitszel static int 831*5de6c855SPrzemek Kitszel ice_vc_fdir_parse_raw(struct ice_vf *vf, 832*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdrs *proto, 833*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf) 834*5de6c855SPrzemek Kitszel { 835*5de6c855SPrzemek Kitszel u8 *pkt_buf, *msk_buf __free(kfree) = NULL; 836*5de6c855SPrzemek Kitszel struct ice_parser_result rslt; 837*5de6c855SPrzemek Kitszel struct ice_pf *pf = vf->pf; 838*5de6c855SPrzemek Kitszel u16 pkt_len, udp_port = 0; 839*5de6c855SPrzemek Kitszel struct ice_parser *psr; 840*5de6c855SPrzemek Kitszel int status = -ENOMEM; 841*5de6c855SPrzemek Kitszel struct ice_hw *hw; 842*5de6c855SPrzemek Kitszel 843*5de6c855SPrzemek Kitszel pkt_len = proto->raw.pkt_len; 844*5de6c855SPrzemek Kitszel 845*5de6c855SPrzemek Kitszel if (!pkt_len || pkt_len > VIRTCHNL_MAX_SIZE_RAW_PACKET) 846*5de6c855SPrzemek Kitszel return -EINVAL; 847*5de6c855SPrzemek Kitszel 848*5de6c855SPrzemek Kitszel pkt_buf = kzalloc(pkt_len, GFP_KERNEL); 849*5de6c855SPrzemek Kitszel msk_buf = kzalloc(pkt_len, GFP_KERNEL); 850*5de6c855SPrzemek Kitszel 851*5de6c855SPrzemek Kitszel if (!pkt_buf || !msk_buf) 852*5de6c855SPrzemek Kitszel goto err_mem_alloc; 853*5de6c855SPrzemek Kitszel 854*5de6c855SPrzemek Kitszel memcpy(pkt_buf, proto->raw.spec, pkt_len); 855*5de6c855SPrzemek Kitszel memcpy(msk_buf, proto->raw.mask, pkt_len); 856*5de6c855SPrzemek Kitszel 857*5de6c855SPrzemek Kitszel hw = &pf->hw; 858*5de6c855SPrzemek Kitszel 859*5de6c855SPrzemek Kitszel /* Get raw profile info via Parser Lib */ 860*5de6c855SPrzemek Kitszel psr = ice_parser_create(hw); 861*5de6c855SPrzemek Kitszel if (IS_ERR(psr)) { 862*5de6c855SPrzemek Kitszel status = PTR_ERR(psr); 863*5de6c855SPrzemek Kitszel goto err_mem_alloc; 864*5de6c855SPrzemek Kitszel } 865*5de6c855SPrzemek Kitszel 866*5de6c855SPrzemek Kitszel ice_parser_dvm_set(psr, ice_is_dvm_ena(hw)); 867*5de6c855SPrzemek Kitszel 868*5de6c855SPrzemek Kitszel if (ice_get_open_tunnel_port(hw, &udp_port, TNL_VXLAN)) 869*5de6c855SPrzemek Kitszel ice_parser_vxlan_tunnel_set(psr, udp_port, true); 870*5de6c855SPrzemek Kitszel 871*5de6c855SPrzemek Kitszel status = ice_parser_run(psr, pkt_buf, pkt_len, &rslt); 872*5de6c855SPrzemek Kitszel if (status) 873*5de6c855SPrzemek Kitszel goto err_parser_destroy; 874*5de6c855SPrzemek Kitszel 875*5de6c855SPrzemek Kitszel if (hw->debug_mask & ICE_DBG_PARSER) 876*5de6c855SPrzemek Kitszel ice_parser_result_dump(hw, &rslt); 877*5de6c855SPrzemek Kitszel 878*5de6c855SPrzemek Kitszel conf->prof = kzalloc(sizeof(*conf->prof), GFP_KERNEL); 879*5de6c855SPrzemek Kitszel if (!conf->prof) { 880*5de6c855SPrzemek Kitszel status = -ENOMEM; 881*5de6c855SPrzemek Kitszel goto err_parser_destroy; 882*5de6c855SPrzemek Kitszel } 883*5de6c855SPrzemek Kitszel 884*5de6c855SPrzemek Kitszel status = ice_parser_profile_init(&rslt, pkt_buf, msk_buf, 885*5de6c855SPrzemek Kitszel pkt_len, ICE_BLK_FD, 886*5de6c855SPrzemek Kitszel conf->prof); 887*5de6c855SPrzemek Kitszel if (status) 888*5de6c855SPrzemek Kitszel goto err_parser_profile_init; 889*5de6c855SPrzemek Kitszel 890*5de6c855SPrzemek Kitszel if (hw->debug_mask & ICE_DBG_PARSER) 891*5de6c855SPrzemek Kitszel ice_parser_profile_dump(hw, conf->prof); 892*5de6c855SPrzemek Kitszel 893*5de6c855SPrzemek Kitszel /* Store raw flow info into @conf */ 894*5de6c855SPrzemek Kitszel conf->pkt_len = pkt_len; 895*5de6c855SPrzemek Kitszel conf->pkt_buf = pkt_buf; 896*5de6c855SPrzemek Kitszel conf->parser_ena = true; 897*5de6c855SPrzemek Kitszel 898*5de6c855SPrzemek Kitszel ice_parser_destroy(psr); 899*5de6c855SPrzemek Kitszel return 0; 900*5de6c855SPrzemek Kitszel 901*5de6c855SPrzemek Kitszel err_parser_profile_init: 902*5de6c855SPrzemek Kitszel kfree(conf->prof); 903*5de6c855SPrzemek Kitszel err_parser_destroy: 904*5de6c855SPrzemek Kitszel ice_parser_destroy(psr); 905*5de6c855SPrzemek Kitszel err_mem_alloc: 906*5de6c855SPrzemek Kitszel kfree(pkt_buf); 907*5de6c855SPrzemek Kitszel return status; 908*5de6c855SPrzemek Kitszel } 909*5de6c855SPrzemek Kitszel 910*5de6c855SPrzemek Kitszel /** 911*5de6c855SPrzemek Kitszel * ice_vc_fdir_parse_pattern 912*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 913*5de6c855SPrzemek Kitszel * @fltr: virtual channel add cmd buffer 914*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 915*5de6c855SPrzemek Kitszel * 916*5de6c855SPrzemek Kitszel * Parse the virtual channel filter's pattern and store them into conf 917*5de6c855SPrzemek Kitszel * 918*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 919*5de6c855SPrzemek Kitszel */ 920*5de6c855SPrzemek Kitszel static int 921*5de6c855SPrzemek Kitszel ice_vc_fdir_parse_pattern(struct ice_vf *vf, struct virtchnl_fdir_add *fltr, 922*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf) 923*5de6c855SPrzemek Kitszel { 924*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdrs *proto = &fltr->rule_cfg.proto_hdrs; 925*5de6c855SPrzemek Kitszel enum virtchnl_proto_hdr_type l3 = VIRTCHNL_PROTO_HDR_NONE; 926*5de6c855SPrzemek Kitszel enum virtchnl_proto_hdr_type l4 = VIRTCHNL_PROTO_HDR_NONE; 927*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 928*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input = &conf->input; 929*5de6c855SPrzemek Kitszel int i; 930*5de6c855SPrzemek Kitszel 931*5de6c855SPrzemek Kitszel if (proto->count > VIRTCHNL_MAX_NUM_PROTO_HDRS) { 932*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid protocol count:0x%x for VF %d\n", 933*5de6c855SPrzemek Kitszel proto->count, vf->vf_id); 934*5de6c855SPrzemek Kitszel return -EINVAL; 935*5de6c855SPrzemek Kitszel } 936*5de6c855SPrzemek Kitszel 937*5de6c855SPrzemek Kitszel /* For raw FDIR filters created by the parser */ 938*5de6c855SPrzemek Kitszel if (ice_vc_fdir_is_raw_flow(proto)) 939*5de6c855SPrzemek Kitszel return ice_vc_fdir_parse_raw(vf, proto, conf); 940*5de6c855SPrzemek Kitszel 941*5de6c855SPrzemek Kitszel for (i = 0; i < proto->count; i++) { 942*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdr *hdr = &proto->proto_hdr[i]; 943*5de6c855SPrzemek Kitszel struct ip_esp_hdr *esph; 944*5de6c855SPrzemek Kitszel struct ip_auth_hdr *ah; 945*5de6c855SPrzemek Kitszel struct sctphdr *sctph; 946*5de6c855SPrzemek Kitszel struct ipv6hdr *ip6h; 947*5de6c855SPrzemek Kitszel struct udphdr *udph; 948*5de6c855SPrzemek Kitszel struct tcphdr *tcph; 949*5de6c855SPrzemek Kitszel struct ethhdr *eth; 950*5de6c855SPrzemek Kitszel struct iphdr *iph; 951*5de6c855SPrzemek Kitszel u8 s_field; 952*5de6c855SPrzemek Kitszel u8 *rawh; 953*5de6c855SPrzemek Kitszel 954*5de6c855SPrzemek Kitszel switch (hdr->type) { 955*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_ETH: 956*5de6c855SPrzemek Kitszel eth = (struct ethhdr *)hdr->buffer; 957*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NON_IP_L2; 958*5de6c855SPrzemek Kitszel 959*5de6c855SPrzemek Kitszel if (hdr->field_selector) 960*5de6c855SPrzemek Kitszel input->ext_data.ether_type = eth->h_proto; 961*5de6c855SPrzemek Kitszel break; 962*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_IPV4: 963*5de6c855SPrzemek Kitszel iph = (struct iphdr *)hdr->buffer; 964*5de6c855SPrzemek Kitszel l3 = VIRTCHNL_PROTO_HDR_IPV4; 965*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER; 966*5de6c855SPrzemek Kitszel 967*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 968*5de6c855SPrzemek Kitszel input->ip.v4.src_ip = iph->saddr; 969*5de6c855SPrzemek Kitszel input->ip.v4.dst_ip = iph->daddr; 970*5de6c855SPrzemek Kitszel input->ip.v4.tos = iph->tos; 971*5de6c855SPrzemek Kitszel input->ip.v4.proto = iph->protocol; 972*5de6c855SPrzemek Kitszel } 973*5de6c855SPrzemek Kitszel break; 974*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_IPV6: 975*5de6c855SPrzemek Kitszel ip6h = (struct ipv6hdr *)hdr->buffer; 976*5de6c855SPrzemek Kitszel l3 = VIRTCHNL_PROTO_HDR_IPV6; 977*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER; 978*5de6c855SPrzemek Kitszel 979*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 980*5de6c855SPrzemek Kitszel memcpy(input->ip.v6.src_ip, 981*5de6c855SPrzemek Kitszel ip6h->saddr.in6_u.u6_addr8, 982*5de6c855SPrzemek Kitszel sizeof(ip6h->saddr)); 983*5de6c855SPrzemek Kitszel memcpy(input->ip.v6.dst_ip, 984*5de6c855SPrzemek Kitszel ip6h->daddr.in6_u.u6_addr8, 985*5de6c855SPrzemek Kitszel sizeof(ip6h->daddr)); 986*5de6c855SPrzemek Kitszel input->ip.v6.tc = ((u8)(ip6h->priority) << 4) | 987*5de6c855SPrzemek Kitszel (ip6h->flow_lbl[0] >> 4); 988*5de6c855SPrzemek Kitszel input->ip.v6.proto = ip6h->nexthdr; 989*5de6c855SPrzemek Kitszel } 990*5de6c855SPrzemek Kitszel break; 991*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_TCP: 992*5de6c855SPrzemek Kitszel tcph = (struct tcphdr *)hdr->buffer; 993*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 994*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP; 995*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 996*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP; 997*5de6c855SPrzemek Kitszel 998*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 999*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) { 1000*5de6c855SPrzemek Kitszel input->ip.v4.src_port = tcph->source; 1001*5de6c855SPrzemek Kitszel input->ip.v4.dst_port = tcph->dest; 1002*5de6c855SPrzemek Kitszel } else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) { 1003*5de6c855SPrzemek Kitszel input->ip.v6.src_port = tcph->source; 1004*5de6c855SPrzemek Kitszel input->ip.v6.dst_port = tcph->dest; 1005*5de6c855SPrzemek Kitszel } 1006*5de6c855SPrzemek Kitszel } 1007*5de6c855SPrzemek Kitszel break; 1008*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_UDP: 1009*5de6c855SPrzemek Kitszel udph = (struct udphdr *)hdr->buffer; 1010*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1011*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP; 1012*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1013*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP; 1014*5de6c855SPrzemek Kitszel 1015*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 1016*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) { 1017*5de6c855SPrzemek Kitszel input->ip.v4.src_port = udph->source; 1018*5de6c855SPrzemek Kitszel input->ip.v4.dst_port = udph->dest; 1019*5de6c855SPrzemek Kitszel } else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) { 1020*5de6c855SPrzemek Kitszel input->ip.v6.src_port = udph->source; 1021*5de6c855SPrzemek Kitszel input->ip.v6.dst_port = udph->dest; 1022*5de6c855SPrzemek Kitszel } 1023*5de6c855SPrzemek Kitszel } 1024*5de6c855SPrzemek Kitszel break; 1025*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_SCTP: 1026*5de6c855SPrzemek Kitszel sctph = (struct sctphdr *)hdr->buffer; 1027*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1028*5de6c855SPrzemek Kitszel input->flow_type = 1029*5de6c855SPrzemek Kitszel ICE_FLTR_PTYPE_NONF_IPV4_SCTP; 1030*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1031*5de6c855SPrzemek Kitszel input->flow_type = 1032*5de6c855SPrzemek Kitszel ICE_FLTR_PTYPE_NONF_IPV6_SCTP; 1033*5de6c855SPrzemek Kitszel 1034*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 1035*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) { 1036*5de6c855SPrzemek Kitszel input->ip.v4.src_port = sctph->source; 1037*5de6c855SPrzemek Kitszel input->ip.v4.dst_port = sctph->dest; 1038*5de6c855SPrzemek Kitszel } else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) { 1039*5de6c855SPrzemek Kitszel input->ip.v6.src_port = sctph->source; 1040*5de6c855SPrzemek Kitszel input->ip.v6.dst_port = sctph->dest; 1041*5de6c855SPrzemek Kitszel } 1042*5de6c855SPrzemek Kitszel } 1043*5de6c855SPrzemek Kitszel break; 1044*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_L2TPV3: 1045*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1046*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV3; 1047*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1048*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV3; 1049*5de6c855SPrzemek Kitszel 1050*5de6c855SPrzemek Kitszel if (hdr->field_selector) 1051*5de6c855SPrzemek Kitszel input->l2tpv3_data.session_id = *((__be32 *)hdr->buffer); 1052*5de6c855SPrzemek Kitszel break; 1053*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_ESP: 1054*5de6c855SPrzemek Kitszel esph = (struct ip_esp_hdr *)hdr->buffer; 1055*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && 1056*5de6c855SPrzemek Kitszel l4 == VIRTCHNL_PROTO_HDR_UDP) 1057*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_NAT_T_ESP; 1058*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && 1059*5de6c855SPrzemek Kitszel l4 == VIRTCHNL_PROTO_HDR_UDP) 1060*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_NAT_T_ESP; 1061*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && 1062*5de6c855SPrzemek Kitszel l4 == VIRTCHNL_PROTO_HDR_NONE) 1063*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_ESP; 1064*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && 1065*5de6c855SPrzemek Kitszel l4 == VIRTCHNL_PROTO_HDR_NONE) 1066*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_ESP; 1067*5de6c855SPrzemek Kitszel 1068*5de6c855SPrzemek Kitszel if (l4 == VIRTCHNL_PROTO_HDR_UDP) 1069*5de6c855SPrzemek Kitszel conf->inset_flag |= FDIR_INSET_FLAG_ESP_UDP; 1070*5de6c855SPrzemek Kitszel else 1071*5de6c855SPrzemek Kitszel conf->inset_flag |= FDIR_INSET_FLAG_ESP_IPSEC; 1072*5de6c855SPrzemek Kitszel 1073*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 1074*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1075*5de6c855SPrzemek Kitszel input->ip.v4.sec_parm_idx = esph->spi; 1076*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1077*5de6c855SPrzemek Kitszel input->ip.v6.sec_parm_idx = esph->spi; 1078*5de6c855SPrzemek Kitszel } 1079*5de6c855SPrzemek Kitszel break; 1080*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_AH: 1081*5de6c855SPrzemek Kitszel ah = (struct ip_auth_hdr *)hdr->buffer; 1082*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1083*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_AH; 1084*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1085*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_AH; 1086*5de6c855SPrzemek Kitszel 1087*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 1088*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1089*5de6c855SPrzemek Kitszel input->ip.v4.sec_parm_idx = ah->spi; 1090*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1091*5de6c855SPrzemek Kitszel input->ip.v6.sec_parm_idx = ah->spi; 1092*5de6c855SPrzemek Kitszel } 1093*5de6c855SPrzemek Kitszel break; 1094*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_PFCP: 1095*5de6c855SPrzemek Kitszel rawh = (u8 *)hdr->buffer; 1096*5de6c855SPrzemek Kitszel s_field = (rawh[0] >> PFCP_S_OFFSET) & PFCP_S_MASK; 1097*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && s_field == 0) 1098*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_PFCP_NODE; 1099*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && s_field == 1) 1100*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_PFCP_SESSION; 1101*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && s_field == 0) 1102*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_PFCP_NODE; 1103*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && s_field == 1) 1104*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_PFCP_SESSION; 1105*5de6c855SPrzemek Kitszel 1106*5de6c855SPrzemek Kitszel if (hdr->field_selector) { 1107*5de6c855SPrzemek Kitszel if (l3 == VIRTCHNL_PROTO_HDR_IPV4) 1108*5de6c855SPrzemek Kitszel input->ip.v4.dst_port = cpu_to_be16(PFCP_PORT_NR); 1109*5de6c855SPrzemek Kitszel else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) 1110*5de6c855SPrzemek Kitszel input->ip.v6.dst_port = cpu_to_be16(PFCP_PORT_NR); 1111*5de6c855SPrzemek Kitszel } 1112*5de6c855SPrzemek Kitszel break; 1113*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_GTPU_IP: 1114*5de6c855SPrzemek Kitszel rawh = (u8 *)hdr->buffer; 1115*5de6c855SPrzemek Kitszel input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER; 1116*5de6c855SPrzemek Kitszel 1117*5de6c855SPrzemek Kitszel if (hdr->field_selector) 1118*5de6c855SPrzemek Kitszel input->gtpu_data.teid = *(__be32 *)(&rawh[GTPU_TEID_OFFSET]); 1119*5de6c855SPrzemek Kitszel conf->ttype = ICE_FDIR_TUNNEL_TYPE_GTPU; 1120*5de6c855SPrzemek Kitszel break; 1121*5de6c855SPrzemek Kitszel case VIRTCHNL_PROTO_HDR_GTPU_EH: 1122*5de6c855SPrzemek Kitszel rawh = (u8 *)hdr->buffer; 1123*5de6c855SPrzemek Kitszel 1124*5de6c855SPrzemek Kitszel if (hdr->field_selector) 1125*5de6c855SPrzemek Kitszel input->gtpu_data.qfi = rawh[GTPU_EH_QFI_OFFSET] & GTPU_EH_QFI_MASK; 1126*5de6c855SPrzemek Kitszel conf->ttype = ICE_FDIR_TUNNEL_TYPE_GTPU_EH; 1127*5de6c855SPrzemek Kitszel break; 1128*5de6c855SPrzemek Kitszel default: 1129*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid header type 0x:%x for VF %d\n", 1130*5de6c855SPrzemek Kitszel hdr->type, vf->vf_id); 1131*5de6c855SPrzemek Kitszel return -EINVAL; 1132*5de6c855SPrzemek Kitszel } 1133*5de6c855SPrzemek Kitszel } 1134*5de6c855SPrzemek Kitszel 1135*5de6c855SPrzemek Kitszel return 0; 1136*5de6c855SPrzemek Kitszel } 1137*5de6c855SPrzemek Kitszel 1138*5de6c855SPrzemek Kitszel /** 1139*5de6c855SPrzemek Kitszel * ice_vc_fdir_parse_action 1140*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1141*5de6c855SPrzemek Kitszel * @fltr: virtual channel add cmd buffer 1142*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1143*5de6c855SPrzemek Kitszel * 1144*5de6c855SPrzemek Kitszel * Parse the virtual channel filter's action and store them into conf 1145*5de6c855SPrzemek Kitszel * 1146*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1147*5de6c855SPrzemek Kitszel */ 1148*5de6c855SPrzemek Kitszel static int 1149*5de6c855SPrzemek Kitszel ice_vc_fdir_parse_action(struct ice_vf *vf, struct virtchnl_fdir_add *fltr, 1150*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf) 1151*5de6c855SPrzemek Kitszel { 1152*5de6c855SPrzemek Kitszel struct virtchnl_filter_action_set *as = &fltr->rule_cfg.action_set; 1153*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 1154*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input = &conf->input; 1155*5de6c855SPrzemek Kitszel u32 dest_num = 0; 1156*5de6c855SPrzemek Kitszel u32 mark_num = 0; 1157*5de6c855SPrzemek Kitszel int i; 1158*5de6c855SPrzemek Kitszel 1159*5de6c855SPrzemek Kitszel if (as->count > VIRTCHNL_MAX_NUM_ACTIONS) { 1160*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid action numbers:0x%x for VF %d\n", 1161*5de6c855SPrzemek Kitszel as->count, vf->vf_id); 1162*5de6c855SPrzemek Kitszel return -EINVAL; 1163*5de6c855SPrzemek Kitszel } 1164*5de6c855SPrzemek Kitszel 1165*5de6c855SPrzemek Kitszel for (i = 0; i < as->count; i++) { 1166*5de6c855SPrzemek Kitszel struct virtchnl_filter_action *action = &as->actions[i]; 1167*5de6c855SPrzemek Kitszel 1168*5de6c855SPrzemek Kitszel switch (action->type) { 1169*5de6c855SPrzemek Kitszel case VIRTCHNL_ACTION_PASSTHRU: 1170*5de6c855SPrzemek Kitszel dest_num++; 1171*5de6c855SPrzemek Kitszel input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER; 1172*5de6c855SPrzemek Kitszel break; 1173*5de6c855SPrzemek Kitszel case VIRTCHNL_ACTION_DROP: 1174*5de6c855SPrzemek Kitszel dest_num++; 1175*5de6c855SPrzemek Kitszel input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DROP_PKT; 1176*5de6c855SPrzemek Kitszel break; 1177*5de6c855SPrzemek Kitszel case VIRTCHNL_ACTION_QUEUE: 1178*5de6c855SPrzemek Kitszel dest_num++; 1179*5de6c855SPrzemek Kitszel input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX; 1180*5de6c855SPrzemek Kitszel input->q_index = action->act_conf.queue.index; 1181*5de6c855SPrzemek Kitszel break; 1182*5de6c855SPrzemek Kitszel case VIRTCHNL_ACTION_Q_REGION: 1183*5de6c855SPrzemek Kitszel dest_num++; 1184*5de6c855SPrzemek Kitszel input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP; 1185*5de6c855SPrzemek Kitszel input->q_index = action->act_conf.queue.index; 1186*5de6c855SPrzemek Kitszel input->q_region = action->act_conf.queue.region; 1187*5de6c855SPrzemek Kitszel break; 1188*5de6c855SPrzemek Kitszel case VIRTCHNL_ACTION_MARK: 1189*5de6c855SPrzemek Kitszel mark_num++; 1190*5de6c855SPrzemek Kitszel input->fltr_id = action->act_conf.mark_id; 1191*5de6c855SPrzemek Kitszel input->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_THREE; 1192*5de6c855SPrzemek Kitszel break; 1193*5de6c855SPrzemek Kitszel default: 1194*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid action type:0x%x for VF %d\n", 1195*5de6c855SPrzemek Kitszel action->type, vf->vf_id); 1196*5de6c855SPrzemek Kitszel return -EINVAL; 1197*5de6c855SPrzemek Kitszel } 1198*5de6c855SPrzemek Kitszel } 1199*5de6c855SPrzemek Kitszel 1200*5de6c855SPrzemek Kitszel if (dest_num == 0 || dest_num >= 2) { 1201*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid destination action for VF %d\n", 1202*5de6c855SPrzemek Kitszel vf->vf_id); 1203*5de6c855SPrzemek Kitszel return -EINVAL; 1204*5de6c855SPrzemek Kitszel } 1205*5de6c855SPrzemek Kitszel 1206*5de6c855SPrzemek Kitszel if (mark_num >= 2) { 1207*5de6c855SPrzemek Kitszel dev_dbg(dev, "Too many mark actions for VF %d\n", vf->vf_id); 1208*5de6c855SPrzemek Kitszel return -EINVAL; 1209*5de6c855SPrzemek Kitszel } 1210*5de6c855SPrzemek Kitszel 1211*5de6c855SPrzemek Kitszel return 0; 1212*5de6c855SPrzemek Kitszel } 1213*5de6c855SPrzemek Kitszel 1214*5de6c855SPrzemek Kitszel /** 1215*5de6c855SPrzemek Kitszel * ice_vc_validate_fdir_fltr - validate the virtual channel filter 1216*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1217*5de6c855SPrzemek Kitszel * @fltr: virtual channel add cmd buffer 1218*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1219*5de6c855SPrzemek Kitszel * 1220*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1221*5de6c855SPrzemek Kitszel */ 1222*5de6c855SPrzemek Kitszel static int 1223*5de6c855SPrzemek Kitszel ice_vc_validate_fdir_fltr(struct ice_vf *vf, struct virtchnl_fdir_add *fltr, 1224*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf) 1225*5de6c855SPrzemek Kitszel { 1226*5de6c855SPrzemek Kitszel struct virtchnl_proto_hdrs *proto = &fltr->rule_cfg.proto_hdrs; 1227*5de6c855SPrzemek Kitszel int ret; 1228*5de6c855SPrzemek Kitszel 1229*5de6c855SPrzemek Kitszel /* For raw FDIR filters created by the parser */ 1230*5de6c855SPrzemek Kitszel if (!ice_vc_fdir_is_raw_flow(proto)) 1231*5de6c855SPrzemek Kitszel if (!ice_vc_validate_pattern(vf, proto)) 1232*5de6c855SPrzemek Kitszel return -EINVAL; 1233*5de6c855SPrzemek Kitszel 1234*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_parse_pattern(vf, fltr, conf); 1235*5de6c855SPrzemek Kitszel if (ret) 1236*5de6c855SPrzemek Kitszel return ret; 1237*5de6c855SPrzemek Kitszel 1238*5de6c855SPrzemek Kitszel return ice_vc_fdir_parse_action(vf, fltr, conf); 1239*5de6c855SPrzemek Kitszel } 1240*5de6c855SPrzemek Kitszel 1241*5de6c855SPrzemek Kitszel /** 1242*5de6c855SPrzemek Kitszel * ice_vc_fdir_comp_rules - compare if two filter rules have the same value 1243*5de6c855SPrzemek Kitszel * @conf_a: FDIR configuration for filter a 1244*5de6c855SPrzemek Kitszel * @conf_b: FDIR configuration for filter b 1245*5de6c855SPrzemek Kitszel * 1246*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1247*5de6c855SPrzemek Kitszel */ 1248*5de6c855SPrzemek Kitszel static bool 1249*5de6c855SPrzemek Kitszel ice_vc_fdir_comp_rules(struct virtchnl_fdir_fltr_conf *conf_a, 1250*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf_b) 1251*5de6c855SPrzemek Kitszel { 1252*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *a = &conf_a->input; 1253*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *b = &conf_b->input; 1254*5de6c855SPrzemek Kitszel 1255*5de6c855SPrzemek Kitszel if (conf_a->ttype != conf_b->ttype) 1256*5de6c855SPrzemek Kitszel return false; 1257*5de6c855SPrzemek Kitszel if (a->flow_type != b->flow_type) 1258*5de6c855SPrzemek Kitszel return false; 1259*5de6c855SPrzemek Kitszel if (memcmp(&a->ip, &b->ip, sizeof(a->ip))) 1260*5de6c855SPrzemek Kitszel return false; 1261*5de6c855SPrzemek Kitszel if (memcmp(&a->mask, &b->mask, sizeof(a->mask))) 1262*5de6c855SPrzemek Kitszel return false; 1263*5de6c855SPrzemek Kitszel if (memcmp(&a->gtpu_data, &b->gtpu_data, sizeof(a->gtpu_data))) 1264*5de6c855SPrzemek Kitszel return false; 1265*5de6c855SPrzemek Kitszel if (memcmp(&a->gtpu_mask, &b->gtpu_mask, sizeof(a->gtpu_mask))) 1266*5de6c855SPrzemek Kitszel return false; 1267*5de6c855SPrzemek Kitszel if (memcmp(&a->l2tpv3_data, &b->l2tpv3_data, sizeof(a->l2tpv3_data))) 1268*5de6c855SPrzemek Kitszel return false; 1269*5de6c855SPrzemek Kitszel if (memcmp(&a->l2tpv3_mask, &b->l2tpv3_mask, sizeof(a->l2tpv3_mask))) 1270*5de6c855SPrzemek Kitszel return false; 1271*5de6c855SPrzemek Kitszel if (memcmp(&a->ext_data, &b->ext_data, sizeof(a->ext_data))) 1272*5de6c855SPrzemek Kitszel return false; 1273*5de6c855SPrzemek Kitszel if (memcmp(&a->ext_mask, &b->ext_mask, sizeof(a->ext_mask))) 1274*5de6c855SPrzemek Kitszel return false; 1275*5de6c855SPrzemek Kitszel 1276*5de6c855SPrzemek Kitszel return true; 1277*5de6c855SPrzemek Kitszel } 1278*5de6c855SPrzemek Kitszel 1279*5de6c855SPrzemek Kitszel /** 1280*5de6c855SPrzemek Kitszel * ice_vc_fdir_is_dup_fltr 1281*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1282*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1283*5de6c855SPrzemek Kitszel * 1284*5de6c855SPrzemek Kitszel * Check if there is duplicated rule with same conf value 1285*5de6c855SPrzemek Kitszel * 1286*5de6c855SPrzemek Kitszel * Return: 0 true success, and false on error. 1287*5de6c855SPrzemek Kitszel */ 1288*5de6c855SPrzemek Kitszel static bool 1289*5de6c855SPrzemek Kitszel ice_vc_fdir_is_dup_fltr(struct ice_vf *vf, struct virtchnl_fdir_fltr_conf *conf) 1290*5de6c855SPrzemek Kitszel { 1291*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *desc; 1292*5de6c855SPrzemek Kitszel bool ret; 1293*5de6c855SPrzemek Kitszel 1294*5de6c855SPrzemek Kitszel list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) { 1295*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *node = 1296*5de6c855SPrzemek Kitszel to_fltr_conf_from_desc(desc); 1297*5de6c855SPrzemek Kitszel 1298*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_comp_rules(node, conf); 1299*5de6c855SPrzemek Kitszel if (ret) 1300*5de6c855SPrzemek Kitszel return true; 1301*5de6c855SPrzemek Kitszel } 1302*5de6c855SPrzemek Kitszel 1303*5de6c855SPrzemek Kitszel return false; 1304*5de6c855SPrzemek Kitszel } 1305*5de6c855SPrzemek Kitszel 1306*5de6c855SPrzemek Kitszel /** 1307*5de6c855SPrzemek Kitszel * ice_vc_fdir_insert_entry 1308*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1309*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1310*5de6c855SPrzemek Kitszel * @id: pointer to ID value allocated by driver 1311*5de6c855SPrzemek Kitszel * 1312*5de6c855SPrzemek Kitszel * Insert FDIR conf entry into list and allocate ID for this filter 1313*5de6c855SPrzemek Kitszel * 1314*5de6c855SPrzemek Kitszel * Return: 0 true success, and other on error. 1315*5de6c855SPrzemek Kitszel */ 1316*5de6c855SPrzemek Kitszel static int 1317*5de6c855SPrzemek Kitszel ice_vc_fdir_insert_entry(struct ice_vf *vf, 1318*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, u32 *id) 1319*5de6c855SPrzemek Kitszel { 1320*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input = &conf->input; 1321*5de6c855SPrzemek Kitszel int i; 1322*5de6c855SPrzemek Kitszel 1323*5de6c855SPrzemek Kitszel /* alloc ID corresponding with conf */ 1324*5de6c855SPrzemek Kitszel i = idr_alloc(&vf->fdir.fdir_rule_idr, conf, 0, 1325*5de6c855SPrzemek Kitszel ICE_FDIR_MAX_FLTRS, GFP_KERNEL); 1326*5de6c855SPrzemek Kitszel if (i < 0) 1327*5de6c855SPrzemek Kitszel return -EINVAL; 1328*5de6c855SPrzemek Kitszel *id = i; 1329*5de6c855SPrzemek Kitszel 1330*5de6c855SPrzemek Kitszel list_add(&input->fltr_node, &vf->fdir.fdir_rule_list); 1331*5de6c855SPrzemek Kitszel return 0; 1332*5de6c855SPrzemek Kitszel } 1333*5de6c855SPrzemek Kitszel 1334*5de6c855SPrzemek Kitszel /** 1335*5de6c855SPrzemek Kitszel * ice_vc_fdir_remove_entry - remove FDIR conf entry by ID value 1336*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1337*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1338*5de6c855SPrzemek Kitszel * @id: filter rule's ID 1339*5de6c855SPrzemek Kitszel */ 1340*5de6c855SPrzemek Kitszel static void 1341*5de6c855SPrzemek Kitszel ice_vc_fdir_remove_entry(struct ice_vf *vf, 1342*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, u32 id) 1343*5de6c855SPrzemek Kitszel { 1344*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input = &conf->input; 1345*5de6c855SPrzemek Kitszel 1346*5de6c855SPrzemek Kitszel idr_remove(&vf->fdir.fdir_rule_idr, id); 1347*5de6c855SPrzemek Kitszel list_del(&input->fltr_node); 1348*5de6c855SPrzemek Kitszel } 1349*5de6c855SPrzemek Kitszel 1350*5de6c855SPrzemek Kitszel /** 1351*5de6c855SPrzemek Kitszel * ice_vc_fdir_lookup_entry - lookup FDIR conf entry by ID value 1352*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1353*5de6c855SPrzemek Kitszel * @id: filter rule's ID 1354*5de6c855SPrzemek Kitszel * 1355*5de6c855SPrzemek Kitszel * Return: NULL on error, and other on success. 1356*5de6c855SPrzemek Kitszel */ 1357*5de6c855SPrzemek Kitszel static struct virtchnl_fdir_fltr_conf * 1358*5de6c855SPrzemek Kitszel ice_vc_fdir_lookup_entry(struct ice_vf *vf, u32 id) 1359*5de6c855SPrzemek Kitszel { 1360*5de6c855SPrzemek Kitszel return idr_find(&vf->fdir.fdir_rule_idr, id); 1361*5de6c855SPrzemek Kitszel } 1362*5de6c855SPrzemek Kitszel 1363*5de6c855SPrzemek Kitszel /** 1364*5de6c855SPrzemek Kitszel * ice_vc_fdir_flush_entry - remove all FDIR conf entry 1365*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1366*5de6c855SPrzemek Kitszel */ 1367*5de6c855SPrzemek Kitszel static void ice_vc_fdir_flush_entry(struct ice_vf *vf) 1368*5de6c855SPrzemek Kitszel { 1369*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf; 1370*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *desc, *temp; 1371*5de6c855SPrzemek Kitszel 1372*5de6c855SPrzemek Kitszel list_for_each_entry_safe(desc, temp, 1373*5de6c855SPrzemek Kitszel &vf->fdir.fdir_rule_list, fltr_node) { 1374*5de6c855SPrzemek Kitszel conf = to_fltr_conf_from_desc(desc); 1375*5de6c855SPrzemek Kitszel list_del(&desc->fltr_node); 1376*5de6c855SPrzemek Kitszel devm_kfree(ice_pf_to_dev(vf->pf), conf); 1377*5de6c855SPrzemek Kitszel } 1378*5de6c855SPrzemek Kitszel } 1379*5de6c855SPrzemek Kitszel 1380*5de6c855SPrzemek Kitszel /** 1381*5de6c855SPrzemek Kitszel * ice_vc_fdir_write_fltr - write filter rule into hardware 1382*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1383*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1384*5de6c855SPrzemek Kitszel * @add: true implies add rule, false implies del rules 1385*5de6c855SPrzemek Kitszel * @is_tun: false implies non-tunnel type filter, true implies tunnel filter 1386*5de6c855SPrzemek Kitszel * 1387*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1388*5de6c855SPrzemek Kitszel */ 1389*5de6c855SPrzemek Kitszel static int ice_vc_fdir_write_fltr(struct ice_vf *vf, 1390*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, 1391*5de6c855SPrzemek Kitszel bool add, bool is_tun) 1392*5de6c855SPrzemek Kitszel { 1393*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input = &conf->input; 1394*5de6c855SPrzemek Kitszel struct ice_vsi *vsi, *ctrl_vsi; 1395*5de6c855SPrzemek Kitszel struct ice_fltr_desc desc; 1396*5de6c855SPrzemek Kitszel struct device *dev; 1397*5de6c855SPrzemek Kitszel struct ice_pf *pf; 1398*5de6c855SPrzemek Kitszel struct ice_hw *hw; 1399*5de6c855SPrzemek Kitszel int ret; 1400*5de6c855SPrzemek Kitszel u8 *pkt; 1401*5de6c855SPrzemek Kitszel 1402*5de6c855SPrzemek Kitszel pf = vf->pf; 1403*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 1404*5de6c855SPrzemek Kitszel hw = &pf->hw; 1405*5de6c855SPrzemek Kitszel vsi = ice_get_vf_vsi(vf); 1406*5de6c855SPrzemek Kitszel if (!vsi) { 1407*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid vsi for VF %d\n", vf->vf_id); 1408*5de6c855SPrzemek Kitszel return -EINVAL; 1409*5de6c855SPrzemek Kitszel } 1410*5de6c855SPrzemek Kitszel 1411*5de6c855SPrzemek Kitszel input->dest_vsi = vsi->idx; 1412*5de6c855SPrzemek Kitszel input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW; 1413*5de6c855SPrzemek Kitszel 1414*5de6c855SPrzemek Kitszel ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx]; 1415*5de6c855SPrzemek Kitszel if (!ctrl_vsi) { 1416*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid ctrl_vsi for VF %d\n", vf->vf_id); 1417*5de6c855SPrzemek Kitszel return -EINVAL; 1418*5de6c855SPrzemek Kitszel } 1419*5de6c855SPrzemek Kitszel 1420*5de6c855SPrzemek Kitszel pkt = devm_kzalloc(dev, ICE_FDIR_MAX_RAW_PKT_SIZE, GFP_KERNEL); 1421*5de6c855SPrzemek Kitszel if (!pkt) 1422*5de6c855SPrzemek Kitszel return -ENOMEM; 1423*5de6c855SPrzemek Kitszel 1424*5de6c855SPrzemek Kitszel ice_fdir_get_prgm_desc(hw, input, &desc, add); 1425*5de6c855SPrzemek Kitszel if (conf->parser_ena) { 1426*5de6c855SPrzemek Kitszel memcpy(pkt, conf->pkt_buf, conf->pkt_len); 1427*5de6c855SPrzemek Kitszel } else { 1428*5de6c855SPrzemek Kitszel ret = ice_fdir_get_gen_prgm_pkt(hw, input, pkt, false, is_tun); 1429*5de6c855SPrzemek Kitszel if (ret) { 1430*5de6c855SPrzemek Kitszel dev_dbg(dev, "Gen training pkt for VF %d ptype %d failed\n", 1431*5de6c855SPrzemek Kitszel vf->vf_id, input->flow_type); 1432*5de6c855SPrzemek Kitszel goto err_free_pkt; 1433*5de6c855SPrzemek Kitszel } 1434*5de6c855SPrzemek Kitszel } 1435*5de6c855SPrzemek Kitszel 1436*5de6c855SPrzemek Kitszel ret = ice_prgm_fdir_fltr(ctrl_vsi, &desc, pkt); 1437*5de6c855SPrzemek Kitszel if (ret) 1438*5de6c855SPrzemek Kitszel goto err_free_pkt; 1439*5de6c855SPrzemek Kitszel 1440*5de6c855SPrzemek Kitszel return 0; 1441*5de6c855SPrzemek Kitszel 1442*5de6c855SPrzemek Kitszel err_free_pkt: 1443*5de6c855SPrzemek Kitszel devm_kfree(dev, pkt); 1444*5de6c855SPrzemek Kitszel return ret; 1445*5de6c855SPrzemek Kitszel } 1446*5de6c855SPrzemek Kitszel 1447*5de6c855SPrzemek Kitszel /** 1448*5de6c855SPrzemek Kitszel * ice_vf_fdir_timer - FDIR program waiting timer interrupt handler 1449*5de6c855SPrzemek Kitszel * @t: pointer to timer_list 1450*5de6c855SPrzemek Kitszel */ 1451*5de6c855SPrzemek Kitszel static void ice_vf_fdir_timer(struct timer_list *t) 1452*5de6c855SPrzemek Kitszel { 1453*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx_irq = timer_container_of(ctx_irq, t, 1454*5de6c855SPrzemek Kitszel rx_tmr); 1455*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx_done; 1456*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir; 1457*5de6c855SPrzemek Kitszel unsigned long flags; 1458*5de6c855SPrzemek Kitszel struct ice_vf *vf; 1459*5de6c855SPrzemek Kitszel struct ice_pf *pf; 1460*5de6c855SPrzemek Kitszel 1461*5de6c855SPrzemek Kitszel fdir = container_of(ctx_irq, struct ice_vf_fdir, ctx_irq); 1462*5de6c855SPrzemek Kitszel vf = container_of(fdir, struct ice_vf, fdir); 1463*5de6c855SPrzemek Kitszel ctx_done = &fdir->ctx_done; 1464*5de6c855SPrzemek Kitszel pf = vf->pf; 1465*5de6c855SPrzemek Kitszel spin_lock_irqsave(&fdir->ctx_lock, flags); 1466*5de6c855SPrzemek Kitszel if (!(ctx_irq->flags & ICE_VF_FDIR_CTX_VALID)) { 1467*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&fdir->ctx_lock, flags); 1468*5de6c855SPrzemek Kitszel WARN_ON_ONCE(1); 1469*5de6c855SPrzemek Kitszel return; 1470*5de6c855SPrzemek Kitszel } 1471*5de6c855SPrzemek Kitszel 1472*5de6c855SPrzemek Kitszel ctx_irq->flags &= ~ICE_VF_FDIR_CTX_VALID; 1473*5de6c855SPrzemek Kitszel 1474*5de6c855SPrzemek Kitszel ctx_done->flags |= ICE_VF_FDIR_CTX_VALID; 1475*5de6c855SPrzemek Kitszel ctx_done->conf = ctx_irq->conf; 1476*5de6c855SPrzemek Kitszel ctx_done->stat = ICE_FDIR_CTX_TIMEOUT; 1477*5de6c855SPrzemek Kitszel ctx_done->v_opcode = ctx_irq->v_opcode; 1478*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&fdir->ctx_lock, flags); 1479*5de6c855SPrzemek Kitszel 1480*5de6c855SPrzemek Kitszel set_bit(ICE_FD_VF_FLUSH_CTX, pf->state); 1481*5de6c855SPrzemek Kitszel ice_service_task_schedule(pf); 1482*5de6c855SPrzemek Kitszel } 1483*5de6c855SPrzemek Kitszel 1484*5de6c855SPrzemek Kitszel /** 1485*5de6c855SPrzemek Kitszel * ice_vc_fdir_irq_handler - ctrl_vsi Rx queue interrupt handler 1486*5de6c855SPrzemek Kitszel * @ctrl_vsi: pointer to a VF's CTRL VSI 1487*5de6c855SPrzemek Kitszel * @rx_desc: pointer to FDIR Rx queue descriptor 1488*5de6c855SPrzemek Kitszel */ 1489*5de6c855SPrzemek Kitszel void 1490*5de6c855SPrzemek Kitszel ice_vc_fdir_irq_handler(struct ice_vsi *ctrl_vsi, 1491*5de6c855SPrzemek Kitszel union ice_32b_rx_flex_desc *rx_desc) 1492*5de6c855SPrzemek Kitszel { 1493*5de6c855SPrzemek Kitszel struct ice_pf *pf = ctrl_vsi->back; 1494*5de6c855SPrzemek Kitszel struct ice_vf *vf = ctrl_vsi->vf; 1495*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx_done; 1496*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx_irq; 1497*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir; 1498*5de6c855SPrzemek Kitszel unsigned long flags; 1499*5de6c855SPrzemek Kitszel struct device *dev; 1500*5de6c855SPrzemek Kitszel int ret; 1501*5de6c855SPrzemek Kitszel 1502*5de6c855SPrzemek Kitszel if (WARN_ON(!vf)) 1503*5de6c855SPrzemek Kitszel return; 1504*5de6c855SPrzemek Kitszel 1505*5de6c855SPrzemek Kitszel fdir = &vf->fdir; 1506*5de6c855SPrzemek Kitszel ctx_done = &fdir->ctx_done; 1507*5de6c855SPrzemek Kitszel ctx_irq = &fdir->ctx_irq; 1508*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 1509*5de6c855SPrzemek Kitszel spin_lock_irqsave(&fdir->ctx_lock, flags); 1510*5de6c855SPrzemek Kitszel if (!(ctx_irq->flags & ICE_VF_FDIR_CTX_VALID)) { 1511*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&fdir->ctx_lock, flags); 1512*5de6c855SPrzemek Kitszel WARN_ON_ONCE(1); 1513*5de6c855SPrzemek Kitszel return; 1514*5de6c855SPrzemek Kitszel } 1515*5de6c855SPrzemek Kitszel 1516*5de6c855SPrzemek Kitszel ctx_irq->flags &= ~ICE_VF_FDIR_CTX_VALID; 1517*5de6c855SPrzemek Kitszel 1518*5de6c855SPrzemek Kitszel ctx_done->flags |= ICE_VF_FDIR_CTX_VALID; 1519*5de6c855SPrzemek Kitszel ctx_done->conf = ctx_irq->conf; 1520*5de6c855SPrzemek Kitszel ctx_done->stat = ICE_FDIR_CTX_IRQ; 1521*5de6c855SPrzemek Kitszel ctx_done->v_opcode = ctx_irq->v_opcode; 1522*5de6c855SPrzemek Kitszel memcpy(&ctx_done->rx_desc, rx_desc, sizeof(*rx_desc)); 1523*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&fdir->ctx_lock, flags); 1524*5de6c855SPrzemek Kitszel 1525*5de6c855SPrzemek Kitszel ret = timer_delete(&ctx_irq->rx_tmr); 1526*5de6c855SPrzemek Kitszel if (!ret) 1527*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Unexpected inactive timer!\n", vf->vf_id); 1528*5de6c855SPrzemek Kitszel 1529*5de6c855SPrzemek Kitszel set_bit(ICE_FD_VF_FLUSH_CTX, pf->state); 1530*5de6c855SPrzemek Kitszel ice_service_task_schedule(pf); 1531*5de6c855SPrzemek Kitszel } 1532*5de6c855SPrzemek Kitszel 1533*5de6c855SPrzemek Kitszel /** 1534*5de6c855SPrzemek Kitszel * ice_vf_fdir_dump_info - dump FDIR information for diagnosis 1535*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1536*5de6c855SPrzemek Kitszel */ 1537*5de6c855SPrzemek Kitszel static void ice_vf_fdir_dump_info(struct ice_vf *vf) 1538*5de6c855SPrzemek Kitszel { 1539*5de6c855SPrzemek Kitszel u32 fd_size, fd_cnt, fd_size_g, fd_cnt_g, fd_size_b, fd_cnt_b; 1540*5de6c855SPrzemek Kitszel struct ice_vsi *vf_vsi; 1541*5de6c855SPrzemek Kitszel struct device *dev; 1542*5de6c855SPrzemek Kitszel struct ice_pf *pf; 1543*5de6c855SPrzemek Kitszel struct ice_hw *hw; 1544*5de6c855SPrzemek Kitszel u16 vsi_num; 1545*5de6c855SPrzemek Kitszel 1546*5de6c855SPrzemek Kitszel pf = vf->pf; 1547*5de6c855SPrzemek Kitszel hw = &pf->hw; 1548*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 1549*5de6c855SPrzemek Kitszel vf_vsi = ice_get_vf_vsi(vf); 1550*5de6c855SPrzemek Kitszel if (!vf_vsi) { 1551*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: invalid VSI pointer\n", vf->vf_id); 1552*5de6c855SPrzemek Kitszel return; 1553*5de6c855SPrzemek Kitszel } 1554*5de6c855SPrzemek Kitszel 1555*5de6c855SPrzemek Kitszel vsi_num = ice_get_hw_vsi_num(hw, vf_vsi->idx); 1556*5de6c855SPrzemek Kitszel 1557*5de6c855SPrzemek Kitszel fd_size = rd32(hw, VSIQF_FD_SIZE(vsi_num)); 1558*5de6c855SPrzemek Kitszel fd_cnt = rd32(hw, VSIQF_FD_CNT(vsi_num)); 1559*5de6c855SPrzemek Kitszel switch (hw->mac_type) { 1560*5de6c855SPrzemek Kitszel case ICE_MAC_E830: 1561*5de6c855SPrzemek Kitszel fd_size_g = FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, fd_size); 1562*5de6c855SPrzemek Kitszel fd_size_b = FIELD_GET(E830_VSIQF_FD_CNT_FD_BCNT_M, fd_size); 1563*5de6c855SPrzemek Kitszel fd_cnt_g = FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, fd_cnt); 1564*5de6c855SPrzemek Kitszel fd_cnt_b = FIELD_GET(E830_VSIQF_FD_CNT_FD_BCNT_M, fd_cnt); 1565*5de6c855SPrzemek Kitszel break; 1566*5de6c855SPrzemek Kitszel case ICE_MAC_E810: 1567*5de6c855SPrzemek Kitszel default: 1568*5de6c855SPrzemek Kitszel fd_size_g = FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, fd_size); 1569*5de6c855SPrzemek Kitszel fd_size_b = FIELD_GET(E800_VSIQF_FD_CNT_FD_BCNT_M, fd_size); 1570*5de6c855SPrzemek Kitszel fd_cnt_g = FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, fd_cnt); 1571*5de6c855SPrzemek Kitszel fd_cnt_b = FIELD_GET(E800_VSIQF_FD_CNT_FD_BCNT_M, fd_cnt); 1572*5de6c855SPrzemek Kitszel } 1573*5de6c855SPrzemek Kitszel 1574*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: Size in the FD table: guaranteed:0x%x, best effort:0x%x\n", 1575*5de6c855SPrzemek Kitszel vf->vf_id, fd_size_g, fd_size_b); 1576*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: Filter counter in the FD table: guaranteed:0x%x, best effort:0x%x\n", 1577*5de6c855SPrzemek Kitszel vf->vf_id, fd_cnt_g, fd_cnt_b); 1578*5de6c855SPrzemek Kitszel } 1579*5de6c855SPrzemek Kitszel 1580*5de6c855SPrzemek Kitszel /** 1581*5de6c855SPrzemek Kitszel * ice_vf_verify_rx_desc - verify received FDIR programming status descriptor 1582*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1583*5de6c855SPrzemek Kitszel * @ctx: FDIR context info for post processing 1584*5de6c855SPrzemek Kitszel * @status: virtchnl FDIR program status 1585*5de6c855SPrzemek Kitszel * 1586*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1587*5de6c855SPrzemek Kitszel */ 1588*5de6c855SPrzemek Kitszel static int 1589*5de6c855SPrzemek Kitszel ice_vf_verify_rx_desc(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx, 1590*5de6c855SPrzemek Kitszel enum virtchnl_fdir_prgm_status *status) 1591*5de6c855SPrzemek Kitszel { 1592*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 1593*5de6c855SPrzemek Kitszel u32 stat_err, error, prog_id; 1594*5de6c855SPrzemek Kitszel int ret; 1595*5de6c855SPrzemek Kitszel 1596*5de6c855SPrzemek Kitszel stat_err = le16_to_cpu(ctx->rx_desc.wb.status_error0); 1597*5de6c855SPrzemek Kitszel if (FIELD_GET(ICE_FXD_FLTR_WB_QW1_DD_M, stat_err) != 1598*5de6c855SPrzemek Kitszel ICE_FXD_FLTR_WB_QW1_DD_YES) { 1599*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 1600*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Desc Done not set\n", vf->vf_id); 1601*5de6c855SPrzemek Kitszel ret = -EINVAL; 1602*5de6c855SPrzemek Kitszel goto err_exit; 1603*5de6c855SPrzemek Kitszel } 1604*5de6c855SPrzemek Kitszel 1605*5de6c855SPrzemek Kitszel prog_id = FIELD_GET(ICE_FXD_FLTR_WB_QW1_PROG_ID_M, stat_err); 1606*5de6c855SPrzemek Kitszel if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_ADD && 1607*5de6c855SPrzemek Kitszel ctx->v_opcode != VIRTCHNL_OP_ADD_FDIR_FILTER) { 1608*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Desc show add, but ctx not", 1609*5de6c855SPrzemek Kitszel vf->vf_id); 1610*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID; 1611*5de6c855SPrzemek Kitszel ret = -EINVAL; 1612*5de6c855SPrzemek Kitszel goto err_exit; 1613*5de6c855SPrzemek Kitszel } 1614*5de6c855SPrzemek Kitszel 1615*5de6c855SPrzemek Kitszel if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_DEL && 1616*5de6c855SPrzemek Kitszel ctx->v_opcode != VIRTCHNL_OP_DEL_FDIR_FILTER) { 1617*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Desc show del, but ctx not", 1618*5de6c855SPrzemek Kitszel vf->vf_id); 1619*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID; 1620*5de6c855SPrzemek Kitszel ret = -EINVAL; 1621*5de6c855SPrzemek Kitszel goto err_exit; 1622*5de6c855SPrzemek Kitszel } 1623*5de6c855SPrzemek Kitszel 1624*5de6c855SPrzemek Kitszel error = FIELD_GET(ICE_FXD_FLTR_WB_QW1_FAIL_M, stat_err); 1625*5de6c855SPrzemek Kitszel if (error == ICE_FXD_FLTR_WB_QW1_FAIL_YES) { 1626*5de6c855SPrzemek Kitszel if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_ADD) { 1627*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d, Failed to add FDIR rule due to no space in the table", 1628*5de6c855SPrzemek Kitszel vf->vf_id); 1629*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 1630*5de6c855SPrzemek Kitszel } else { 1631*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d, Failed to remove FDIR rule, attempt to remove non-existent entry", 1632*5de6c855SPrzemek Kitszel vf->vf_id); 1633*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST; 1634*5de6c855SPrzemek Kitszel } 1635*5de6c855SPrzemek Kitszel ret = -EINVAL; 1636*5de6c855SPrzemek Kitszel goto err_exit; 1637*5de6c855SPrzemek Kitszel } 1638*5de6c855SPrzemek Kitszel 1639*5de6c855SPrzemek Kitszel error = FIELD_GET(ICE_FXD_FLTR_WB_QW1_FAIL_PROF_M, stat_err); 1640*5de6c855SPrzemek Kitszel if (error == ICE_FXD_FLTR_WB_QW1_FAIL_PROF_YES) { 1641*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Profile matching error", vf->vf_id); 1642*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 1643*5de6c855SPrzemek Kitszel ret = -EINVAL; 1644*5de6c855SPrzemek Kitszel goto err_exit; 1645*5de6c855SPrzemek Kitszel } 1646*5de6c855SPrzemek Kitszel 1647*5de6c855SPrzemek Kitszel *status = VIRTCHNL_FDIR_SUCCESS; 1648*5de6c855SPrzemek Kitszel 1649*5de6c855SPrzemek Kitszel return 0; 1650*5de6c855SPrzemek Kitszel 1651*5de6c855SPrzemek Kitszel err_exit: 1652*5de6c855SPrzemek Kitszel ice_vf_fdir_dump_info(vf); 1653*5de6c855SPrzemek Kitszel return ret; 1654*5de6c855SPrzemek Kitszel } 1655*5de6c855SPrzemek Kitszel 1656*5de6c855SPrzemek Kitszel static int ice_fdir_is_tunnel(enum ice_fdir_tunnel_type ttype) 1657*5de6c855SPrzemek Kitszel { 1658*5de6c855SPrzemek Kitszel return (ttype == ICE_FDIR_TUNNEL_TYPE_GRE_INNER || 1659*5de6c855SPrzemek Kitszel ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_INNER || 1660*5de6c855SPrzemek Kitszel ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_EH_INNER || 1661*5de6c855SPrzemek Kitszel ttype == ICE_FDIR_TUNNEL_TYPE_GTPOGRE_INNER || 1662*5de6c855SPrzemek Kitszel ttype == ICE_FDIR_TUNNEL_TYPE_ECPRI || 1663*5de6c855SPrzemek Kitszel ttype == ICE_FDIR_TUNNEL_TYPE_L2TPV2_INNER); 1664*5de6c855SPrzemek Kitszel } 1665*5de6c855SPrzemek Kitszel 1666*5de6c855SPrzemek Kitszel /** 1667*5de6c855SPrzemek Kitszel * ice_vc_add_fdir_fltr_post 1668*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 1669*5de6c855SPrzemek Kitszel * @ctx: FDIR context info for post processing 1670*5de6c855SPrzemek Kitszel * @status: virtchnl FDIR program status 1671*5de6c855SPrzemek Kitszel * @success: true implies success, false implies failure 1672*5de6c855SPrzemek Kitszel * 1673*5de6c855SPrzemek Kitszel * Post process for flow director add command. If success, then do post process 1674*5de6c855SPrzemek Kitszel * and send back success msg by virtchnl. Otherwise, do context reversion and 1675*5de6c855SPrzemek Kitszel * send back failure msg by virtchnl. 1676*5de6c855SPrzemek Kitszel * 1677*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1678*5de6c855SPrzemek Kitszel */ 1679*5de6c855SPrzemek Kitszel static int 1680*5de6c855SPrzemek Kitszel ice_vc_add_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx, 1681*5de6c855SPrzemek Kitszel enum virtchnl_fdir_prgm_status status, 1682*5de6c855SPrzemek Kitszel bool success) 1683*5de6c855SPrzemek Kitszel { 1684*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf = ctx->conf; 1685*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 1686*5de6c855SPrzemek Kitszel enum virtchnl_status_code v_ret; 1687*5de6c855SPrzemek Kitszel struct virtchnl_fdir_add *resp; 1688*5de6c855SPrzemek Kitszel int ret, len, is_tun; 1689*5de6c855SPrzemek Kitszel 1690*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 1691*5de6c855SPrzemek Kitszel len = sizeof(*resp); 1692*5de6c855SPrzemek Kitszel resp = kzalloc(len, GFP_KERNEL); 1693*5de6c855SPrzemek Kitszel if (!resp) { 1694*5de6c855SPrzemek Kitszel len = 0; 1695*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 1696*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: Alloc resp buf fail", vf->vf_id); 1697*5de6c855SPrzemek Kitszel goto err_exit; 1698*5de6c855SPrzemek Kitszel } 1699*5de6c855SPrzemek Kitszel 1700*5de6c855SPrzemek Kitszel if (!success) 1701*5de6c855SPrzemek Kitszel goto err_exit; 1702*5de6c855SPrzemek Kitszel 1703*5de6c855SPrzemek Kitszel is_tun = 0; 1704*5de6c855SPrzemek Kitszel resp->status = status; 1705*5de6c855SPrzemek Kitszel resp->flow_id = conf->flow_id; 1706*5de6c855SPrzemek Kitszel vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]++; 1707*5de6c855SPrzemek Kitszel vf->fdir.fdir_fltr_cnt_total++; 1708*5de6c855SPrzemek Kitszel 1709*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret, 1710*5de6c855SPrzemek Kitszel (u8 *)resp, len); 1711*5de6c855SPrzemek Kitszel kfree(resp); 1712*5de6c855SPrzemek Kitszel 1713*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: flow_id:0x%X, FDIR %s success!\n", 1714*5de6c855SPrzemek Kitszel vf->vf_id, conf->flow_id, 1715*5de6c855SPrzemek Kitszel (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) ? 1716*5de6c855SPrzemek Kitszel "add" : "del"); 1717*5de6c855SPrzemek Kitszel return ret; 1718*5de6c855SPrzemek Kitszel 1719*5de6c855SPrzemek Kitszel err_exit: 1720*5de6c855SPrzemek Kitszel if (resp) 1721*5de6c855SPrzemek Kitszel resp->status = status; 1722*5de6c855SPrzemek Kitszel ice_vc_fdir_remove_entry(vf, conf, conf->flow_id); 1723*5de6c855SPrzemek Kitszel devm_kfree(dev, conf); 1724*5de6c855SPrzemek Kitszel 1725*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret, 1726*5de6c855SPrzemek Kitszel (u8 *)resp, len); 1727*5de6c855SPrzemek Kitszel kfree(resp); 1728*5de6c855SPrzemek Kitszel return ret; 1729*5de6c855SPrzemek Kitszel } 1730*5de6c855SPrzemek Kitszel 1731*5de6c855SPrzemek Kitszel /** 1732*5de6c855SPrzemek Kitszel * ice_vc_del_fdir_fltr_post 1733*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 1734*5de6c855SPrzemek Kitszel * @ctx: FDIR context info for post processing 1735*5de6c855SPrzemek Kitszel * @status: virtchnl FDIR program status 1736*5de6c855SPrzemek Kitszel * @success: true implies success, false implies failure 1737*5de6c855SPrzemek Kitszel * 1738*5de6c855SPrzemek Kitszel * Post process for flow director del command. If success, then do post process 1739*5de6c855SPrzemek Kitszel * and send back success msg by virtchnl. Otherwise, do context reversion and 1740*5de6c855SPrzemek Kitszel * send back failure msg by virtchnl. 1741*5de6c855SPrzemek Kitszel * 1742*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1743*5de6c855SPrzemek Kitszel */ 1744*5de6c855SPrzemek Kitszel static int 1745*5de6c855SPrzemek Kitszel ice_vc_del_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx, 1746*5de6c855SPrzemek Kitszel enum virtchnl_fdir_prgm_status status, 1747*5de6c855SPrzemek Kitszel bool success) 1748*5de6c855SPrzemek Kitszel { 1749*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf = ctx->conf; 1750*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 1751*5de6c855SPrzemek Kitszel enum virtchnl_status_code v_ret; 1752*5de6c855SPrzemek Kitszel struct virtchnl_fdir_del *resp; 1753*5de6c855SPrzemek Kitszel int ret, len, is_tun; 1754*5de6c855SPrzemek Kitszel 1755*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 1756*5de6c855SPrzemek Kitszel len = sizeof(*resp); 1757*5de6c855SPrzemek Kitszel resp = kzalloc(len, GFP_KERNEL); 1758*5de6c855SPrzemek Kitszel if (!resp) { 1759*5de6c855SPrzemek Kitszel len = 0; 1760*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 1761*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: Alloc resp buf fail", vf->vf_id); 1762*5de6c855SPrzemek Kitszel goto err_exit; 1763*5de6c855SPrzemek Kitszel } 1764*5de6c855SPrzemek Kitszel 1765*5de6c855SPrzemek Kitszel if (!success) 1766*5de6c855SPrzemek Kitszel goto err_exit; 1767*5de6c855SPrzemek Kitszel 1768*5de6c855SPrzemek Kitszel is_tun = 0; 1769*5de6c855SPrzemek Kitszel resp->status = status; 1770*5de6c855SPrzemek Kitszel ice_vc_fdir_remove_entry(vf, conf, conf->flow_id); 1771*5de6c855SPrzemek Kitszel vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]--; 1772*5de6c855SPrzemek Kitszel vf->fdir.fdir_fltr_cnt_total--; 1773*5de6c855SPrzemek Kitszel 1774*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret, 1775*5de6c855SPrzemek Kitszel (u8 *)resp, len); 1776*5de6c855SPrzemek Kitszel kfree(resp); 1777*5de6c855SPrzemek Kitszel 1778*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: flow_id:0x%X, FDIR %s success!\n", 1779*5de6c855SPrzemek Kitszel vf->vf_id, conf->flow_id, 1780*5de6c855SPrzemek Kitszel (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) ? 1781*5de6c855SPrzemek Kitszel "add" : "del"); 1782*5de6c855SPrzemek Kitszel devm_kfree(dev, conf); 1783*5de6c855SPrzemek Kitszel return ret; 1784*5de6c855SPrzemek Kitszel 1785*5de6c855SPrzemek Kitszel err_exit: 1786*5de6c855SPrzemek Kitszel if (resp) 1787*5de6c855SPrzemek Kitszel resp->status = status; 1788*5de6c855SPrzemek Kitszel if (success) 1789*5de6c855SPrzemek Kitszel devm_kfree(dev, conf); 1790*5de6c855SPrzemek Kitszel 1791*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret, 1792*5de6c855SPrzemek Kitszel (u8 *)resp, len); 1793*5de6c855SPrzemek Kitszel kfree(resp); 1794*5de6c855SPrzemek Kitszel return ret; 1795*5de6c855SPrzemek Kitszel } 1796*5de6c855SPrzemek Kitszel 1797*5de6c855SPrzemek Kitszel /** 1798*5de6c855SPrzemek Kitszel * ice_flush_fdir_ctx 1799*5de6c855SPrzemek Kitszel * @pf: pointer to the PF structure 1800*5de6c855SPrzemek Kitszel * 1801*5de6c855SPrzemek Kitszel * Flush all the pending event on ctx_done list and process them. 1802*5de6c855SPrzemek Kitszel */ 1803*5de6c855SPrzemek Kitszel void ice_flush_fdir_ctx(struct ice_pf *pf) 1804*5de6c855SPrzemek Kitszel { 1805*5de6c855SPrzemek Kitszel struct ice_vf *vf; 1806*5de6c855SPrzemek Kitszel unsigned int bkt; 1807*5de6c855SPrzemek Kitszel 1808*5de6c855SPrzemek Kitszel if (!test_and_clear_bit(ICE_FD_VF_FLUSH_CTX, pf->state)) 1809*5de6c855SPrzemek Kitszel return; 1810*5de6c855SPrzemek Kitszel 1811*5de6c855SPrzemek Kitszel mutex_lock(&pf->vfs.table_lock); 1812*5de6c855SPrzemek Kitszel ice_for_each_vf(pf, bkt, vf) { 1813*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(pf); 1814*5de6c855SPrzemek Kitszel enum virtchnl_fdir_prgm_status status; 1815*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx; 1816*5de6c855SPrzemek Kitszel unsigned long flags; 1817*5de6c855SPrzemek Kitszel int ret; 1818*5de6c855SPrzemek Kitszel 1819*5de6c855SPrzemek Kitszel if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) 1820*5de6c855SPrzemek Kitszel continue; 1821*5de6c855SPrzemek Kitszel 1822*5de6c855SPrzemek Kitszel if (vf->ctrl_vsi_idx == ICE_NO_VSI) 1823*5de6c855SPrzemek Kitszel continue; 1824*5de6c855SPrzemek Kitszel 1825*5de6c855SPrzemek Kitszel ctx = &vf->fdir.ctx_done; 1826*5de6c855SPrzemek Kitszel spin_lock_irqsave(&vf->fdir.ctx_lock, flags); 1827*5de6c855SPrzemek Kitszel if (!(ctx->flags & ICE_VF_FDIR_CTX_VALID)) { 1828*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1829*5de6c855SPrzemek Kitszel continue; 1830*5de6c855SPrzemek Kitszel } 1831*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1832*5de6c855SPrzemek Kitszel 1833*5de6c855SPrzemek Kitszel WARN_ON(ctx->stat == ICE_FDIR_CTX_READY); 1834*5de6c855SPrzemek Kitszel if (ctx->stat == ICE_FDIR_CTX_TIMEOUT) { 1835*5de6c855SPrzemek Kitszel status = VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT; 1836*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: ctrl_vsi irq timeout\n", 1837*5de6c855SPrzemek Kitszel vf->vf_id); 1838*5de6c855SPrzemek Kitszel goto err_exit; 1839*5de6c855SPrzemek Kitszel } 1840*5de6c855SPrzemek Kitszel 1841*5de6c855SPrzemek Kitszel ret = ice_vf_verify_rx_desc(vf, ctx, &status); 1842*5de6c855SPrzemek Kitszel if (ret) 1843*5de6c855SPrzemek Kitszel goto err_exit; 1844*5de6c855SPrzemek Kitszel 1845*5de6c855SPrzemek Kitszel if (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) 1846*5de6c855SPrzemek Kitszel ice_vc_add_fdir_fltr_post(vf, ctx, status, true); 1847*5de6c855SPrzemek Kitszel else if (ctx->v_opcode == VIRTCHNL_OP_DEL_FDIR_FILTER) 1848*5de6c855SPrzemek Kitszel ice_vc_del_fdir_fltr_post(vf, ctx, status, true); 1849*5de6c855SPrzemek Kitszel else 1850*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Unsupported opcode\n", vf->vf_id); 1851*5de6c855SPrzemek Kitszel 1852*5de6c855SPrzemek Kitszel spin_lock_irqsave(&vf->fdir.ctx_lock, flags); 1853*5de6c855SPrzemek Kitszel ctx->flags &= ~ICE_VF_FDIR_CTX_VALID; 1854*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1855*5de6c855SPrzemek Kitszel continue; 1856*5de6c855SPrzemek Kitszel err_exit: 1857*5de6c855SPrzemek Kitszel if (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) 1858*5de6c855SPrzemek Kitszel ice_vc_add_fdir_fltr_post(vf, ctx, status, false); 1859*5de6c855SPrzemek Kitszel else if (ctx->v_opcode == VIRTCHNL_OP_DEL_FDIR_FILTER) 1860*5de6c855SPrzemek Kitszel ice_vc_del_fdir_fltr_post(vf, ctx, status, false); 1861*5de6c855SPrzemek Kitszel else 1862*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: Unsupported opcode\n", vf->vf_id); 1863*5de6c855SPrzemek Kitszel 1864*5de6c855SPrzemek Kitszel spin_lock_irqsave(&vf->fdir.ctx_lock, flags); 1865*5de6c855SPrzemek Kitszel ctx->flags &= ~ICE_VF_FDIR_CTX_VALID; 1866*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1867*5de6c855SPrzemek Kitszel } 1868*5de6c855SPrzemek Kitszel mutex_unlock(&pf->vfs.table_lock); 1869*5de6c855SPrzemek Kitszel } 1870*5de6c855SPrzemek Kitszel 1871*5de6c855SPrzemek Kitszel /** 1872*5de6c855SPrzemek Kitszel * ice_vc_fdir_set_irq_ctx - set FDIR context info for later IRQ handler 1873*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 1874*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1875*5de6c855SPrzemek Kitszel * @v_opcode: virtual channel operation code 1876*5de6c855SPrzemek Kitszel * 1877*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1878*5de6c855SPrzemek Kitszel */ 1879*5de6c855SPrzemek Kitszel static int 1880*5de6c855SPrzemek Kitszel ice_vc_fdir_set_irq_ctx(struct ice_vf *vf, struct virtchnl_fdir_fltr_conf *conf, 1881*5de6c855SPrzemek Kitszel enum virtchnl_ops v_opcode) 1882*5de6c855SPrzemek Kitszel { 1883*5de6c855SPrzemek Kitszel struct device *dev = ice_pf_to_dev(vf->pf); 1884*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx; 1885*5de6c855SPrzemek Kitszel unsigned long flags; 1886*5de6c855SPrzemek Kitszel 1887*5de6c855SPrzemek Kitszel ctx = &vf->fdir.ctx_irq; 1888*5de6c855SPrzemek Kitszel spin_lock_irqsave(&vf->fdir.ctx_lock, flags); 1889*5de6c855SPrzemek Kitszel if ((vf->fdir.ctx_irq.flags & ICE_VF_FDIR_CTX_VALID) || 1890*5de6c855SPrzemek Kitszel (vf->fdir.ctx_done.flags & ICE_VF_FDIR_CTX_VALID)) { 1891*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1892*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: Last request is still in progress\n", 1893*5de6c855SPrzemek Kitszel vf->vf_id); 1894*5de6c855SPrzemek Kitszel return -EBUSY; 1895*5de6c855SPrzemek Kitszel } 1896*5de6c855SPrzemek Kitszel ctx->flags |= ICE_VF_FDIR_CTX_VALID; 1897*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1898*5de6c855SPrzemek Kitszel 1899*5de6c855SPrzemek Kitszel ctx->conf = conf; 1900*5de6c855SPrzemek Kitszel ctx->v_opcode = v_opcode; 1901*5de6c855SPrzemek Kitszel ctx->stat = ICE_FDIR_CTX_READY; 1902*5de6c855SPrzemek Kitszel timer_setup(&ctx->rx_tmr, ice_vf_fdir_timer, 0); 1903*5de6c855SPrzemek Kitszel 1904*5de6c855SPrzemek Kitszel mod_timer(&ctx->rx_tmr, round_jiffies(msecs_to_jiffies(10) + jiffies)); 1905*5de6c855SPrzemek Kitszel 1906*5de6c855SPrzemek Kitszel return 0; 1907*5de6c855SPrzemek Kitszel } 1908*5de6c855SPrzemek Kitszel 1909*5de6c855SPrzemek Kitszel /** 1910*5de6c855SPrzemek Kitszel * ice_vc_fdir_clear_irq_ctx - clear FDIR context info for IRQ handler 1911*5de6c855SPrzemek Kitszel * @vf: pointer to the VF structure 1912*5de6c855SPrzemek Kitszel * 1913*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 1914*5de6c855SPrzemek Kitszel */ 1915*5de6c855SPrzemek Kitszel static void ice_vc_fdir_clear_irq_ctx(struct ice_vf *vf) 1916*5de6c855SPrzemek Kitszel { 1917*5de6c855SPrzemek Kitszel struct ice_vf_fdir_ctx *ctx = &vf->fdir.ctx_irq; 1918*5de6c855SPrzemek Kitszel unsigned long flags; 1919*5de6c855SPrzemek Kitszel 1920*5de6c855SPrzemek Kitszel timer_delete(&ctx->rx_tmr); 1921*5de6c855SPrzemek Kitszel spin_lock_irqsave(&vf->fdir.ctx_lock, flags); 1922*5de6c855SPrzemek Kitszel ctx->flags &= ~ICE_VF_FDIR_CTX_VALID; 1923*5de6c855SPrzemek Kitszel spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags); 1924*5de6c855SPrzemek Kitszel } 1925*5de6c855SPrzemek Kitszel 1926*5de6c855SPrzemek Kitszel /** 1927*5de6c855SPrzemek Kitszel * ice_vc_parser_fv_check_diff - check two parsed FDIR profile fv context 1928*5de6c855SPrzemek Kitszel * @fv_a: struct of parsed FDIR profile field vector 1929*5de6c855SPrzemek Kitszel * @fv_b: struct of parsed FDIR profile field vector 1930*5de6c855SPrzemek Kitszel * 1931*5de6c855SPrzemek Kitszel * Check if the two parsed FDIR profile field vector context are different, 1932*5de6c855SPrzemek Kitszel * including proto_id, offset and mask. 1933*5de6c855SPrzemek Kitszel * 1934*5de6c855SPrzemek Kitszel * Return: true on different, false on otherwise. 1935*5de6c855SPrzemek Kitszel */ 1936*5de6c855SPrzemek Kitszel static bool ice_vc_parser_fv_check_diff(struct ice_parser_fv *fv_a, 1937*5de6c855SPrzemek Kitszel struct ice_parser_fv *fv_b) 1938*5de6c855SPrzemek Kitszel { 1939*5de6c855SPrzemek Kitszel return (fv_a->proto_id != fv_b->proto_id || 1940*5de6c855SPrzemek Kitszel fv_a->offset != fv_b->offset || 1941*5de6c855SPrzemek Kitszel fv_a->msk != fv_b->msk); 1942*5de6c855SPrzemek Kitszel } 1943*5de6c855SPrzemek Kitszel 1944*5de6c855SPrzemek Kitszel /** 1945*5de6c855SPrzemek Kitszel * ice_vc_parser_fv_save - save parsed FDIR profile fv context 1946*5de6c855SPrzemek Kitszel * @fv: struct of parsed FDIR profile field vector 1947*5de6c855SPrzemek Kitszel * @fv_src: parsed FDIR profile field vector context to save 1948*5de6c855SPrzemek Kitszel * 1949*5de6c855SPrzemek Kitszel * Save the parsed FDIR profile field vector context, including proto_id, 1950*5de6c855SPrzemek Kitszel * offset and mask. 1951*5de6c855SPrzemek Kitszel * 1952*5de6c855SPrzemek Kitszel * Return: Void. 1953*5de6c855SPrzemek Kitszel */ 1954*5de6c855SPrzemek Kitszel static void ice_vc_parser_fv_save(struct ice_parser_fv *fv, 1955*5de6c855SPrzemek Kitszel struct ice_parser_fv *fv_src) 1956*5de6c855SPrzemek Kitszel { 1957*5de6c855SPrzemek Kitszel fv->proto_id = fv_src->proto_id; 1958*5de6c855SPrzemek Kitszel fv->offset = fv_src->offset; 1959*5de6c855SPrzemek Kitszel fv->msk = fv_src->msk; 1960*5de6c855SPrzemek Kitszel fv->spec = 0; 1961*5de6c855SPrzemek Kitszel } 1962*5de6c855SPrzemek Kitszel 1963*5de6c855SPrzemek Kitszel /** 1964*5de6c855SPrzemek Kitszel * ice_vc_add_fdir_raw - add a raw FDIR filter for VF 1965*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 1966*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 1967*5de6c855SPrzemek Kitszel * @v_ret: the final VIRTCHNL code 1968*5de6c855SPrzemek Kitszel * @stat: pointer to the VIRTCHNL_OP_ADD_FDIR_FILTER 1969*5de6c855SPrzemek Kitszel * @len: length of the stat 1970*5de6c855SPrzemek Kitszel * 1971*5de6c855SPrzemek Kitszel * Return: 0 on success or negative errno on failure. 1972*5de6c855SPrzemek Kitszel */ 1973*5de6c855SPrzemek Kitszel static int 1974*5de6c855SPrzemek Kitszel ice_vc_add_fdir_raw(struct ice_vf *vf, 1975*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, 1976*5de6c855SPrzemek Kitszel enum virtchnl_status_code *v_ret, 1977*5de6c855SPrzemek Kitszel struct virtchnl_fdir_add *stat, int len) 1978*5de6c855SPrzemek Kitszel { 1979*5de6c855SPrzemek Kitszel struct ice_vsi *vf_vsi, *ctrl_vsi; 1980*5de6c855SPrzemek Kitszel struct ice_fdir_prof_info *pi; 1981*5de6c855SPrzemek Kitszel struct ice_pf *pf = vf->pf; 1982*5de6c855SPrzemek Kitszel int ret, ptg, id, i; 1983*5de6c855SPrzemek Kitszel struct device *dev; 1984*5de6c855SPrzemek Kitszel struct ice_hw *hw; 1985*5de6c855SPrzemek Kitszel bool fv_found; 1986*5de6c855SPrzemek Kitszel 1987*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 1988*5de6c855SPrzemek Kitszel hw = &pf->hw; 1989*5de6c855SPrzemek Kitszel *v_ret = VIRTCHNL_STATUS_ERR_PARAM; 1990*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 1991*5de6c855SPrzemek Kitszel 1992*5de6c855SPrzemek Kitszel id = find_first_bit(conf->prof->ptypes, ICE_FLOW_PTYPE_MAX); 1993*5de6c855SPrzemek Kitszel ptg = hw->blk[ICE_BLK_FD].xlt1.t[id]; 1994*5de6c855SPrzemek Kitszel 1995*5de6c855SPrzemek Kitszel vf_vsi = ice_get_vf_vsi(vf); 1996*5de6c855SPrzemek Kitszel if (!vf_vsi) { 1997*5de6c855SPrzemek Kitszel dev_err(dev, "Can not get FDIR vf_vsi for VF %d\n", vf->vf_id); 1998*5de6c855SPrzemek Kitszel return -ENODEV; 1999*5de6c855SPrzemek Kitszel } 2000*5de6c855SPrzemek Kitszel 2001*5de6c855SPrzemek Kitszel ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx]; 2002*5de6c855SPrzemek Kitszel if (!ctrl_vsi) { 2003*5de6c855SPrzemek Kitszel dev_err(dev, "Can not get FDIR ctrl_vsi for VF %d\n", 2004*5de6c855SPrzemek Kitszel vf->vf_id); 2005*5de6c855SPrzemek Kitszel return -ENODEV; 2006*5de6c855SPrzemek Kitszel } 2007*5de6c855SPrzemek Kitszel 2008*5de6c855SPrzemek Kitszel fv_found = false; 2009*5de6c855SPrzemek Kitszel 2010*5de6c855SPrzemek Kitszel /* Check if profile info already exists, then update the counter */ 2011*5de6c855SPrzemek Kitszel pi = &vf->fdir_prof_info[ptg]; 2012*5de6c855SPrzemek Kitszel if (pi->fdir_active_cnt != 0) { 2013*5de6c855SPrzemek Kitszel for (i = 0; i < ICE_MAX_FV_WORDS; i++) 2014*5de6c855SPrzemek Kitszel if (ice_vc_parser_fv_check_diff(&pi->prof.fv[i], 2015*5de6c855SPrzemek Kitszel &conf->prof->fv[i])) 2016*5de6c855SPrzemek Kitszel break; 2017*5de6c855SPrzemek Kitszel if (i == ICE_MAX_FV_WORDS) { 2018*5de6c855SPrzemek Kitszel fv_found = true; 2019*5de6c855SPrzemek Kitszel pi->fdir_active_cnt++; 2020*5de6c855SPrzemek Kitszel } 2021*5de6c855SPrzemek Kitszel } 2022*5de6c855SPrzemek Kitszel 2023*5de6c855SPrzemek Kitszel /* HW profile setting is only required for the first time */ 2024*5de6c855SPrzemek Kitszel if (!fv_found) { 2025*5de6c855SPrzemek Kitszel ret = ice_flow_set_parser_prof(hw, vf_vsi->idx, 2026*5de6c855SPrzemek Kitszel ctrl_vsi->idx, conf->prof, 2027*5de6c855SPrzemek Kitszel ICE_BLK_FD); 2028*5de6c855SPrzemek Kitszel 2029*5de6c855SPrzemek Kitszel if (ret) { 2030*5de6c855SPrzemek Kitszel *v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 2031*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: insert hw prof failed\n", 2032*5de6c855SPrzemek Kitszel vf->vf_id); 2033*5de6c855SPrzemek Kitszel return ret; 2034*5de6c855SPrzemek Kitszel } 2035*5de6c855SPrzemek Kitszel } 2036*5de6c855SPrzemek Kitszel 2037*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_insert_entry(vf, conf, &conf->flow_id); 2038*5de6c855SPrzemek Kitszel if (ret) { 2039*5de6c855SPrzemek Kitszel *v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 2040*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: insert FDIR list failed\n", 2041*5de6c855SPrzemek Kitszel vf->vf_id); 2042*5de6c855SPrzemek Kitszel return ret; 2043*5de6c855SPrzemek Kitszel } 2044*5de6c855SPrzemek Kitszel 2045*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_set_irq_ctx(vf, conf, 2046*5de6c855SPrzemek Kitszel VIRTCHNL_OP_ADD_FDIR_FILTER); 2047*5de6c855SPrzemek Kitszel if (ret) { 2048*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: set FDIR context failed\n", 2049*5de6c855SPrzemek Kitszel vf->vf_id); 2050*5de6c855SPrzemek Kitszel goto err_rem_entry; 2051*5de6c855SPrzemek Kitszel } 2052*5de6c855SPrzemek Kitszel 2053*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_write_fltr(vf, conf, true, false); 2054*5de6c855SPrzemek Kitszel if (ret) { 2055*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: adding FDIR raw flow rule failed, ret:%d\n", 2056*5de6c855SPrzemek Kitszel vf->vf_id, ret); 2057*5de6c855SPrzemek Kitszel goto err_clr_irq; 2058*5de6c855SPrzemek Kitszel } 2059*5de6c855SPrzemek Kitszel 2060*5de6c855SPrzemek Kitszel /* Save parsed profile fv info of the FDIR rule for the first time */ 2061*5de6c855SPrzemek Kitszel if (!fv_found) { 2062*5de6c855SPrzemek Kitszel for (i = 0; i < conf->prof->fv_num; i++) 2063*5de6c855SPrzemek Kitszel ice_vc_parser_fv_save(&pi->prof.fv[i], 2064*5de6c855SPrzemek Kitszel &conf->prof->fv[i]); 2065*5de6c855SPrzemek Kitszel pi->prof.fv_num = conf->prof->fv_num; 2066*5de6c855SPrzemek Kitszel pi->fdir_active_cnt = 1; 2067*5de6c855SPrzemek Kitszel } 2068*5de6c855SPrzemek Kitszel 2069*5de6c855SPrzemek Kitszel return 0; 2070*5de6c855SPrzemek Kitszel 2071*5de6c855SPrzemek Kitszel err_clr_irq: 2072*5de6c855SPrzemek Kitszel ice_vc_fdir_clear_irq_ctx(vf); 2073*5de6c855SPrzemek Kitszel err_rem_entry: 2074*5de6c855SPrzemek Kitszel ice_vc_fdir_remove_entry(vf, conf, conf->flow_id); 2075*5de6c855SPrzemek Kitszel return ret; 2076*5de6c855SPrzemek Kitszel } 2077*5de6c855SPrzemek Kitszel 2078*5de6c855SPrzemek Kitszel /** 2079*5de6c855SPrzemek Kitszel * ice_vc_add_fdir_fltr - add a FDIR filter for VF by the msg buffer 2080*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 2081*5de6c855SPrzemek Kitszel * @msg: pointer to the msg buffer 2082*5de6c855SPrzemek Kitszel * 2083*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 2084*5de6c855SPrzemek Kitszel */ 2085*5de6c855SPrzemek Kitszel int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg) 2086*5de6c855SPrzemek Kitszel { 2087*5de6c855SPrzemek Kitszel struct virtchnl_fdir_add *fltr = (struct virtchnl_fdir_add *)msg; 2088*5de6c855SPrzemek Kitszel struct virtchnl_fdir_add *stat = NULL; 2089*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf; 2090*5de6c855SPrzemek Kitszel enum virtchnl_status_code v_ret; 2091*5de6c855SPrzemek Kitszel struct ice_vsi *vf_vsi; 2092*5de6c855SPrzemek Kitszel struct device *dev; 2093*5de6c855SPrzemek Kitszel struct ice_pf *pf; 2094*5de6c855SPrzemek Kitszel int is_tun = 0; 2095*5de6c855SPrzemek Kitszel int len = 0; 2096*5de6c855SPrzemek Kitszel int ret; 2097*5de6c855SPrzemek Kitszel 2098*5de6c855SPrzemek Kitszel pf = vf->pf; 2099*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 2100*5de6c855SPrzemek Kitszel vf_vsi = ice_get_vf_vsi(vf); 2101*5de6c855SPrzemek Kitszel if (!vf_vsi) { 2102*5de6c855SPrzemek Kitszel dev_err(dev, "Can not get FDIR vf_vsi for VF %u\n", vf->vf_id); 2103*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2104*5de6c855SPrzemek Kitszel goto err_exit; 2105*5de6c855SPrzemek Kitszel } 2106*5de6c855SPrzemek Kitszel 2107*5de6c855SPrzemek Kitszel #define ICE_VF_MAX_FDIR_FILTERS 128 2108*5de6c855SPrzemek Kitszel if (!ice_fdir_num_avail_fltr(&pf->hw, vf_vsi) || 2109*5de6c855SPrzemek Kitszel vf->fdir.fdir_fltr_cnt_total >= ICE_VF_MAX_FDIR_FILTERS) { 2110*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2111*5de6c855SPrzemek Kitszel dev_err(dev, "Max number of FDIR filters for VF %d is reached\n", 2112*5de6c855SPrzemek Kitszel vf->vf_id); 2113*5de6c855SPrzemek Kitszel goto err_exit; 2114*5de6c855SPrzemek Kitszel } 2115*5de6c855SPrzemek Kitszel 2116*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_param_check(vf, fltr->vsi_id); 2117*5de6c855SPrzemek Kitszel if (ret) { 2118*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2119*5de6c855SPrzemek Kitszel dev_dbg(dev, "Parameter check for VF %d failed\n", vf->vf_id); 2120*5de6c855SPrzemek Kitszel goto err_exit; 2121*5de6c855SPrzemek Kitszel } 2122*5de6c855SPrzemek Kitszel 2123*5de6c855SPrzemek Kitszel ret = ice_vf_start_ctrl_vsi(vf); 2124*5de6c855SPrzemek Kitszel if (ret && (ret != -EEXIST)) { 2125*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2126*5de6c855SPrzemek Kitszel dev_err(dev, "Init FDIR for VF %d failed, ret:%d\n", 2127*5de6c855SPrzemek Kitszel vf->vf_id, ret); 2128*5de6c855SPrzemek Kitszel goto err_exit; 2129*5de6c855SPrzemek Kitszel } 2130*5de6c855SPrzemek Kitszel 2131*5de6c855SPrzemek Kitszel stat = kzalloc(sizeof(*stat), GFP_KERNEL); 2132*5de6c855SPrzemek Kitszel if (!stat) { 2133*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 2134*5de6c855SPrzemek Kitszel dev_dbg(dev, "Alloc stat for VF %d failed\n", vf->vf_id); 2135*5de6c855SPrzemek Kitszel goto err_exit; 2136*5de6c855SPrzemek Kitszel } 2137*5de6c855SPrzemek Kitszel 2138*5de6c855SPrzemek Kitszel conf = devm_kzalloc(dev, sizeof(*conf), GFP_KERNEL); 2139*5de6c855SPrzemek Kitszel if (!conf) { 2140*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 2141*5de6c855SPrzemek Kitszel dev_dbg(dev, "Alloc conf for VF %d failed\n", vf->vf_id); 2142*5de6c855SPrzemek Kitszel goto err_exit; 2143*5de6c855SPrzemek Kitszel } 2144*5de6c855SPrzemek Kitszel 2145*5de6c855SPrzemek Kitszel len = sizeof(*stat); 2146*5de6c855SPrzemek Kitszel ret = ice_vc_validate_fdir_fltr(vf, fltr, conf); 2147*5de6c855SPrzemek Kitszel if (ret) { 2148*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2149*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID; 2150*5de6c855SPrzemek Kitszel dev_dbg(dev, "Invalid FDIR filter from VF %d\n", vf->vf_id); 2151*5de6c855SPrzemek Kitszel goto err_free_conf; 2152*5de6c855SPrzemek Kitszel } 2153*5de6c855SPrzemek Kitszel 2154*5de6c855SPrzemek Kitszel if (fltr->validate_only) { 2155*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2156*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_SUCCESS; 2157*5de6c855SPrzemek Kitszel devm_kfree(dev, conf); 2158*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_FDIR_FILTER, 2159*5de6c855SPrzemek Kitszel v_ret, (u8 *)stat, len); 2160*5de6c855SPrzemek Kitszel goto exit; 2161*5de6c855SPrzemek Kitszel } 2162*5de6c855SPrzemek Kitszel 2163*5de6c855SPrzemek Kitszel /* For raw FDIR filters created by the parser */ 2164*5de6c855SPrzemek Kitszel if (conf->parser_ena) { 2165*5de6c855SPrzemek Kitszel ret = ice_vc_add_fdir_raw(vf, conf, &v_ret, stat, len); 2166*5de6c855SPrzemek Kitszel if (ret) 2167*5de6c855SPrzemek Kitszel goto err_free_conf; 2168*5de6c855SPrzemek Kitszel goto exit; 2169*5de6c855SPrzemek Kitszel } 2170*5de6c855SPrzemek Kitszel 2171*5de6c855SPrzemek Kitszel is_tun = ice_fdir_is_tunnel(conf->ttype); 2172*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_config_input_set(vf, fltr, conf, is_tun); 2173*5de6c855SPrzemek Kitszel if (ret) { 2174*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2175*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT; 2176*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: FDIR input set configure failed, ret:%d\n", 2177*5de6c855SPrzemek Kitszel vf->vf_id, ret); 2178*5de6c855SPrzemek Kitszel goto err_free_conf; 2179*5de6c855SPrzemek Kitszel } 2180*5de6c855SPrzemek Kitszel 2181*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_is_dup_fltr(vf, conf); 2182*5de6c855SPrzemek Kitszel if (ret) { 2183*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2184*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_EXIST; 2185*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: duplicated FDIR rule detected\n", 2186*5de6c855SPrzemek Kitszel vf->vf_id); 2187*5de6c855SPrzemek Kitszel goto err_free_conf; 2188*5de6c855SPrzemek Kitszel } 2189*5de6c855SPrzemek Kitszel 2190*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_insert_entry(vf, conf, &conf->flow_id); 2191*5de6c855SPrzemek Kitszel if (ret) { 2192*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2193*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2194*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: insert FDIR list failed\n", vf->vf_id); 2195*5de6c855SPrzemek Kitszel goto err_free_conf; 2196*5de6c855SPrzemek Kitszel } 2197*5de6c855SPrzemek Kitszel 2198*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_set_irq_ctx(vf, conf, VIRTCHNL_OP_ADD_FDIR_FILTER); 2199*5de6c855SPrzemek Kitszel if (ret) { 2200*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2201*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2202*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id); 2203*5de6c855SPrzemek Kitszel goto err_rem_entry; 2204*5de6c855SPrzemek Kitszel } 2205*5de6c855SPrzemek Kitszel 2206*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun); 2207*5de6c855SPrzemek Kitszel if (ret) { 2208*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2209*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2210*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n", 2211*5de6c855SPrzemek Kitszel vf->vf_id, ret); 2212*5de6c855SPrzemek Kitszel goto err_clr_irq; 2213*5de6c855SPrzemek Kitszel } 2214*5de6c855SPrzemek Kitszel 2215*5de6c855SPrzemek Kitszel exit: 2216*5de6c855SPrzemek Kitszel kfree(stat); 2217*5de6c855SPrzemek Kitszel return ret; 2218*5de6c855SPrzemek Kitszel 2219*5de6c855SPrzemek Kitszel err_clr_irq: 2220*5de6c855SPrzemek Kitszel ice_vc_fdir_clear_irq_ctx(vf); 2221*5de6c855SPrzemek Kitszel err_rem_entry: 2222*5de6c855SPrzemek Kitszel ice_vc_fdir_remove_entry(vf, conf, conf->flow_id); 2223*5de6c855SPrzemek Kitszel err_free_conf: 2224*5de6c855SPrzemek Kitszel devm_kfree(dev, conf); 2225*5de6c855SPrzemek Kitszel err_exit: 2226*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_FDIR_FILTER, v_ret, 2227*5de6c855SPrzemek Kitszel (u8 *)stat, len); 2228*5de6c855SPrzemek Kitszel kfree(stat); 2229*5de6c855SPrzemek Kitszel return ret; 2230*5de6c855SPrzemek Kitszel } 2231*5de6c855SPrzemek Kitszel 2232*5de6c855SPrzemek Kitszel /** 2233*5de6c855SPrzemek Kitszel * ice_vc_del_fdir_raw - delete a raw FDIR filter for VF 2234*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 2235*5de6c855SPrzemek Kitszel * @conf: FDIR configuration for each filter 2236*5de6c855SPrzemek Kitszel * @v_ret: the final VIRTCHNL code 2237*5de6c855SPrzemek Kitszel * @stat: pointer to the VIRTCHNL_OP_DEL_FDIR_FILTER 2238*5de6c855SPrzemek Kitszel * @len: length of the stat 2239*5de6c855SPrzemek Kitszel * 2240*5de6c855SPrzemek Kitszel * Return: 0 on success or negative errno on failure. 2241*5de6c855SPrzemek Kitszel */ 2242*5de6c855SPrzemek Kitszel static int 2243*5de6c855SPrzemek Kitszel ice_vc_del_fdir_raw(struct ice_vf *vf, 2244*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf, 2245*5de6c855SPrzemek Kitszel enum virtchnl_status_code *v_ret, 2246*5de6c855SPrzemek Kitszel struct virtchnl_fdir_del *stat, int len) 2247*5de6c855SPrzemek Kitszel { 2248*5de6c855SPrzemek Kitszel struct ice_vsi *vf_vsi, *ctrl_vsi; 2249*5de6c855SPrzemek Kitszel enum ice_block blk = ICE_BLK_FD; 2250*5de6c855SPrzemek Kitszel struct ice_fdir_prof_info *pi; 2251*5de6c855SPrzemek Kitszel struct ice_pf *pf = vf->pf; 2252*5de6c855SPrzemek Kitszel struct device *dev; 2253*5de6c855SPrzemek Kitszel struct ice_hw *hw; 2254*5de6c855SPrzemek Kitszel unsigned long id; 2255*5de6c855SPrzemek Kitszel u16 vsi_num; 2256*5de6c855SPrzemek Kitszel int ptg; 2257*5de6c855SPrzemek Kitszel int ret; 2258*5de6c855SPrzemek Kitszel 2259*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 2260*5de6c855SPrzemek Kitszel hw = &pf->hw; 2261*5de6c855SPrzemek Kitszel *v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2262*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2263*5de6c855SPrzemek Kitszel 2264*5de6c855SPrzemek Kitszel id = find_first_bit(conf->prof->ptypes, ICE_FLOW_PTYPE_MAX); 2265*5de6c855SPrzemek Kitszel ptg = hw->blk[ICE_BLK_FD].xlt1.t[id]; 2266*5de6c855SPrzemek Kitszel 2267*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_write_fltr(vf, conf, false, false); 2268*5de6c855SPrzemek Kitszel if (ret) { 2269*5de6c855SPrzemek Kitszel dev_err(dev, "VF %u: deleting FDIR raw flow rule failed: %d\n", 2270*5de6c855SPrzemek Kitszel vf->vf_id, ret); 2271*5de6c855SPrzemek Kitszel return ret; 2272*5de6c855SPrzemek Kitszel } 2273*5de6c855SPrzemek Kitszel 2274*5de6c855SPrzemek Kitszel vf_vsi = ice_get_vf_vsi(vf); 2275*5de6c855SPrzemek Kitszel if (!vf_vsi) { 2276*5de6c855SPrzemek Kitszel dev_err(dev, "Can not get FDIR vf_vsi for VF %u\n", vf->vf_id); 2277*5de6c855SPrzemek Kitszel return -ENODEV; 2278*5de6c855SPrzemek Kitszel } 2279*5de6c855SPrzemek Kitszel 2280*5de6c855SPrzemek Kitszel ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx]; 2281*5de6c855SPrzemek Kitszel if (!ctrl_vsi) { 2282*5de6c855SPrzemek Kitszel dev_err(dev, "Can not get FDIR ctrl_vsi for VF %u\n", 2283*5de6c855SPrzemek Kitszel vf->vf_id); 2284*5de6c855SPrzemek Kitszel return -ENODEV; 2285*5de6c855SPrzemek Kitszel } 2286*5de6c855SPrzemek Kitszel 2287*5de6c855SPrzemek Kitszel pi = &vf->fdir_prof_info[ptg]; 2288*5de6c855SPrzemek Kitszel if (pi->fdir_active_cnt != 0) { 2289*5de6c855SPrzemek Kitszel pi->fdir_active_cnt--; 2290*5de6c855SPrzemek Kitszel /* Remove the profile id flow if no active FDIR rule left */ 2291*5de6c855SPrzemek Kitszel if (!pi->fdir_active_cnt) { 2292*5de6c855SPrzemek Kitszel vsi_num = ice_get_hw_vsi_num(hw, ctrl_vsi->idx); 2293*5de6c855SPrzemek Kitszel ice_rem_prof_id_flow(hw, blk, vsi_num, id); 2294*5de6c855SPrzemek Kitszel 2295*5de6c855SPrzemek Kitszel vsi_num = ice_get_hw_vsi_num(hw, vf_vsi->idx); 2296*5de6c855SPrzemek Kitszel ice_rem_prof_id_flow(hw, blk, vsi_num, id); 2297*5de6c855SPrzemek Kitszel } 2298*5de6c855SPrzemek Kitszel } 2299*5de6c855SPrzemek Kitszel 2300*5de6c855SPrzemek Kitszel conf->parser_ena = false; 2301*5de6c855SPrzemek Kitszel return 0; 2302*5de6c855SPrzemek Kitszel } 2303*5de6c855SPrzemek Kitszel 2304*5de6c855SPrzemek Kitszel /** 2305*5de6c855SPrzemek Kitszel * ice_vc_del_fdir_fltr - delete a FDIR filter for VF by the msg buffer 2306*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 2307*5de6c855SPrzemek Kitszel * @msg: pointer to the msg buffer 2308*5de6c855SPrzemek Kitszel * 2309*5de6c855SPrzemek Kitszel * Return: 0 on success, and other on error. 2310*5de6c855SPrzemek Kitszel */ 2311*5de6c855SPrzemek Kitszel int ice_vc_del_fdir_fltr(struct ice_vf *vf, u8 *msg) 2312*5de6c855SPrzemek Kitszel { 2313*5de6c855SPrzemek Kitszel struct virtchnl_fdir_del *fltr = (struct virtchnl_fdir_del *)msg; 2314*5de6c855SPrzemek Kitszel struct virtchnl_fdir_del *stat = NULL; 2315*5de6c855SPrzemek Kitszel struct virtchnl_fdir_fltr_conf *conf; 2316*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 2317*5de6c855SPrzemek Kitszel enum virtchnl_status_code v_ret; 2318*5de6c855SPrzemek Kitszel struct ice_fdir_fltr *input; 2319*5de6c855SPrzemek Kitszel enum ice_fltr_ptype flow; 2320*5de6c855SPrzemek Kitszel struct device *dev; 2321*5de6c855SPrzemek Kitszel struct ice_pf *pf; 2322*5de6c855SPrzemek Kitszel int is_tun = 0; 2323*5de6c855SPrzemek Kitszel int len = 0; 2324*5de6c855SPrzemek Kitszel int ret; 2325*5de6c855SPrzemek Kitszel 2326*5de6c855SPrzemek Kitszel pf = vf->pf; 2327*5de6c855SPrzemek Kitszel dev = ice_pf_to_dev(pf); 2328*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_param_check(vf, fltr->vsi_id); 2329*5de6c855SPrzemek Kitszel if (ret) { 2330*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_PARAM; 2331*5de6c855SPrzemek Kitszel dev_dbg(dev, "Parameter check for VF %d failed\n", vf->vf_id); 2332*5de6c855SPrzemek Kitszel goto err_exit; 2333*5de6c855SPrzemek Kitszel } 2334*5de6c855SPrzemek Kitszel 2335*5de6c855SPrzemek Kitszel stat = kzalloc(sizeof(*stat), GFP_KERNEL); 2336*5de6c855SPrzemek Kitszel if (!stat) { 2337*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 2338*5de6c855SPrzemek Kitszel dev_dbg(dev, "Alloc stat for VF %d failed\n", vf->vf_id); 2339*5de6c855SPrzemek Kitszel goto err_exit; 2340*5de6c855SPrzemek Kitszel } 2341*5de6c855SPrzemek Kitszel 2342*5de6c855SPrzemek Kitszel len = sizeof(*stat); 2343*5de6c855SPrzemek Kitszel 2344*5de6c855SPrzemek Kitszel conf = ice_vc_fdir_lookup_entry(vf, fltr->flow_id); 2345*5de6c855SPrzemek Kitszel if (!conf) { 2346*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2347*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST; 2348*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: FDIR invalid flow_id:0x%X\n", 2349*5de6c855SPrzemek Kitszel vf->vf_id, fltr->flow_id); 2350*5de6c855SPrzemek Kitszel goto err_exit; 2351*5de6c855SPrzemek Kitszel } 2352*5de6c855SPrzemek Kitszel 2353*5de6c855SPrzemek Kitszel /* Just return failure when ctrl_vsi idx is invalid */ 2354*5de6c855SPrzemek Kitszel if (vf->ctrl_vsi_idx == ICE_NO_VSI) { 2355*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2356*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2357*5de6c855SPrzemek Kitszel dev_err(dev, "Invalid FDIR ctrl_vsi for VF %d\n", vf->vf_id); 2358*5de6c855SPrzemek Kitszel goto err_exit; 2359*5de6c855SPrzemek Kitszel } 2360*5de6c855SPrzemek Kitszel 2361*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_set_irq_ctx(vf, conf, VIRTCHNL_OP_DEL_FDIR_FILTER); 2362*5de6c855SPrzemek Kitszel if (ret) { 2363*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2364*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2365*5de6c855SPrzemek Kitszel dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id); 2366*5de6c855SPrzemek Kitszel goto err_exit; 2367*5de6c855SPrzemek Kitszel } 2368*5de6c855SPrzemek Kitszel 2369*5de6c855SPrzemek Kitszel /* For raw FDIR filters created by the parser */ 2370*5de6c855SPrzemek Kitszel if (conf->parser_ena) { 2371*5de6c855SPrzemek Kitszel ret = ice_vc_del_fdir_raw(vf, conf, &v_ret, stat, len); 2372*5de6c855SPrzemek Kitszel if (ret) 2373*5de6c855SPrzemek Kitszel goto err_del_tmr; 2374*5de6c855SPrzemek Kitszel goto exit; 2375*5de6c855SPrzemek Kitszel } 2376*5de6c855SPrzemek Kitszel 2377*5de6c855SPrzemek Kitszel is_tun = ice_fdir_is_tunnel(conf->ttype); 2378*5de6c855SPrzemek Kitszel ret = ice_vc_fdir_write_fltr(vf, conf, false, is_tun); 2379*5de6c855SPrzemek Kitszel if (ret) { 2380*5de6c855SPrzemek Kitszel v_ret = VIRTCHNL_STATUS_SUCCESS; 2381*5de6c855SPrzemek Kitszel stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; 2382*5de6c855SPrzemek Kitszel dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n", 2383*5de6c855SPrzemek Kitszel vf->vf_id, ret); 2384*5de6c855SPrzemek Kitszel goto err_del_tmr; 2385*5de6c855SPrzemek Kitszel } 2386*5de6c855SPrzemek Kitszel 2387*5de6c855SPrzemek Kitszel /* Remove unused profiles to avoid unexpected behaviors */ 2388*5de6c855SPrzemek Kitszel input = &conf->input; 2389*5de6c855SPrzemek Kitszel flow = input->flow_type; 2390*5de6c855SPrzemek Kitszel if (fdir->fdir_fltr_cnt[flow][is_tun] == 1) 2391*5de6c855SPrzemek Kitszel ice_vc_fdir_rem_prof(vf, flow, is_tun); 2392*5de6c855SPrzemek Kitszel 2393*5de6c855SPrzemek Kitszel exit: 2394*5de6c855SPrzemek Kitszel kfree(stat); 2395*5de6c855SPrzemek Kitszel 2396*5de6c855SPrzemek Kitszel return ret; 2397*5de6c855SPrzemek Kitszel 2398*5de6c855SPrzemek Kitszel err_del_tmr: 2399*5de6c855SPrzemek Kitszel ice_vc_fdir_clear_irq_ctx(vf); 2400*5de6c855SPrzemek Kitszel err_exit: 2401*5de6c855SPrzemek Kitszel ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_FDIR_FILTER, v_ret, 2402*5de6c855SPrzemek Kitszel (u8 *)stat, len); 2403*5de6c855SPrzemek Kitszel kfree(stat); 2404*5de6c855SPrzemek Kitszel return ret; 2405*5de6c855SPrzemek Kitszel } 2406*5de6c855SPrzemek Kitszel 2407*5de6c855SPrzemek Kitszel /** 2408*5de6c855SPrzemek Kitszel * ice_vf_fdir_init - init FDIR resource for VF 2409*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 2410*5de6c855SPrzemek Kitszel */ 2411*5de6c855SPrzemek Kitszel void ice_vf_fdir_init(struct ice_vf *vf) 2412*5de6c855SPrzemek Kitszel { 2413*5de6c855SPrzemek Kitszel struct ice_vf_fdir *fdir = &vf->fdir; 2414*5de6c855SPrzemek Kitszel 2415*5de6c855SPrzemek Kitszel idr_init(&fdir->fdir_rule_idr); 2416*5de6c855SPrzemek Kitszel INIT_LIST_HEAD(&fdir->fdir_rule_list); 2417*5de6c855SPrzemek Kitszel 2418*5de6c855SPrzemek Kitszel spin_lock_init(&fdir->ctx_lock); 2419*5de6c855SPrzemek Kitszel fdir->ctx_irq.flags = 0; 2420*5de6c855SPrzemek Kitszel fdir->ctx_done.flags = 0; 2421*5de6c855SPrzemek Kitszel ice_vc_fdir_reset_cnt_all(fdir); 2422*5de6c855SPrzemek Kitszel } 2423*5de6c855SPrzemek Kitszel 2424*5de6c855SPrzemek Kitszel /** 2425*5de6c855SPrzemek Kitszel * ice_vf_fdir_exit - destroy FDIR resource for VF 2426*5de6c855SPrzemek Kitszel * @vf: pointer to the VF info 2427*5de6c855SPrzemek Kitszel */ 2428*5de6c855SPrzemek Kitszel void ice_vf_fdir_exit(struct ice_vf *vf) 2429*5de6c855SPrzemek Kitszel { 2430*5de6c855SPrzemek Kitszel ice_vc_fdir_flush_entry(vf); 2431*5de6c855SPrzemek Kitszel idr_destroy(&vf->fdir.fdir_rule_idr); 2432*5de6c855SPrzemek Kitszel ice_vc_fdir_rem_prof_all(vf); 2433*5de6c855SPrzemek Kitszel ice_vc_fdir_free_prof_all(vf); 2434*5de6c855SPrzemek Kitszel } 2435