The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ice/ice_flow.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* SPDX-License-Identifier: BSD-3-Clause */
    2 /*  Copyright (c) 2021, Intel Corporation
    3  *  All rights reserved.
    4  *
    5  *  Redistribution and use in source and binary forms, with or without
    6  *  modification, are permitted provided that the following conditions are met:
    7  *
    8  *   1. Redistributions of source code must retain the above copyright notice,
    9  *      this list of conditions and the following disclaimer.
   10  *
   11  *   2. Redistributions in binary form must reproduce the above copyright
   12  *      notice, this list of conditions and the following disclaimer in the
   13  *      documentation and/or other materials provided with the distribution.
   14  *
   15  *   3. Neither the name of the Intel Corporation nor the names of its
   16  *      contributors may be used to endorse or promote products derived from
   17  *      this software without specific prior written permission.
   18  *
   19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   23  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  *  POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 /*$FreeBSD$*/
   32 
   33 #include "ice_common.h"
   34 #include "ice_flow.h"
   35 
   36 /* Size of known protocol header fields */
   37 #define ICE_FLOW_FLD_SZ_ETH_TYPE        2
   38 #define ICE_FLOW_FLD_SZ_VLAN            2
   39 #define ICE_FLOW_FLD_SZ_IPV4_ADDR       4
   40 #define ICE_FLOW_FLD_SZ_IPV6_ADDR       16
   41 #define ICE_FLOW_FLD_SZ_IP_DSCP         1
   42 #define ICE_FLOW_FLD_SZ_IP_TTL          1
   43 #define ICE_FLOW_FLD_SZ_IP_PROT         1
   44 #define ICE_FLOW_FLD_SZ_PORT            2
   45 #define ICE_FLOW_FLD_SZ_TCP_FLAGS       1
   46 #define ICE_FLOW_FLD_SZ_ICMP_TYPE       1
   47 #define ICE_FLOW_FLD_SZ_ICMP_CODE       1
   48 #define ICE_FLOW_FLD_SZ_ARP_OPER        2
   49 #define ICE_FLOW_FLD_SZ_GRE_KEYID       4
   50 
   51 /* Describe properties of a protocol header field */
   52 struct ice_flow_field_info {
   53         enum ice_flow_seg_hdr hdr;
   54         s16 off;        /* Offset from start of a protocol header, in bits */
   55         u16 size;       /* Size of fields in bits */
   56 };
   57 
   58 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
   59         .hdr = _hdr, \
   60         .off = (_offset_bytes) * BITS_PER_BYTE, \
   61         .size = (_size_bytes) * BITS_PER_BYTE, \
   62 }
   63 
   64 /* Table containing properties of supported protocol header fields */
   65 static const
   66 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
   67         /* Ether */
   68         /* ICE_FLOW_FIELD_IDX_ETH_DA */
   69         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
   70         /* ICE_FLOW_FIELD_IDX_ETH_SA */
   71         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
   72         /* ICE_FLOW_FIELD_IDX_S_VLAN */
   73         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
   74         /* ICE_FLOW_FIELD_IDX_C_VLAN */
   75         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
   76         /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
   77         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
   78         /* IPv4 / IPv6 */
   79         /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
   80         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, ICE_FLOW_FLD_SZ_IP_DSCP),
   81         /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
   82         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP),
   83         /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
   84         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, ICE_FLOW_FLD_SZ_IP_TTL),
   85         /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
   86         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
   87         /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
   88         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 7, ICE_FLOW_FLD_SZ_IP_TTL),
   89         /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
   90         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 6, ICE_FLOW_FLD_SZ_IP_PROT),
   91         /* ICE_FLOW_FIELD_IDX_IPV4_SA */
   92         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
   93         /* ICE_FLOW_FIELD_IDX_IPV4_DA */
   94         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
   95         /* ICE_FLOW_FIELD_IDX_IPV6_SA */
   96         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
   97         /* ICE_FLOW_FIELD_IDX_IPV6_DA */
   98         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
   99         /* Transport */
  100         /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
  101         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
  102         /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
  103         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
  104         /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
  105         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
  106         /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
  107         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
  108         /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
  109         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
  110         /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
  111         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
  112         /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
  113         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
  114         /* ARP */
  115         /* ICE_FLOW_FIELD_IDX_ARP_SIP */
  116         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
  117         /* ICE_FLOW_FIELD_IDX_ARP_DIP */
  118         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
  119         /* ICE_FLOW_FIELD_IDX_ARP_SHA */
  120         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
  121         /* ICE_FLOW_FIELD_IDX_ARP_DHA */
  122         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
  123         /* ICE_FLOW_FIELD_IDX_ARP_OP */
  124         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
  125         /* ICMP */
  126         /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
  127         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
  128         /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
  129         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
  130         /* GRE */
  131         /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
  132         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
  133 };
  134 
  135 /* Bitmaps indicating relevant packet types for a particular protocol header
  136  *
  137  * Packet types for packets with an Outer/First/Single MAC header
  138  */
  139 static const u32 ice_ptypes_mac_ofos[] = {
  140         0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
  141         0x0000077E, 0x00000000, 0x00000000, 0x00000000,
  142         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  143         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  144         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  145         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  146         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  147         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  148 };
  149 
  150 /* Packet types for packets with an Innermost/Last MAC VLAN header */
  151 static const u32 ice_ptypes_macvlan_il[] = {
  152         0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
  153         0x0000077E, 0x00000000, 0x00000000, 0x00000000,
  154         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  155         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  156         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  157         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  158         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  159         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  160 };
  161 
  162 /* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
  163  * does NOT include IPV4 other PTYPEs
  164  */
  165 static const u32 ice_ptypes_ipv4_ofos[] = {
  166         0x1D800000, 0x04000800, 0x00000000, 0x00000000,
  167         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  168         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  169         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  170         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  171         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  172         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  173         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  174 };
  175 
  176 /* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
  177  * includes IPV4 other PTYPEs
  178  */
  179 static const u32 ice_ptypes_ipv4_ofos_all[] = {
  180         0x1D800000, 0x04000800, 0x00000000, 0x00000000,
  181         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  182         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  183         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  184         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  185         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  186         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  187         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  188 };
  189 
  190 /* Packet types for packets with an Innermost/Last IPv4 header */
  191 static const u32 ice_ptypes_ipv4_il[] = {
  192         0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
  193         0x0000000E, 0x00000000, 0x00000000, 0x00000000,
  194         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  195         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  196         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  197         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  198         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  199         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  200 };
  201 
  202 /* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
  203  * does NOT include IVP6 other PTYPEs
  204  */
  205 static const u32 ice_ptypes_ipv6_ofos[] = {
  206         0x00000000, 0x00000000, 0x76000000, 0x10002000,
  207         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  208         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  209         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  210         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  211         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  212         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  213         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  214 };
  215 
  216 /* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
  217  * includes IPV6 other PTYPEs
  218  */
  219 static const u32 ice_ptypes_ipv6_ofos_all[] = {
  220         0x00000000, 0x00000000, 0x76000000, 0x10002000,
  221         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  222         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  223         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  224         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  225         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  226         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  227         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  228 };
  229 
  230 /* Packet types for packets with an Innermost/Last IPv6 header */
  231 static const u32 ice_ptypes_ipv6_il[] = {
  232         0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
  233         0x00000770, 0x00000000, 0x00000000, 0x00000000,
  234         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  235         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  236         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  237         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  238         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  239         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  240 };
  241 
  242 /* Packet types for packets with an Outer/First/Single
  243  * non-frag IPv4 header - no L4
  244  */
  245 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
  246         0x10800000, 0x04000800, 0x00000000, 0x00000000,
  247         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  248         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  249         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  250         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  251         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  252         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  253         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  254 };
  255 
  256 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
  257 static const u32 ice_ptypes_ipv4_il_no_l4[] = {
  258         0x60000000, 0x18043008, 0x80000002, 0x6010c021,
  259         0x00000008, 0x00000000, 0x00000000, 0x00000000,
  260         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  261         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  262         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  263         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  264         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  265         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  266 };
  267 
  268 /* Packet types for packets with an Outer/First/Single
  269  * non-frag IPv6 header - no L4
  270  */
  271 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
  272         0x00000000, 0x00000000, 0x42000000, 0x10002000,
  273         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  274         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  275         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  276         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  277         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  278         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  279         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  280 };
  281 
  282 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
  283 static const u32 ice_ptypes_ipv6_il_no_l4[] = {
  284         0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
  285         0x00000430, 0x00000000, 0x00000000, 0x00000000,
  286         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  287         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  288         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  289         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  290         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  291         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  292 };
  293 
  294 /* Packet types for packets with an Outermost/First ARP header */
  295 static const u32 ice_ptypes_arp_of[] = {
  296         0x00000800, 0x00000000, 0x00000000, 0x00000000,
  297         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  298         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  299         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  300         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  301         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  302         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  303         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  304 };
  305 
  306 /* UDP Packet types for non-tunneled packets or tunneled
  307  * packets with inner UDP.
  308  */
  309 static const u32 ice_ptypes_udp_il[] = {
  310         0x81000000, 0x20204040, 0x04000010, 0x80810102,
  311         0x00000040, 0x00000000, 0x00000000, 0x00000000,
  312         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  313         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  314         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  315         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  316         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  317         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  318 };
  319 
  320 /* Packet types for packets with an Innermost/Last TCP header */
  321 static const u32 ice_ptypes_tcp_il[] = {
  322         0x04000000, 0x80810102, 0x10000040, 0x02040408,
  323         0x00000102, 0x00000000, 0x00000000, 0x00000000,
  324         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  325         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  326         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  327         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  328         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  329         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  330 };
  331 
  332 /* Packet types for packets with an Innermost/Last SCTP header */
  333 static const u32 ice_ptypes_sctp_il[] = {
  334         0x08000000, 0x01020204, 0x20000081, 0x04080810,
  335         0x00000204, 0x00000000, 0x00000000, 0x00000000,
  336         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  337         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  338         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  339         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  340         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  341         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  342 };
  343 
  344 /* Packet types for packets with an Outermost/First ICMP header */
  345 static const u32 ice_ptypes_icmp_of[] = {
  346         0x10000000, 0x00000000, 0x00000000, 0x00000000,
  347         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  348         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  349         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  350         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  351         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  352         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  353         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  354 };
  355 
  356 /* Packet types for packets with an Innermost/Last ICMP header */
  357 static const u32 ice_ptypes_icmp_il[] = {
  358         0x00000000, 0x02040408, 0x40000102, 0x08101020,
  359         0x00000408, 0x00000000, 0x00000000, 0x00000000,
  360         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  361         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  362         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  363         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  364         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  365         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  366 };
  367 
  368 /* Packet types for packets with an Outermost/First GRE header */
  369 static const u32 ice_ptypes_gre_of[] = {
  370         0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
  371         0x0000017E, 0x00000000, 0x00000000, 0x00000000,
  372         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  373         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  374         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  375         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  376         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  377         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  378 };
  379 
  380 /* Packet types for packets with an Innermost/Last MAC header */
  381 static const u32 ice_ptypes_mac_il[] = {
  382         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  383         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  384         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  385         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  386         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  387         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  388         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  389         0x00000000, 0x00000000, 0x00000000, 0x00000000,
  390 };
  391 
  392 /* Manage parameters and info. used during the creation of a flow profile */
  393 struct ice_flow_prof_params {
  394         enum ice_block blk;
  395         u16 entry_length; /* # of bytes formatted entry will require */
  396         u8 es_cnt;
  397         struct ice_flow_prof *prof;
  398 
  399         /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
  400          * This will give us the direction flags.
  401          */
  402         struct ice_fv_word es[ICE_MAX_FV_WORDS];
  403         ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
  404 };
  405 
  406 #define ICE_FLOW_SEG_HDRS_L3_MASK       \
  407         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
  408          ICE_FLOW_SEG_HDR_ARP)
  409 #define ICE_FLOW_SEG_HDRS_L4_MASK       \
  410         (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
  411          ICE_FLOW_SEG_HDR_SCTP)
  412 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */
  413 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER      \
  414         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
  415 
  416 /**
  417  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
  418  * @segs: array of one or more packet segments that describe the flow
  419  * @segs_cnt: number of packet segments provided
  420  */
  421 static enum ice_status
  422 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
  423 {
  424         u8 i;
  425 
  426         for (i = 0; i < segs_cnt; i++) {
  427                 /* Multiple L3 headers */
  428                 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
  429                     !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
  430                         return ICE_ERR_PARAM;
  431 
  432                 /* Multiple L4 headers */
  433                 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
  434                     !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
  435                         return ICE_ERR_PARAM;
  436         }
  437 
  438         return ICE_SUCCESS;
  439 }
  440 
  441 /**
  442  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
  443  * @params: information about the flow to be processed
  444  *
  445  * This function identifies the packet types associated with the protocol
  446  * headers being present in packet segments of the specified flow profile.
  447  */
  448 static enum ice_status
  449 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
  450 {
  451         struct ice_flow_prof *prof;
  452         u8 i;
  453 
  454         ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
  455                    ICE_NONDMA_MEM);
  456 
  457         prof = params->prof;
  458 
  459         for (i = 0; i < params->prof->segs_cnt; i++) {
  460                 const ice_bitmap_t *src;
  461                 u32 hdrs;
  462 
  463                 hdrs = prof->segs[i].hdrs;
  464 
  465                 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
  466                         src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
  467                                 (const ice_bitmap_t *)ice_ptypes_mac_il;
  468                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  469                                        ICE_FLOW_PTYPE_MAX);
  470                 }
  471 
  472                 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
  473                         src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
  474                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  475                                        ICE_FLOW_PTYPE_MAX);
  476                 }
  477 
  478                 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
  479                         ice_and_bitmap(params->ptypes, params->ptypes,
  480                                        (const ice_bitmap_t *)ice_ptypes_arp_of,
  481                                        ICE_FLOW_PTYPE_MAX);
  482                 }
  483 
  484                 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
  485                     (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
  486                         src = i ?
  487                                 (const ice_bitmap_t *)ice_ptypes_ipv4_il :
  488                                 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
  489                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  490                                        ICE_FLOW_PTYPE_MAX);
  491                 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
  492                            (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
  493                         src = i ?
  494                                 (const ice_bitmap_t *)ice_ptypes_ipv6_il :
  495                                 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
  496                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  497                                        ICE_FLOW_PTYPE_MAX);
  498                 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
  499                            !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
  500                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
  501                                 (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
  502                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  503                                        ICE_FLOW_PTYPE_MAX);
  504                 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
  505                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
  506                                 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
  507                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  508                                        ICE_FLOW_PTYPE_MAX);
  509                 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
  510                            !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
  511                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
  512                                 (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
  513                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  514                                        ICE_FLOW_PTYPE_MAX);
  515                 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
  516                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
  517                                 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
  518                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  519                                        ICE_FLOW_PTYPE_MAX);
  520                 }
  521 
  522                 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
  523                         src = (const ice_bitmap_t *)ice_ptypes_udp_il;
  524                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  525                                        ICE_FLOW_PTYPE_MAX);
  526                 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
  527                         ice_and_bitmap(params->ptypes, params->ptypes,
  528                                        (const ice_bitmap_t *)ice_ptypes_tcp_il,
  529                                        ICE_FLOW_PTYPE_MAX);
  530                 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
  531                         src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
  532                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  533                                        ICE_FLOW_PTYPE_MAX);
  534                 }
  535 
  536                 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
  537                         src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
  538                                 (const ice_bitmap_t *)ice_ptypes_icmp_il;
  539                         ice_and_bitmap(params->ptypes, params->ptypes, src,
  540                                        ICE_FLOW_PTYPE_MAX);
  541                 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
  542                         if (!i) {
  543                                 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
  544                                 ice_and_bitmap(params->ptypes, params->ptypes,
  545                                                src, ICE_FLOW_PTYPE_MAX);
  546                         }
  547                 }
  548         }
  549 
  550         return ICE_SUCCESS;
  551 }
  552 
  553 /**
  554  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
  555  * @hw: pointer to the HW struct
  556  * @params: information about the flow to be processed
  557  * @seg: packet segment index of the field to be extracted
  558  * @fld: ID of field to be extracted
  559  *
  560  * This function determines the protocol ID, offset, and size of the given
  561  * field. It then allocates one or more extraction sequence entries for the
  562  * given field, and fill the entries with protocol ID and offset information.
  563  */
  564 static enum ice_status
  565 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
  566                     u8 seg, enum ice_flow_field fld)
  567 {
  568         enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
  569         enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
  570         u8 fv_words = hw->blk[params->blk].es.fvw;
  571         struct ice_flow_fld_info *flds;
  572         u16 cnt, ese_bits, i;
  573         u16 off;
  574 
  575         flds = params->prof->segs[seg].fields;
  576 
  577         switch (fld) {
  578         case ICE_FLOW_FIELD_IDX_ETH_DA:
  579         case ICE_FLOW_FIELD_IDX_ETH_SA:
  580         case ICE_FLOW_FIELD_IDX_S_VLAN:
  581         case ICE_FLOW_FIELD_IDX_C_VLAN:
  582                 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
  583                 break;
  584         case ICE_FLOW_FIELD_IDX_ETH_TYPE:
  585                 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
  586                 break;
  587         case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
  588                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
  589                 break;
  590         case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
  591                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
  592                 break;
  593         case ICE_FLOW_FIELD_IDX_IPV4_TTL:
  594         case ICE_FLOW_FIELD_IDX_IPV4_PROT:
  595                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
  596 
  597                 /* TTL and PROT share the same extraction seq. entry.
  598                  * Each is considered a sibling to the other in terms of sharing
  599                  * the same extraction sequence entry.
  600                  */
  601                 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
  602                         sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
  603                 else
  604                         sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
  605                 break;
  606         case ICE_FLOW_FIELD_IDX_IPV6_TTL:
  607         case ICE_FLOW_FIELD_IDX_IPV6_PROT:
  608                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
  609 
  610                 /* TTL and PROT share the same extraction seq. entry.
  611                  * Each is considered a sibling to the other in terms of sharing
  612                  * the same extraction sequence entry.
  613                  */
  614                 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
  615                         sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
  616                 else
  617                         sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
  618                 break;
  619         case ICE_FLOW_FIELD_IDX_IPV4_SA:
  620         case ICE_FLOW_FIELD_IDX_IPV4_DA:
  621                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
  622                 break;
  623         case ICE_FLOW_FIELD_IDX_IPV6_SA:
  624         case ICE_FLOW_FIELD_IDX_IPV6_DA:
  625                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
  626                 break;
  627         case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
  628         case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
  629         case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
  630                 prot_id = ICE_PROT_TCP_IL;
  631                 break;
  632         case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
  633         case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
  634                 prot_id = ICE_PROT_UDP_IL_OR_S;
  635                 break;
  636         case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
  637         case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
  638                 prot_id = ICE_PROT_SCTP_IL;
  639                 break;
  640         case ICE_FLOW_FIELD_IDX_ARP_SIP:
  641         case ICE_FLOW_FIELD_IDX_ARP_DIP:
  642         case ICE_FLOW_FIELD_IDX_ARP_SHA:
  643         case ICE_FLOW_FIELD_IDX_ARP_DHA:
  644         case ICE_FLOW_FIELD_IDX_ARP_OP:
  645                 prot_id = ICE_PROT_ARP_OF;
  646                 break;
  647         case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
  648         case ICE_FLOW_FIELD_IDX_ICMP_CODE:
  649                 /* ICMP type and code share the same extraction seq. entry */
  650                 prot_id = (params->prof->segs[seg].hdrs &
  651                            ICE_FLOW_SEG_HDR_IPV4) ?
  652                         ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
  653                 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
  654                         ICE_FLOW_FIELD_IDX_ICMP_CODE :
  655                         ICE_FLOW_FIELD_IDX_ICMP_TYPE;
  656                 break;
  657         case ICE_FLOW_FIELD_IDX_GRE_KEYID:
  658                 prot_id = ICE_PROT_GRE_OF;
  659                 break;
  660         default:
  661                 return ICE_ERR_NOT_IMPL;
  662         }
  663 
  664         /* Each extraction sequence entry is a word in size, and extracts a
  665          * word-aligned offset from a protocol header.
  666          */
  667         ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
  668 
  669         flds[fld].xtrct.prot_id = prot_id;
  670         flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
  671                 ICE_FLOW_FV_EXTRACT_SZ;
  672         flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
  673         flds[fld].xtrct.idx = params->es_cnt;
  674 
  675         /* Adjust the next field-entry index after accommodating the number of
  676          * entries this field consumes
  677          */
  678         cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
  679                                   ice_flds_info[fld].size, ese_bits);
  680 
  681         /* Fill in the extraction sequence entries needed for this field */
  682         off = flds[fld].xtrct.off;
  683         for (i = 0; i < cnt; i++) {
  684                 /* Only consume an extraction sequence entry if there is no
  685                  * sibling field associated with this field or the sibling entry
  686                  * already extracts the word shared with this field.
  687                  */
  688                 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
  689                     flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
  690                     flds[sib].xtrct.off != off) {
  691                         u8 idx;
  692 
  693                         /* Make sure the number of extraction sequence required
  694                          * does not exceed the block's capability
  695                          */
  696                         if (params->es_cnt >= fv_words)
  697                                 return ICE_ERR_MAX_LIMIT;
  698 
  699                         /* some blocks require a reversed field vector layout */
  700                         if (hw->blk[params->blk].es.reverse)
  701                                 idx = fv_words - params->es_cnt - 1;
  702                         else
  703                                 idx = params->es_cnt;
  704 
  705                         params->es[idx].prot_id = prot_id;
  706                         params->es[idx].off = off;
  707                         params->es_cnt++;
  708                 }
  709 
  710                 off += ICE_FLOW_FV_EXTRACT_SZ;
  711         }
  712 
  713         return ICE_SUCCESS;
  714 }
  715 
  716 /**
  717  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
  718  * @hw: pointer to the HW struct
  719  * @params: information about the flow to be processed
  720  *
  721  * This function iterates through all matched fields in the given segments, and
  722  * creates an extraction sequence for the fields.
  723  */
  724 static enum ice_status
  725 ice_flow_create_xtrct_seq(struct ice_hw *hw,
  726                           struct ice_flow_prof_params *params)
  727 {
  728         enum ice_status status = ICE_SUCCESS;
  729         u8 i;
  730 
  731         for (i = 0; i < params->prof->segs_cnt; i++) {
  732                 u64 match = params->prof->segs[i].match;
  733                 enum ice_flow_field j;
  734 
  735                 ice_for_each_set_bit(j, (ice_bitmap_t *)&match,
  736                                      ICE_FLOW_FIELD_IDX_MAX) {
  737                         status = ice_flow_xtract_fld(hw, params, i, j);
  738                         if (status)
  739                                 return status;
  740                         ice_clear_bit(j, (ice_bitmap_t *)&match);
  741                 }
  742         }
  743 
  744         return status;
  745 }
  746 
  747 /**
  748  * ice_flow_proc_segs - process all packet segments associated with a profile
  749  * @hw: pointer to the HW struct
  750  * @params: information about the flow to be processed
  751  */
  752 static enum ice_status
  753 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
  754 {
  755         enum ice_status status;
  756 
  757         status = ice_flow_proc_seg_hdrs(params);
  758         if (status)
  759                 return status;
  760 
  761         status = ice_flow_create_xtrct_seq(hw, params);
  762         if (status)
  763                 return status;
  764 
  765         switch (params->blk) {
  766         case ICE_BLK_RSS:
  767                 status = ICE_SUCCESS;
  768                 break;
  769         default:
  770                 return ICE_ERR_NOT_IMPL;
  771         }
  772 
  773         return status;
  774 }
  775 
  776 #define ICE_FLOW_FIND_PROF_CHK_FLDS     0x00000001
  777 #define ICE_FLOW_FIND_PROF_CHK_VSI      0x00000002
  778 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR  0x00000004
  779 
  780 /**
  781  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
  782  * @hw: pointer to the HW struct
  783  * @blk: classification stage
  784  * @dir: flow direction
  785  * @segs: array of one or more packet segments that describe the flow
  786  * @segs_cnt: number of packet segments provided
  787  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
  788  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
  789  */
  790 static struct ice_flow_prof *
  791 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
  792                          enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
  793                          u8 segs_cnt, u16 vsi_handle, u32 conds)
  794 {
  795         struct ice_flow_prof *p, *prof = NULL;
  796 
  797         ice_acquire_lock(&hw->fl_profs_locks[blk]);
  798         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
  799                 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
  800                     segs_cnt && segs_cnt == p->segs_cnt) {
  801                         u8 i;
  802 
  803                         /* Check for profile-VSI association if specified */
  804                         if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
  805                             ice_is_vsi_valid(hw, vsi_handle) &&
  806                             !ice_is_bit_set(p->vsis, vsi_handle))
  807                                 continue;
  808 
  809                         /* Protocol headers must be checked. Matched fields are
  810                          * checked if specified.
  811                          */
  812                         for (i = 0; i < segs_cnt; i++)
  813                                 if (segs[i].hdrs != p->segs[i].hdrs ||
  814                                     ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
  815                                      segs[i].match != p->segs[i].match))
  816                                         break;
  817 
  818                         /* A match is found if all segments are matched */
  819                         if (i == segs_cnt) {
  820                                 prof = p;
  821                                 break;
  822                         }
  823                 }
  824         ice_release_lock(&hw->fl_profs_locks[blk]);
  825 
  826         return prof;
  827 }
  828 
  829 /**
  830  * ice_flow_find_prof - Look up a profile matching headers and matched fields
  831  * @hw: pointer to the HW struct
  832  * @blk: classification stage
  833  * @dir: flow direction
  834  * @segs: array of one or more packet segments that describe the flow
  835  * @segs_cnt: number of packet segments provided
  836  */
  837 u64
  838 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
  839                    struct ice_flow_seg_info *segs, u8 segs_cnt)
  840 {
  841         struct ice_flow_prof *p;
  842 
  843         p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
  844                                      ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
  845 
  846         return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
  847 }
  848 
  849 /**
  850  * ice_flow_find_prof_id - Look up a profile with given profile ID
  851  * @hw: pointer to the HW struct
  852  * @blk: classification stage
  853  * @prof_id: unique ID to identify this flow profile
  854  */
  855 static struct ice_flow_prof *
  856 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
  857 {
  858         struct ice_flow_prof *p;
  859 
  860         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
  861                 if (p->id == prof_id)
  862                         return p;
  863 
  864         return NULL;
  865 }
  866 
  867 /**
  868  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
  869  * @hw: pointer to the HW struct
  870  * @blk: classification stage
  871  * @prof_id: the profile ID handle
  872  * @hw_prof_id: pointer to variable to receive the HW profile ID
  873  */
  874 enum ice_status
  875 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
  876                      u8 *hw_prof_id)
  877 {
  878         enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
  879         struct ice_prof_map *map;
  880 
  881         ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
  882         map = ice_search_prof_id(hw, blk, prof_id);
  883         if (map) {
  884                 *hw_prof_id = map->prof_id;
  885                 status = ICE_SUCCESS;
  886         }
  887         ice_release_lock(&hw->blk[blk].es.prof_map_lock);
  888         return status;
  889 }
  890 
  891 /**
  892  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
  893  * @hw: pointer to the HW struct
  894  * @blk: classification stage
  895  * @dir: flow direction
  896  * @prof_id: unique ID to identify this flow profile
  897  * @segs: array of one or more packet segments that describe the flow
  898  * @segs_cnt: number of packet segments provided
  899  * @acts: array of default actions
  900  * @acts_cnt: number of default actions
  901  * @prof: stores the returned flow profile added
  902  *
  903  * Assumption: the caller has acquired the lock to the profile list
  904  */
  905 static enum ice_status
  906 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
  907                        enum ice_flow_dir dir, u64 prof_id,
  908                        struct ice_flow_seg_info *segs, u8 segs_cnt,
  909                        struct ice_flow_action *acts, u8 acts_cnt,
  910                        struct ice_flow_prof **prof)
  911 {
  912         struct ice_flow_prof_params *params;
  913         enum ice_status status;
  914         u8 i;
  915 
  916         if (!prof || (acts_cnt && !acts))
  917                 return ICE_ERR_BAD_PTR;
  918 
  919         params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
  920         if (!params)
  921                 return ICE_ERR_NO_MEMORY;
  922 
  923         params->prof = (struct ice_flow_prof *)
  924                 ice_malloc(hw, sizeof(*params->prof));
  925         if (!params->prof) {
  926                 status = ICE_ERR_NO_MEMORY;
  927                 goto free_params;
  928         }
  929 
  930         /* initialize extraction sequence to all invalid (0xff) */
  931         for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
  932                 params->es[i].prot_id = ICE_PROT_INVALID;
  933                 params->es[i].off = ICE_FV_OFFSET_INVAL;
  934         }
  935 
  936         params->blk = blk;
  937         params->prof->id = prof_id;
  938         params->prof->dir = dir;
  939         params->prof->segs_cnt = segs_cnt;
  940 
  941         /* Make a copy of the segments that need to be persistent in the flow
  942          * profile instance
  943          */
  944         for (i = 0; i < segs_cnt; i++)
  945                 ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
  946                            ICE_NONDMA_TO_NONDMA);
  947 
  948         status = ice_flow_proc_segs(hw, params);
  949         if (status) {
  950                 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
  951                 goto out;
  952         }
  953 
  954         /* Add a HW profile for this flow profile */
  955         status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
  956                               params->es);
  957         if (status) {
  958                 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
  959                 goto out;
  960         }
  961 
  962         *prof = params->prof;
  963 
  964 out:
  965         if (status) {
  966                 ice_free(hw, params->prof);
  967         }
  968 free_params:
  969         ice_free(hw, params);
  970 
  971         return status;
  972 }
  973 
  974 /**
  975  * ice_flow_rem_prof_sync - remove a flow profile
  976  * @hw: pointer to the hardware structure
  977  * @blk: classification stage
  978  * @prof: pointer to flow profile to remove
  979  *
  980  * Assumption: the caller has acquired the lock to the profile list
  981  */
  982 static enum ice_status
  983 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
  984                        struct ice_flow_prof *prof)
  985 {
  986         enum ice_status status;
  987 
  988         /* Remove all hardware profiles associated with this flow profile */
  989         status = ice_rem_prof(hw, blk, prof->id);
  990         if (!status) {
  991                 LIST_DEL(&prof->l_entry);
  992                 ice_free(hw, prof);
  993         }
  994 
  995         return status;
  996 }
  997 
  998 /**
  999  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
 1000  * @hw: pointer to the hardware structure
 1001  * @blk: classification stage
 1002  * @vsi_handle: software VSI handle
 1003  * @vsig: target VSI group
 1004  *
 1005  * Assumption: the caller has already verified that the VSI to
 1006  * be added has the same characteristics as the VSIG and will
 1007  * thereby have access to all resources added to that VSIG.
 1008  */
 1009 enum ice_status
 1010 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
 1011                         u16 vsig)
 1012 {
 1013         enum ice_status status;
 1014 
 1015         if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
 1016                 return ICE_ERR_PARAM;
 1017 
 1018         ice_acquire_lock(&hw->fl_profs_locks[blk]);
 1019         status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
 1020                                   vsig);
 1021         ice_release_lock(&hw->fl_profs_locks[blk]);
 1022 
 1023         return status;
 1024 }
 1025 
 1026 /**
 1027  * ice_flow_assoc_prof - associate a VSI with a flow profile
 1028  * @hw: pointer to the hardware structure
 1029  * @blk: classification stage
 1030  * @prof: pointer to flow profile
 1031  * @vsi_handle: software VSI handle
 1032  *
 1033  * Assumption: the caller has acquired the lock to the profile list
 1034  * and the software VSI handle has been validated
 1035  */
 1036 static enum ice_status
 1037 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
 1038                     struct ice_flow_prof *prof, u16 vsi_handle)
 1039 {
 1040         enum ice_status status = ICE_SUCCESS;
 1041 
 1042         if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
 1043                 status = ice_add_prof_id_flow(hw, blk,
 1044                                               ice_get_hw_vsi_num(hw,
 1045                                                                  vsi_handle),
 1046                                               prof->id);
 1047                 if (!status)
 1048                         ice_set_bit(vsi_handle, prof->vsis);
 1049                 else
 1050                         ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
 1051                                   status);
 1052         }
 1053 
 1054         return status;
 1055 }
 1056 
 1057 /**
 1058  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
 1059  * @hw: pointer to the hardware structure
 1060  * @blk: classification stage
 1061  * @prof: pointer to flow profile
 1062  * @vsi_handle: software VSI handle
 1063  *
 1064  * Assumption: the caller has acquired the lock to the profile list
 1065  * and the software VSI handle has been validated
 1066  */
 1067 static enum ice_status
 1068 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
 1069                        struct ice_flow_prof *prof, u16 vsi_handle)
 1070 {
 1071         enum ice_status status = ICE_SUCCESS;
 1072 
 1073         if (ice_is_bit_set(prof->vsis, vsi_handle)) {
 1074                 status = ice_rem_prof_id_flow(hw, blk,
 1075                                               ice_get_hw_vsi_num(hw,
 1076                                                                  vsi_handle),
 1077                                               prof->id);
 1078                 if (!status)
 1079                         ice_clear_bit(vsi_handle, prof->vsis);
 1080                 else
 1081                         ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
 1082                                   status);
 1083         }
 1084 
 1085         return status;
 1086 }
 1087 
 1088 /**
 1089  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
 1090  * @hw: pointer to the HW struct
 1091  * @blk: classification stage
 1092  * @dir: flow direction
 1093  * @prof_id: unique ID to identify this flow profile
 1094  * @segs: array of one or more packet segments that describe the flow
 1095  * @segs_cnt: number of packet segments provided
 1096  * @acts: array of default actions
 1097  * @acts_cnt: number of default actions
 1098  * @prof: stores the returned flow profile added
 1099  */
 1100 static enum ice_status
 1101 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
 1102                   u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
 1103                   struct ice_flow_action *acts, u8 acts_cnt,
 1104                   struct ice_flow_prof **prof)
 1105 {
 1106         enum ice_status status;
 1107 
 1108         if (segs_cnt > ICE_FLOW_SEG_MAX)
 1109                 return ICE_ERR_MAX_LIMIT;
 1110 
 1111         if (!segs_cnt)
 1112                 return ICE_ERR_PARAM;
 1113 
 1114         if (!segs)
 1115                 return ICE_ERR_BAD_PTR;
 1116 
 1117         status = ice_flow_val_hdrs(segs, segs_cnt);
 1118         if (status)
 1119                 return status;
 1120 
 1121         ice_acquire_lock(&hw->fl_profs_locks[blk]);
 1122 
 1123         status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
 1124                                         acts, acts_cnt, prof);
 1125         if (!status)
 1126                 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
 1127 
 1128         ice_release_lock(&hw->fl_profs_locks[blk]);
 1129 
 1130         return status;
 1131 }
 1132 
 1133 /**
 1134  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
 1135  * @hw: pointer to the HW struct
 1136  * @blk: the block for which the flow profile is to be removed
 1137  * @prof_id: unique ID of the flow profile to be removed
 1138  */
 1139 static enum ice_status
 1140 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
 1141 {
 1142         struct ice_flow_prof *prof;
 1143         enum ice_status status;
 1144 
 1145         ice_acquire_lock(&hw->fl_profs_locks[blk]);
 1146 
 1147         prof = ice_flow_find_prof_id(hw, blk, prof_id);
 1148         if (!prof) {
 1149                 status = ICE_ERR_DOES_NOT_EXIST;
 1150                 goto out;
 1151         }
 1152 
 1153         /* prof becomes invalid after the call */
 1154         status = ice_flow_rem_prof_sync(hw, blk, prof);
 1155 
 1156 out:
 1157         ice_release_lock(&hw->fl_profs_locks[blk]);
 1158 
 1159         return status;
 1160 }
 1161 
 1162 /**
 1163  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
 1164  * @seg: packet segment the field being set belongs to
 1165  * @fld: field to be set
 1166  * @field_type: type of the field
 1167  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
 1168  *           entry's input buffer
 1169  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
 1170  *            input buffer
 1171  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
 1172  *            entry's input buffer
 1173  *
 1174  * This helper function stores information of a field being matched, including
 1175  * the type of the field and the locations of the value to match, the mask, and
 1176  * the upper-bound value in the start of the input buffer for a flow entry.
 1177  * This function should only be used for fixed-size data structures.
 1178  *
 1179  * This function also opportunistically determines the protocol headers to be
 1180  * present based on the fields being set. Some fields cannot be used alone to
 1181  * determine the protocol headers present. Sometimes, fields for particular
 1182  * protocol headers are not matched. In those cases, the protocol headers
 1183  * must be explicitly set.
 1184  */
 1185 static void
 1186 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
 1187                      enum ice_flow_fld_match_type field_type, u16 val_loc,
 1188                      u16 mask_loc, u16 last_loc)
 1189 {
 1190         u64 bit = BIT_ULL(fld);
 1191 
 1192         seg->match |= bit;
 1193         if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
 1194                 seg->range |= bit;
 1195 
 1196         seg->fields[fld].type = field_type;
 1197         seg->fields[fld].src.val = val_loc;
 1198         seg->fields[fld].src.mask = mask_loc;
 1199         seg->fields[fld].src.last = last_loc;
 1200 
 1201         ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
 1202 }
 1203 
 1204 /**
 1205  * ice_flow_set_fld - specifies locations of field from entry's input buffer
 1206  * @seg: packet segment the field being set belongs to
 1207  * @fld: field to be set
 1208  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
 1209  *           entry's input buffer
 1210  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
 1211  *            input buffer
 1212  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
 1213  *            entry's input buffer
 1214  * @range: indicate if field being matched is to be in a range
 1215  *
 1216  * This function specifies the locations, in the form of byte offsets from the
 1217  * start of the input buffer for a flow entry, from where the value to match,
 1218  * the mask value, and upper value can be extracted. These locations are then
 1219  * stored in the flow profile. When adding a flow entry associated with the
 1220  * flow profile, these locations will be used to quickly extract the values and
 1221  * create the content of a match entry. This function should only be used for
 1222  * fixed-size data structures.
 1223  */
 1224 static void
 1225 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
 1226                  u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
 1227 {
 1228         enum ice_flow_fld_match_type t = range ?
 1229                 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
 1230 
 1231         ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
 1232 }
 1233 
 1234 /**
 1235  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
 1236  * @seg: packet segment the field being set belongs to
 1237  * @fld: field to be set
 1238  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
 1239  *           entry's input buffer
 1240  * @pref_loc: location of prefix value from entry's input buffer
 1241  * @pref_sz: size of the location holding the prefix value
 1242  *
 1243  * This function specifies the locations, in the form of byte offsets from the
 1244  * start of the input buffer for a flow entry, from where the value to match
 1245  * and the IPv4 prefix value can be extracted. These locations are then stored
 1246  * in the flow profile. When adding flow entries to the associated flow profile,
 1247  * these locations can be used to quickly extract the values to create the
 1248  * content of a match entry. This function should only be used for fixed-size
 1249  * data structures.
 1250  */
 1251 void
 1252 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
 1253                         u16 val_loc, u16 pref_loc, u8 pref_sz)
 1254 {
 1255         /* For this type of field, the "mask" location is for the prefix value's
 1256          * location and the "last" location is for the size of the location of
 1257          * the prefix value.
 1258          */
 1259         ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
 1260                              pref_loc, (u16)pref_sz);
 1261 }
 1262 
 1263 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
 1264         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
 1265 
 1266 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
 1267         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
 1268 
 1269 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
 1270         (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
 1271          ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
 1272 
 1273 /**
 1274  * ice_flow_set_rss_seg_info - setup packet segments for RSS
 1275  * @segs: pointer to the flow field segment(s)
 1276  * @seg_cnt: segment count
 1277  * @cfg: configure parameters
 1278  *
 1279  * Helper function to extract fields from hash bitmap and use flow
 1280  * header value to set flow field segment for further use in flow
 1281  * profile entry or removal.
 1282  */
 1283 static enum ice_status
 1284 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
 1285                           const struct ice_rss_hash_cfg *cfg)
 1286 {
 1287         struct ice_flow_seg_info *seg;
 1288         u64 val;
 1289         u8 i;
 1290 
 1291         /* set inner most segment */
 1292         seg = &segs[seg_cnt - 1];
 1293 
 1294         ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
 1295                              ICE_FLOW_FIELD_IDX_MAX)
 1296                 ice_flow_set_fld(seg, (enum ice_flow_field)i,
 1297                                  ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
 1298                                  ICE_FLOW_FLD_OFF_INVAL, false);
 1299 
 1300         ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
 1301 
 1302         /* set outer most header */
 1303         if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
 1304                 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
 1305                                                    ICE_FLOW_SEG_HDR_IPV_FRAG |
 1306                                                    ICE_FLOW_SEG_HDR_IPV_OTHER;
 1307         else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
 1308                 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
 1309                                                    ICE_FLOW_SEG_HDR_IPV_FRAG |
 1310                                                    ICE_FLOW_SEG_HDR_IPV_OTHER;
 1311         else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE)
 1312                 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
 1313                                                    ICE_FLOW_SEG_HDR_GRE |
 1314                                                    ICE_FLOW_SEG_HDR_IPV_OTHER;
 1315         else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
 1316                 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
 1317                                                    ICE_FLOW_SEG_HDR_GRE |
 1318                                                    ICE_FLOW_SEG_HDR_IPV_OTHER;
 1319 
 1320         if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
 1321                 return ICE_ERR_PARAM;
 1322 
 1323         val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
 1324         if (val && !ice_is_pow2(val))
 1325                 return ICE_ERR_CFG;
 1326 
 1327         val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
 1328         if (val && !ice_is_pow2(val))
 1329                 return ICE_ERR_CFG;
 1330 
 1331         return ICE_SUCCESS;
 1332 }
 1333 
 1334 /**
 1335  * ice_rem_vsi_rss_list - remove VSI from RSS list
 1336  * @hw: pointer to the hardware structure
 1337  * @vsi_handle: software VSI handle
 1338  *
 1339  * Remove the VSI from all RSS configurations in the list.
 1340  */
 1341 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
 1342 {
 1343         struct ice_rss_cfg *r, *tmp;
 1344 
 1345         if (LIST_EMPTY(&hw->rss_list_head))
 1346                 return;
 1347 
 1348         ice_acquire_lock(&hw->rss_locks);
 1349         LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
 1350                                  ice_rss_cfg, l_entry)
 1351                 if (ice_test_and_clear_bit(vsi_handle, r->vsis))
 1352                         if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
 1353                                 LIST_DEL(&r->l_entry);
 1354                                 ice_free(hw, r);
 1355                         }
 1356         ice_release_lock(&hw->rss_locks);
 1357 }
 1358 
 1359 /**
 1360  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
 1361  * @hw: pointer to the hardware structure
 1362  * @vsi_handle: software VSI handle
 1363  *
 1364  * This function will iterate through all flow profiles and disassociate
 1365  * the VSI from that profile. If the flow profile has no VSIs it will
 1366  * be removed.
 1367  */
 1368 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
 1369 {
 1370         const enum ice_block blk = ICE_BLK_RSS;
 1371         struct ice_flow_prof *p, *t;
 1372         enum ice_status status = ICE_SUCCESS;
 1373 
 1374         if (!ice_is_vsi_valid(hw, vsi_handle))
 1375                 return ICE_ERR_PARAM;
 1376 
 1377         if (LIST_EMPTY(&hw->fl_profs[blk]))
 1378                 return ICE_SUCCESS;
 1379 
 1380         ice_acquire_lock(&hw->rss_locks);
 1381         LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
 1382                                  l_entry)
 1383                 if (ice_is_bit_set(p->vsis, vsi_handle)) {
 1384                         status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
 1385                         if (status)
 1386                                 break;
 1387 
 1388                         if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
 1389                                 status = ice_flow_rem_prof(hw, blk, p->id);
 1390                                 if (status)
 1391                                         break;
 1392                         }
 1393                 }
 1394         ice_release_lock(&hw->rss_locks);
 1395 
 1396         return status;
 1397 }
 1398 
 1399 /**
 1400  * ice_get_rss_hdr_type - get a RSS profile's header type
 1401  * @prof: RSS flow profile
 1402  */
 1403 static enum ice_rss_cfg_hdr_type
 1404 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
 1405 {
 1406         enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
 1407 
 1408         if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
 1409                 hdr_type = ICE_RSS_OUTER_HEADERS;
 1410         } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
 1411                 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE)
 1412                         hdr_type = ICE_RSS_INNER_HEADERS;
 1413                 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4)
 1414                         hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
 1415                 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6)
 1416                         hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
 1417         }
 1418 
 1419         return hdr_type;
 1420 }
 1421 
 1422 /**
 1423  * ice_rem_rss_list - remove RSS configuration from list
 1424  * @hw: pointer to the hardware structure
 1425  * @vsi_handle: software VSI handle
 1426  * @prof: pointer to flow profile
 1427  *
 1428  * Assumption: lock has already been acquired for RSS list
 1429  */
 1430 static void
 1431 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
 1432 {
 1433         enum ice_rss_cfg_hdr_type hdr_type;
 1434         struct ice_rss_cfg *r, *tmp;
 1435 
 1436         /* Search for RSS hash fields associated to the VSI that match the
 1437          * hash configurations associated to the flow profile. If found
 1438          * remove from the RSS entry list of the VSI context and delete entry.
 1439          */
 1440         hdr_type = ice_get_rss_hdr_type(prof);
 1441         LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
 1442                                  ice_rss_cfg, l_entry)
 1443                 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
 1444                     r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
 1445                     r->hash.hdr_type == hdr_type) {
 1446                         ice_clear_bit(vsi_handle, r->vsis);
 1447                         if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
 1448                                 LIST_DEL(&r->l_entry);
 1449                                 ice_free(hw, r);
 1450                         }
 1451                         return;
 1452                 }
 1453 }
 1454 
 1455 /**
 1456  * ice_add_rss_list - add RSS configuration to list
 1457  * @hw: pointer to the hardware structure
 1458  * @vsi_handle: software VSI handle
 1459  * @prof: pointer to flow profile
 1460  *
 1461  * Assumption: lock has already been acquired for RSS list
 1462  */
 1463 static enum ice_status
 1464 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
 1465 {
 1466         enum ice_rss_cfg_hdr_type hdr_type;
 1467         struct ice_rss_cfg *r, *rss_cfg;
 1468 
 1469         hdr_type = ice_get_rss_hdr_type(prof);
 1470         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
 1471                             ice_rss_cfg, l_entry)
 1472                 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
 1473                     r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
 1474                     r->hash.hdr_type == hdr_type) {
 1475                         ice_set_bit(vsi_handle, r->vsis);
 1476                         return ICE_SUCCESS;
 1477                 }
 1478 
 1479         rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
 1480         if (!rss_cfg)
 1481                 return ICE_ERR_NO_MEMORY;
 1482 
 1483         rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
 1484         rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
 1485         rss_cfg->hash.hdr_type = hdr_type;
 1486         rss_cfg->hash.symm = prof->cfg.symm;
 1487         ice_set_bit(vsi_handle, rss_cfg->vsis);
 1488 
 1489         LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
 1490 
 1491         return ICE_SUCCESS;
 1492 }
 1493 
 1494 #define ICE_FLOW_PROF_HASH_S    0
 1495 #define ICE_FLOW_PROF_HASH_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
 1496 #define ICE_FLOW_PROF_HDR_S     32
 1497 #define ICE_FLOW_PROF_HDR_M     (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
 1498 #define ICE_FLOW_PROF_ENCAP_S   62
 1499 #define ICE_FLOW_PROF_ENCAP_M   (0x3ULL << ICE_FLOW_PROF_ENCAP_S)
 1500 
 1501 /* Flow profile ID format:
 1502  * [0:31] - Packet match fields
 1503  * [32:61] - Protocol header
 1504  * [62:63] - Encapsulation flag:
 1505  *           0 if non-tunneled
 1506  *           1 if tunneled
 1507  *           2 for tunneled with outer ipv4
 1508  *           3 for tunneled with outer ipv6
 1509  */
 1510 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \
 1511         ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
 1512                (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
 1513                (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M)))
 1514 
 1515 /**
 1516  * ice_add_rss_cfg_sync - add an RSS configuration
 1517  * @hw: pointer to the hardware structure
 1518  * @vsi_handle: software VSI handle
 1519  * @cfg: configure parameters
 1520  *
 1521  * Assumption: lock has already been acquired for RSS list
 1522  */
 1523 static enum ice_status
 1524 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
 1525                      const struct ice_rss_hash_cfg *cfg)
 1526 {
 1527         const enum ice_block blk = ICE_BLK_RSS;
 1528         struct ice_flow_prof *prof = NULL;
 1529         struct ice_flow_seg_info *segs;
 1530         enum ice_status status;
 1531         u8 segs_cnt;
 1532 
 1533         if (cfg->symm)
 1534                 return ICE_ERR_PARAM;
 1535 
 1536         segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
 1537                         ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
 1538 
 1539         segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
 1540                                                       sizeof(*segs));
 1541         if (!segs)
 1542                 return ICE_ERR_NO_MEMORY;
 1543 
 1544         /* Construct the packet segment info from the hashed fields */
 1545         status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
 1546         if (status)
 1547                 goto exit;
 1548 
 1549         /* Search for a flow profile that has matching headers, hash fields
 1550          * and has the input VSI associated to it. If found, no further
 1551          * operations required and exit.
 1552          */
 1553         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
 1554                                         vsi_handle,
 1555                                         ICE_FLOW_FIND_PROF_CHK_FLDS |
 1556                                         ICE_FLOW_FIND_PROF_CHK_VSI);
 1557         if (prof)
 1558                 goto exit;
 1559 
 1560         /* Check if a flow profile exists with the same protocol headers and
 1561          * associated with the input VSI. If so disassociate the VSI from
 1562          * this profile. The VSI will be added to a new profile created with
 1563          * the protocol header and new hash field configuration.
 1564          */
 1565         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
 1566                                         vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
 1567         if (prof) {
 1568                 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
 1569                 if (!status)
 1570                         ice_rem_rss_list(hw, vsi_handle, prof);
 1571                 else
 1572                         goto exit;
 1573 
 1574                 /* Remove profile if it has no VSIs associated */
 1575                 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
 1576                         status = ice_flow_rem_prof(hw, blk, prof->id);
 1577                         if (status)
 1578                                 goto exit;
 1579                 }
 1580         }
 1581 
 1582         /* Search for a profile that has same match fields only. If this
 1583          * exists then associate the VSI to this profile.
 1584          */
 1585         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
 1586                                         vsi_handle,
 1587                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
 1588         if (prof) {
 1589                 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
 1590                 if (!status)
 1591                         status = ice_add_rss_list(hw, vsi_handle, prof);
 1592                 goto exit;
 1593         }
 1594 
 1595         /* Create a new flow profile with generated profile and packet
 1596          * segment information.
 1597          */
 1598         status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
 1599                                    ICE_FLOW_GEN_PROFID(cfg->hash_flds,
 1600                                                        segs[segs_cnt - 1].hdrs,
 1601                                                        cfg->hdr_type),
 1602                                    segs, segs_cnt, NULL, 0, &prof);
 1603         if (status)
 1604                 goto exit;
 1605 
 1606         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
 1607         /* If association to a new flow profile failed then this profile can
 1608          * be removed.
 1609          */
 1610         if (status) {
 1611                 ice_flow_rem_prof(hw, blk, prof->id);
 1612                 goto exit;
 1613         }
 1614 
 1615         status = ice_add_rss_list(hw, vsi_handle, prof);
 1616 
 1617         prof->cfg.symm = cfg->symm;
 1618 
 1619 exit:
 1620         ice_free(hw, segs);
 1621         return status;
 1622 }
 1623 
 1624 /**
 1625  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
 1626  * @hw: pointer to the hardware structure
 1627  * @vsi_handle: software VSI handle
 1628  * @cfg: configure parameters
 1629  *
 1630  * This function will generate a flow profile based on fields associated with
 1631  * the input fields to hash on, the flow type and use the VSI number to add
 1632  * a flow entry to the profile.
 1633  */
 1634 enum ice_status
 1635 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
 1636                 const struct ice_rss_hash_cfg *cfg)
 1637 {
 1638         struct ice_rss_hash_cfg local_cfg;
 1639         enum ice_status status;
 1640 
 1641         if (!ice_is_vsi_valid(hw, vsi_handle) ||
 1642             !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
 1643             cfg->hash_flds == ICE_HASH_INVALID)
 1644                 return ICE_ERR_PARAM;
 1645 
 1646         local_cfg = *cfg;
 1647         if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
 1648                 ice_acquire_lock(&hw->rss_locks);
 1649                 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
 1650                 ice_release_lock(&hw->rss_locks);
 1651         } else {
 1652                 ice_acquire_lock(&hw->rss_locks);
 1653                 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
 1654                 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
 1655                 if (!status) {
 1656                         local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
 1657                         status = ice_add_rss_cfg_sync(hw, vsi_handle,
 1658                                                       &local_cfg);
 1659                 }
 1660                 ice_release_lock(&hw->rss_locks);
 1661         }
 1662 
 1663         return status;
 1664 }
 1665 
 1666 /**
 1667  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
 1668  * @hw: pointer to the hardware structure
 1669  * @vsi_handle: software VSI handle
 1670  * @cfg: configure parameters
 1671  *
 1672  * Assumption: lock has already been acquired for RSS list
 1673  */
 1674 static enum ice_status
 1675 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
 1676                      const struct ice_rss_hash_cfg *cfg)
 1677 {
 1678         const enum ice_block blk = ICE_BLK_RSS;
 1679         struct ice_flow_seg_info *segs;
 1680         struct ice_flow_prof *prof;
 1681         enum ice_status status;
 1682         u8 segs_cnt;
 1683 
 1684         segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
 1685                         ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
 1686         segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
 1687                                                       sizeof(*segs));
 1688         if (!segs)
 1689                 return ICE_ERR_NO_MEMORY;
 1690 
 1691         /* Construct the packet segment info from the hashed fields */
 1692         status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
 1693         if (status)
 1694                 goto out;
 1695 
 1696         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
 1697                                         vsi_handle,
 1698                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
 1699         if (!prof) {
 1700                 status = ICE_ERR_DOES_NOT_EXIST;
 1701                 goto out;
 1702         }
 1703 
 1704         status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
 1705         if (status)
 1706                 goto out;
 1707 
 1708         /* Remove RSS configuration from VSI context before deleting
 1709          * the flow profile.
 1710          */
 1711         ice_rem_rss_list(hw, vsi_handle, prof);
 1712 
 1713         if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
 1714                 status = ice_flow_rem_prof(hw, blk, prof->id);
 1715 
 1716 out:
 1717         ice_free(hw, segs);
 1718         return status;
 1719 }
 1720 
 1721 /**
 1722  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
 1723  * @hw: pointer to the hardware structure
 1724  * @vsi_handle: software VSI handle
 1725  * @cfg: configure parameters
 1726  *
 1727  * This function will lookup the flow profile based on the input
 1728  * hash field bitmap, iterate through the profile entry list of
 1729  * that profile and find entry associated with input VSI to be
 1730  * removed. Calls are made to underlying flow apis which will in
 1731  * turn build or update buffers for RSS XLT1 section.
 1732  */
 1733 enum ice_status
 1734 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
 1735                 const struct ice_rss_hash_cfg *cfg)
 1736 {
 1737         struct ice_rss_hash_cfg local_cfg;
 1738         enum ice_status status;
 1739 
 1740         if (!ice_is_vsi_valid(hw, vsi_handle) ||
 1741             !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
 1742             cfg->hash_flds == ICE_HASH_INVALID)
 1743                 return ICE_ERR_PARAM;
 1744 
 1745         ice_acquire_lock(&hw->rss_locks);
 1746         local_cfg = *cfg;
 1747         if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
 1748                 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
 1749         } else {
 1750                 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
 1751                 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
 1752 
 1753                 if (!status) {
 1754                         local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
 1755                         status = ice_rem_rss_cfg_sync(hw, vsi_handle,
 1756                                                       &local_cfg);
 1757                 }
 1758         }
 1759         ice_release_lock(&hw->rss_locks);
 1760 
 1761         return status;
 1762 }
 1763 
 1764 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
 1765  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
 1766  * convert its values to their appropriate flow L3, L4 values.
 1767  */
 1768 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
 1769         (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
 1770          BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
 1771 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
 1772         (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
 1773          BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
 1774 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
 1775         (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
 1776          BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
 1777          BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
 1778 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
 1779         (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
 1780          ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
 1781 
 1782 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
 1783         (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
 1784          BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
 1785 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
 1786         (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
 1787          BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
 1788          BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
 1789 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
 1790         (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
 1791          BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
 1792 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
 1793         (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
 1794          ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
 1795 
 1796 /**
 1797  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
 1798  * @hw: pointer to the hardware structure
 1799  * @vsi_handle: software VSI handle
 1800  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
 1801  *
 1802  * This function will take the hash bitmap provided by the AVF driver via a
 1803  * message, convert it to ICE-compatible values, and configure RSS flow
 1804  * profiles.
 1805  */
 1806 enum ice_status
 1807 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
 1808 {
 1809         enum ice_status status = ICE_SUCCESS;
 1810         struct ice_rss_hash_cfg hcfg;
 1811         u64 hash_flds;
 1812 
 1813         if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
 1814             !ice_is_vsi_valid(hw, vsi_handle))
 1815                 return ICE_ERR_PARAM;
 1816 
 1817         /* Make sure no unsupported bits are specified */
 1818         if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
 1819                          ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
 1820                 return ICE_ERR_CFG;
 1821 
 1822         hash_flds = avf_hash;
 1823 
 1824         /* Always create an L3 RSS configuration for any L4 RSS configuration */
 1825         if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
 1826                 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
 1827 
 1828         if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
 1829                 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
 1830 
 1831         /* Create the corresponding RSS configuration for each valid hash bit */
 1832         while (hash_flds) {
 1833                 u64 rss_hash = ICE_HASH_INVALID;
 1834 
 1835                 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
 1836                         if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
 1837                                 rss_hash = ICE_FLOW_HASH_IPV4;
 1838                                 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
 1839                         } else if (hash_flds &
 1840                                    ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
 1841                                 rss_hash = ICE_FLOW_HASH_IPV4 |
 1842                                         ICE_FLOW_HASH_TCP_PORT;
 1843                                 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
 1844                         } else if (hash_flds &
 1845                                    ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
 1846                                 rss_hash = ICE_FLOW_HASH_IPV4 |
 1847                                         ICE_FLOW_HASH_UDP_PORT;
 1848                                 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
 1849                         } else if (hash_flds &
 1850                                    BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
 1851                                 rss_hash = ICE_FLOW_HASH_IPV4 |
 1852                                         ICE_FLOW_HASH_SCTP_PORT;
 1853                                 hash_flds &=
 1854                                         ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
 1855                         }
 1856                 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
 1857                         if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
 1858                                 rss_hash = ICE_FLOW_HASH_IPV6;
 1859                                 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
 1860                         } else if (hash_flds &
 1861                                    ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
 1862                                 rss_hash = ICE_FLOW_HASH_IPV6 |
 1863                                         ICE_FLOW_HASH_TCP_PORT;
 1864                                 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
 1865                         } else if (hash_flds &
 1866                                    ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
 1867                                 rss_hash = ICE_FLOW_HASH_IPV6 |
 1868                                         ICE_FLOW_HASH_UDP_PORT;
 1869                                 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
 1870                         } else if (hash_flds &
 1871                                    BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
 1872                                 rss_hash = ICE_FLOW_HASH_IPV6 |
 1873                                         ICE_FLOW_HASH_SCTP_PORT;
 1874                                 hash_flds &=
 1875                                         ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
 1876                         }
 1877                 }
 1878 
 1879                 if (rss_hash == ICE_HASH_INVALID)
 1880                         return ICE_ERR_OUT_OF_RANGE;
 1881 
 1882                 hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
 1883                 hcfg.hash_flds = rss_hash;
 1884                 hcfg.symm = false;
 1885                 hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
 1886                 status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
 1887                 if (status)
 1888                         break;
 1889         }
 1890 
 1891         return status;
 1892 }
 1893 
 1894 /**
 1895  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
 1896  * @hw: pointer to the hardware structure
 1897  * @vsi_handle: software VSI handle
 1898  */
 1899 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
 1900 {
 1901         enum ice_status status = ICE_SUCCESS;
 1902         struct ice_rss_cfg *r;
 1903 
 1904         if (!ice_is_vsi_valid(hw, vsi_handle))
 1905                 return ICE_ERR_PARAM;
 1906 
 1907         ice_acquire_lock(&hw->rss_locks);
 1908         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
 1909                             ice_rss_cfg, l_entry) {
 1910                 if (ice_is_bit_set(r->vsis, vsi_handle)) {
 1911                         status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
 1912                         if (status)
 1913                                 break;
 1914                 }
 1915         }
 1916         ice_release_lock(&hw->rss_locks);
 1917 
 1918         return status;
 1919 }
 1920 
 1921 /**
 1922  * ice_get_rss_cfg - returns hashed fields for the given header types
 1923  * @hw: pointer to the hardware structure
 1924  * @vsi_handle: software VSI handle
 1925  * @hdrs: protocol header type
 1926  *
 1927  * This function will return the match fields of the first instance of flow
 1928  * profile having the given header types and containing input VSI
 1929  */
 1930 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
 1931 {
 1932         u64 rss_hash = ICE_HASH_INVALID;
 1933         struct ice_rss_cfg *r;
 1934 
 1935         /* verify if the protocol header is non zero and VSI is valid */
 1936         if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
 1937                 return ICE_HASH_INVALID;
 1938 
 1939         ice_acquire_lock(&hw->rss_locks);
 1940         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
 1941                             ice_rss_cfg, l_entry)
 1942                 if (ice_is_bit_set(r->vsis, vsi_handle) &&
 1943                     r->hash.addl_hdrs == hdrs) {
 1944                         rss_hash = r->hash.hash_flds;
 1945                         break;
 1946                 }
 1947         ice_release_lock(&hw->rss_locks);
 1948 
 1949         return rss_hash;
 1950 }

Cache object: 8307372a61ffb1824baa31147abe4adc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.