New upstream version 18.08
[deb_dpdk.git] / drivers / net / dpaa2 / base / dpaa2_hw_dpni.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
4  *   Copyright 2016 NXP
5  *
6  */
7
8 #include <time.h>
9 #include <net/if.h>
10
11 #include <rte_mbuf.h>
12 #include <rte_ethdev_driver.h>
13 #include <rte_malloc.h>
14 #include <rte_memcpy.h>
15 #include <rte_string_fns.h>
16 #include <rte_cycles.h>
17 #include <rte_kvargs.h>
18 #include <rte_dev.h>
19
20 #include <dpaa2_pmd_logs.h>
21 #include <dpaa2_hw_pvt.h>
22 #include <dpaa2_hw_mempool.h>
23
24 #include "../dpaa2_ethdev.h"
25
26 static int
27 dpaa2_distset_to_dpkg_profile_cfg(
28                 uint64_t req_dist_set,
29                 struct dpkg_profile_cfg *kg_cfg);
30
31 int
32 dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
33                       uint64_t req_dist_set)
34 {
35         struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
36         struct fsl_mc_io *dpni = priv->hw;
37         struct dpni_rx_tc_dist_cfg tc_cfg;
38         struct dpkg_profile_cfg kg_cfg;
39         void *p_params;
40         int ret, tc_index = 0;
41
42         p_params = rte_malloc(
43                 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
44         if (!p_params) {
45                 DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
46                 return -ENOMEM;
47         }
48         memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
49         memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
50
51         ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg);
52         if (ret) {
53                 DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported",
54                               req_dist_set);
55                 rte_free(p_params);
56                 return ret;
57         }
58         tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
59         tc_cfg.dist_size = eth_dev->data->nb_rx_queues;
60         tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
61
62         ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
63         if (ret) {
64                 DPAA2_PMD_ERR("Unable to prepare extract parameters");
65                 rte_free(p_params);
66                 return ret;
67         }
68
69         ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
70                                   &tc_cfg);
71         rte_free(p_params);
72         if (ret) {
73                 DPAA2_PMD_ERR(
74                              "Setting distribution for Rx failed with err: %d",
75                              ret);
76                 return ret;
77         }
78
79         return 0;
80 }
81
82 int dpaa2_remove_flow_dist(
83         struct rte_eth_dev *eth_dev,
84         uint8_t tc_index)
85 {
86         struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
87         struct fsl_mc_io *dpni = priv->hw;
88         struct dpni_rx_tc_dist_cfg tc_cfg;
89         struct dpkg_profile_cfg kg_cfg;
90         void *p_params;
91         int ret;
92
93         p_params = rte_malloc(
94                 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
95         if (!p_params) {
96                 DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
97                 return -ENOMEM;
98         }
99         memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
100         memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
101         kg_cfg.num_extracts = 0;
102         tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
103         tc_cfg.dist_size = 0;
104         tc_cfg.dist_mode = DPNI_DIST_MODE_NONE;
105
106         ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
107         if (ret) {
108                 DPAA2_PMD_ERR("Unable to prepare extract parameters");
109                 rte_free(p_params);
110                 return ret;
111         }
112
113         ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
114                                   &tc_cfg);
115         rte_free(p_params);
116         if (ret)
117                 DPAA2_PMD_ERR(
118                              "Setting distribution for Rx failed with err: %d",
119                              ret);
120         return ret;
121 }
122
123 static int
124 dpaa2_distset_to_dpkg_profile_cfg(
125                 uint64_t req_dist_set,
126                 struct dpkg_profile_cfg *kg_cfg)
127 {
128         uint32_t loop = 0, i = 0, dist_field = 0;
129         int l2_configured = 0, l3_configured = 0;
130         int l4_configured = 0, sctp_configured = 0;
131
132         memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
133         while (req_dist_set) {
134                 if (req_dist_set % 2 != 0) {
135                         dist_field = 1U << loop;
136                         switch (dist_field) {
137                         case ETH_RSS_L2_PAYLOAD:
138
139                                 if (l2_configured)
140                                         break;
141                                 l2_configured = 1;
142
143                                 kg_cfg->extracts[i].extract.from_hdr.prot =
144                                         NET_PROT_ETH;
145                                 kg_cfg->extracts[i].extract.from_hdr.field =
146                                         NH_FLD_ETH_TYPE;
147                                 kg_cfg->extracts[i].type =
148                                         DPKG_EXTRACT_FROM_HDR;
149                                 kg_cfg->extracts[i].extract.from_hdr.type =
150                                         DPKG_FULL_FIELD;
151                                 i++;
152                         break;
153
154                         case ETH_RSS_IPV4:
155                         case ETH_RSS_FRAG_IPV4:
156                         case ETH_RSS_NONFRAG_IPV4_OTHER:
157                         case ETH_RSS_IPV6:
158                         case ETH_RSS_FRAG_IPV6:
159                         case ETH_RSS_NONFRAG_IPV6_OTHER:
160                         case ETH_RSS_IPV6_EX:
161
162                                 if (l3_configured)
163                                         break;
164                                 l3_configured = 1;
165
166                                 kg_cfg->extracts[i].extract.from_hdr.prot =
167                                         NET_PROT_IP;
168                                 kg_cfg->extracts[i].extract.from_hdr.field =
169                                         NH_FLD_IP_SRC;
170                                 kg_cfg->extracts[i].type =
171                                         DPKG_EXTRACT_FROM_HDR;
172                                 kg_cfg->extracts[i].extract.from_hdr.type =
173                                         DPKG_FULL_FIELD;
174                                 i++;
175
176                                 kg_cfg->extracts[i].extract.from_hdr.prot =
177                                         NET_PROT_IP;
178                                 kg_cfg->extracts[i].extract.from_hdr.field =
179                                         NH_FLD_IP_DST;
180                                 kg_cfg->extracts[i].type =
181                                         DPKG_EXTRACT_FROM_HDR;
182                                 kg_cfg->extracts[i].extract.from_hdr.type =
183                                         DPKG_FULL_FIELD;
184                                 i++;
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_PROTO;
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                                 kg_cfg->num_extracts++;
195                                 i++;
196                         break;
197
198                         case ETH_RSS_NONFRAG_IPV4_TCP:
199                         case ETH_RSS_NONFRAG_IPV6_TCP:
200                         case ETH_RSS_NONFRAG_IPV4_UDP:
201                         case ETH_RSS_NONFRAG_IPV6_UDP:
202                         case ETH_RSS_IPV6_TCP_EX:
203                         case ETH_RSS_IPV6_UDP_EX:
204
205                                 if (l4_configured)
206                                         break;
207                                 l4_configured = 1;
208
209                                 kg_cfg->extracts[i].extract.from_hdr.prot =
210                                         NET_PROT_TCP;
211                                 kg_cfg->extracts[i].extract.from_hdr.field =
212                                         NH_FLD_TCP_PORT_SRC;
213                                 kg_cfg->extracts[i].type =
214                                         DPKG_EXTRACT_FROM_HDR;
215                                 kg_cfg->extracts[i].extract.from_hdr.type =
216                                         DPKG_FULL_FIELD;
217                                 i++;
218
219                                 kg_cfg->extracts[i].extract.from_hdr.prot =
220                                         NET_PROT_TCP;
221                                 kg_cfg->extracts[i].extract.from_hdr.field =
222                                         NH_FLD_TCP_PORT_SRC;
223                                 kg_cfg->extracts[i].type =
224                                         DPKG_EXTRACT_FROM_HDR;
225                                 kg_cfg->extracts[i].extract.from_hdr.type =
226                                         DPKG_FULL_FIELD;
227                                 i++;
228                                 break;
229
230                         case ETH_RSS_NONFRAG_IPV4_SCTP:
231                         case ETH_RSS_NONFRAG_IPV6_SCTP:
232
233                                 if (sctp_configured)
234                                         break;
235                                 sctp_configured = 1;
236
237                                 kg_cfg->extracts[i].extract.from_hdr.prot =
238                                         NET_PROT_SCTP;
239                                 kg_cfg->extracts[i].extract.from_hdr.field =
240                                         NH_FLD_SCTP_PORT_SRC;
241                                 kg_cfg->extracts[i].type =
242                                         DPKG_EXTRACT_FROM_HDR;
243                                 kg_cfg->extracts[i].extract.from_hdr.type =
244                                         DPKG_FULL_FIELD;
245                                 i++;
246
247                                 kg_cfg->extracts[i].extract.from_hdr.prot =
248                                         NET_PROT_SCTP;
249                                 kg_cfg->extracts[i].extract.from_hdr.field =
250                                         NH_FLD_SCTP_PORT_DST;
251                                 kg_cfg->extracts[i].type =
252                                         DPKG_EXTRACT_FROM_HDR;
253                                 kg_cfg->extracts[i].extract.from_hdr.type =
254                                         DPKG_FULL_FIELD;
255                                 i++;
256                                 break;
257
258                         default:
259                                 DPAA2_PMD_WARN(
260                                              "Unsupported flow dist option %x",
261                                              dist_field);
262                                 return -EINVAL;
263                         }
264                 }
265                 req_dist_set = req_dist_set >> 1;
266                 loop++;
267         }
268         kg_cfg->num_extracts = i;
269         return 0;
270 }
271
272 int
273 dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv,
274                      void *blist)
275 {
276         /* Function to attach a DPNI with a buffer pool list. Buffer pool list
277          * handle is passed in blist.
278          */
279         int32_t retcode;
280         struct fsl_mc_io *dpni = priv->hw;
281         struct dpni_pools_cfg bpool_cfg;
282         struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist;
283         struct dpni_buffer_layout layout;
284         int tot_size;
285
286         /* ... rx buffer layout .
287          * Check alignment for buffer layouts first
288          */
289
290         /* ... rx buffer layout ... */
291         tot_size = RTE_PKTMBUF_HEADROOM;
292         tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN);
293
294         memset(&layout, 0, sizeof(struct dpni_buffer_layout));
295         layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM |
296                          DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
297                          DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
298                          DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
299                          DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
300
301         layout.pass_frame_status = 1;
302         layout.private_data_size = DPAA2_FD_PTA_SIZE;
303         layout.pass_parser_result = 1;
304         layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN;
305         layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE -
306                                 DPAA2_MBUF_HW_ANNOTATION;
307         retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token,
308                                          DPNI_QUEUE_RX, &layout);
309         if (retcode) {
310                 DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)",
311                              retcode);
312                 return retcode;
313         }
314
315         /*Attach buffer pool to the network interface as described by the user*/
316         bpool_cfg.num_dpbp = 1;
317         bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id;
318         bpool_cfg.pools[0].backup_pool = 0;
319         bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size,
320                                                 DPAA2_PACKET_LAYOUT_ALIGN);
321         bpool_cfg.pools[0].priority_mask = 0;
322
323         retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg);
324         if (retcode != 0) {
325                 DPAA2_PMD_ERR("Error configuring buffer pool on interface."
326                               " bpid = %d error code = %d",
327                               bpool_cfg.pools[0].dpbp_id, retcode);
328                 return retcode;
329         }
330
331         priv->bp_list = bp_list;
332         return 0;
333 }