net/dpaa2: add RSS flow distribution
[dpdk.git] / drivers / net / dpaa2 / base / dpaa2_hw_dpni.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
5  *   Copyright (c) 2016 NXP. All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Freescale Semiconductor, Inc nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <time.h>
35 #include <net/if.h>
36
37 #include <rte_mbuf.h>
38 #include <rte_ethdev.h>
39 #include <rte_malloc.h>
40 #include <rte_memcpy.h>
41 #include <rte_string_fns.h>
42 #include <rte_cycles.h>
43 #include <rte_kvargs.h>
44 #include <rte_dev.h>
45 #include <rte_ethdev.h>
46
47 #include <fslmc_logs.h>
48 #include <dpaa2_hw_pvt.h>
49
50 #include "../dpaa2_ethdev.h"
51
52 static void
53 dpaa2_distset_to_dpkg_profile_cfg(
54                 uint32_t req_dist_set,
55                 struct dpkg_profile_cfg *kg_cfg);
56
57 int
58 dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
59                       uint32_t req_dist_set)
60 {
61         struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
62         struct fsl_mc_io *dpni = priv->hw;
63         struct dpni_rx_tc_dist_cfg tc_cfg;
64         struct dpkg_profile_cfg kg_cfg;
65         void *p_params;
66         int ret, tc_index = 0;
67
68         p_params = rte_malloc(
69                 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
70         if (!p_params) {
71                 RTE_LOG(ERR, PMD, "Memory unavaialble\n");
72                 return -ENOMEM;
73         }
74         memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
75         memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
76
77         dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg);
78         tc_cfg.key_cfg_iova = (uint64_t)(p_params);
79         tc_cfg.dist_size = eth_dev->data->nb_rx_queues;
80         tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
81
82         ret = dpni_prepare_key_cfg(&kg_cfg, p_params);
83         if (ret) {
84                 RTE_LOG(ERR, PMD, "Unable to prepare extract parameters\n");
85                 rte_free(p_params);
86                 return ret;
87         }
88
89         ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
90                                   &tc_cfg);
91         rte_free(p_params);
92         if (ret) {
93                 RTE_LOG(ERR, PMD, "Setting distribution for Rx failed with"
94                         " err code: %d\n", ret);
95                 return ret;
96         }
97
98         return 0;
99 }
100
101 int dpaa2_remove_flow_dist(
102         struct rte_eth_dev *eth_dev,
103         uint8_t tc_index)
104 {
105         struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
106         struct fsl_mc_io *dpni = priv->hw;
107         struct dpni_rx_tc_dist_cfg tc_cfg;
108         struct dpkg_profile_cfg kg_cfg;
109         void *p_params;
110         int ret;
111
112         p_params = rte_malloc(
113                 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
114         if (!p_params) {
115                 RTE_LOG(ERR, PMD, "Memory unavaialble\n");
116                 return -ENOMEM;
117         }
118         memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
119         memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
120
121         tc_cfg.key_cfg_iova = (uint64_t)(p_params);
122         tc_cfg.dist_size = 0;
123         tc_cfg.dist_mode = DPNI_DIST_MODE_NONE;
124
125         ret = dpni_prepare_key_cfg(&kg_cfg, p_params);
126         if (ret) {
127                 RTE_LOG(ERR, PMD, "Unable to prepare extract parameters\n");
128                 rte_free(p_params);
129                 return ret;
130         }
131
132         ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
133                                   &tc_cfg);
134         rte_free(p_params);
135         if (ret) {
136                 RTE_LOG(ERR, PMD, "Setting distribution for Rx failed with"
137                         " err code: %d\n", ret);
138                 return ret;
139         }
140         return ret;
141 }
142
143 static void
144 dpaa2_distset_to_dpkg_profile_cfg(
145                 uint32_t req_dist_set,
146                 struct dpkg_profile_cfg *kg_cfg)
147 {
148         uint32_t loop = 0, i = 0, dist_field = 0;
149         int l2_configured = 0, l3_configured = 0;
150         int l4_configured = 0, sctp_configured = 0;
151
152         memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
153         while (req_dist_set) {
154                 if (req_dist_set % 2 != 0) {
155                         dist_field = 1U << loop;
156                         switch (dist_field) {
157                         case ETH_RSS_L2_PAYLOAD:
158
159                                 if (l2_configured)
160                                         break;
161                                 l2_configured = 1;
162
163                                 kg_cfg->extracts[i].extract.from_hdr.prot =
164                                         NET_PROT_ETH;
165                                 kg_cfg->extracts[i].extract.from_hdr.field =
166                                         NH_FLD_ETH_TYPE;
167                                 kg_cfg->extracts[i].type =
168                                         DPKG_EXTRACT_FROM_HDR;
169                                 kg_cfg->extracts[i].extract.from_hdr.type =
170                                         DPKG_FULL_FIELD;
171                                 i++;
172                         break;
173
174                         case ETH_RSS_IPV4:
175                         case ETH_RSS_FRAG_IPV4:
176                         case ETH_RSS_NONFRAG_IPV4_OTHER:
177                         case ETH_RSS_IPV6:
178                         case ETH_RSS_FRAG_IPV6:
179                         case ETH_RSS_NONFRAG_IPV6_OTHER:
180                         case ETH_RSS_IPV6_EX:
181
182                                 if (l3_configured)
183                                         break;
184                                 l3_configured = 1;
185
186                                 kg_cfg->extracts[i].extract.from_hdr.prot =
187                                         NET_PROT_IP;
188                                 kg_cfg->extracts[i].extract.from_hdr.field =
189                                         NH_FLD_IP_SRC;
190                                 kg_cfg->extracts[i].type =
191                                         DPKG_EXTRACT_FROM_HDR;
192                                 kg_cfg->extracts[i].extract.from_hdr.type =
193                                         DPKG_FULL_FIELD;
194                                 i++;
195
196                                 kg_cfg->extracts[i].extract.from_hdr.prot =
197                                         NET_PROT_IP;
198                                 kg_cfg->extracts[i].extract.from_hdr.field =
199                                         NH_FLD_IP_DST;
200                                 kg_cfg->extracts[i].type =
201                                         DPKG_EXTRACT_FROM_HDR;
202                                 kg_cfg->extracts[i].extract.from_hdr.type =
203                                         DPKG_FULL_FIELD;
204                                 i++;
205
206                                 kg_cfg->extracts[i].extract.from_hdr.prot =
207                                         NET_PROT_IP;
208                                 kg_cfg->extracts[i].extract.from_hdr.field =
209                                         NH_FLD_IP_PROTO;
210                                 kg_cfg->extracts[i].type =
211                                         DPKG_EXTRACT_FROM_HDR;
212                                 kg_cfg->extracts[i].extract.from_hdr.type =
213                                         DPKG_FULL_FIELD;
214                                 kg_cfg->num_extracts++;
215                                 i++;
216                         break;
217
218                         case ETH_RSS_NONFRAG_IPV4_TCP:
219                         case ETH_RSS_NONFRAG_IPV6_TCP:
220                         case ETH_RSS_NONFRAG_IPV4_UDP:
221                         case ETH_RSS_NONFRAG_IPV6_UDP:
222                         case ETH_RSS_IPV6_TCP_EX:
223                         case ETH_RSS_IPV6_UDP_EX:
224
225                                 if (l4_configured)
226                                         break;
227                                 l4_configured = 1;
228
229                                 kg_cfg->extracts[i].extract.from_hdr.prot =
230                                         NET_PROT_TCP;
231                                 kg_cfg->extracts[i].extract.from_hdr.field =
232                                         NH_FLD_TCP_PORT_SRC;
233                                 kg_cfg->extracts[i].type =
234                                         DPKG_EXTRACT_FROM_HDR;
235                                 kg_cfg->extracts[i].extract.from_hdr.type =
236                                         DPKG_FULL_FIELD;
237                                 i++;
238
239                                 kg_cfg->extracts[i].extract.from_hdr.prot =
240                                         NET_PROT_TCP;
241                                 kg_cfg->extracts[i].extract.from_hdr.field =
242                                         NH_FLD_TCP_PORT_SRC;
243                                 kg_cfg->extracts[i].type =
244                                         DPKG_EXTRACT_FROM_HDR;
245                                 kg_cfg->extracts[i].extract.from_hdr.type =
246                                         DPKG_FULL_FIELD;
247                                 i++;
248                                 break;
249
250                         case ETH_RSS_NONFRAG_IPV4_SCTP:
251                         case ETH_RSS_NONFRAG_IPV6_SCTP:
252
253                                 if (sctp_configured)
254                                         break;
255                                 sctp_configured = 1;
256
257                                 kg_cfg->extracts[i].extract.from_hdr.prot =
258                                         NET_PROT_SCTP;
259                                 kg_cfg->extracts[i].extract.from_hdr.field =
260                                         NH_FLD_SCTP_PORT_SRC;
261                                 kg_cfg->extracts[i].type =
262                                         DPKG_EXTRACT_FROM_HDR;
263                                 kg_cfg->extracts[i].extract.from_hdr.type =
264                                         DPKG_FULL_FIELD;
265                                 i++;
266
267                                 kg_cfg->extracts[i].extract.from_hdr.prot =
268                                         NET_PROT_SCTP;
269                                 kg_cfg->extracts[i].extract.from_hdr.field =
270                                         NH_FLD_SCTP_PORT_DST;
271                                 kg_cfg->extracts[i].type =
272                                         DPKG_EXTRACT_FROM_HDR;
273                                 kg_cfg->extracts[i].extract.from_hdr.type =
274                                         DPKG_FULL_FIELD;
275                                 i++;
276                                 break;
277
278                         default:
279                                 PMD_DRV_LOG(WARNING, "Bad flow distribution"
280                                             " option %x\n", dist_field);
281                         }
282                 }
283                 req_dist_set = req_dist_set >> 1;
284                 loop++;
285         }
286         kg_cfg->num_extracts = i;
287 }