]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(C) 2019 Marvell International Ltd. | |
3 | */ | |
4 | ||
5 | #include "otx2_ethdev.h" | |
6 | ||
7 | int | |
8 | otx2_nix_rss_tbl_init(struct otx2_eth_dev *dev, | |
9 | uint8_t group, uint16_t *ind_tbl) | |
10 | { | |
11 | struct otx2_rss_info *rss = &dev->rss_info; | |
12 | struct otx2_mbox *mbox = dev->mbox; | |
13 | struct nix_aq_enq_req *req; | |
14 | int rc, idx; | |
15 | ||
16 | for (idx = 0; idx < rss->rss_size; idx++) { | |
17 | req = otx2_mbox_alloc_msg_nix_aq_enq(mbox); | |
18 | if (!req) { | |
19 | /* The shared memory buffer can be full. | |
20 | * Flush it and retry | |
21 | */ | |
22 | otx2_mbox_msg_send(mbox, 0); | |
23 | rc = otx2_mbox_wait_for_rsp(mbox, 0); | |
24 | if (rc < 0) | |
25 | return rc; | |
26 | ||
27 | req = otx2_mbox_alloc_msg_nix_aq_enq(mbox); | |
28 | if (!req) | |
29 | return -ENOMEM; | |
30 | } | |
31 | req->rss.rq = ind_tbl[idx]; | |
32 | /* Fill AQ info */ | |
33 | req->qidx = (group * rss->rss_size) + idx; | |
34 | req->ctype = NIX_AQ_CTYPE_RSS; | |
35 | req->op = NIX_AQ_INSTOP_INIT; | |
36 | } | |
37 | ||
38 | otx2_mbox_msg_send(mbox, 0); | |
39 | rc = otx2_mbox_wait_for_rsp(mbox, 0); | |
40 | if (rc < 0) | |
41 | return rc; | |
42 | ||
43 | return 0; | |
44 | } | |
45 | ||
46 | int | |
47 | otx2_nix_dev_reta_update(struct rte_eth_dev *eth_dev, | |
48 | struct rte_eth_rss_reta_entry64 *reta_conf, | |
49 | uint16_t reta_size) | |
50 | { | |
51 | struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); | |
52 | struct otx2_rss_info *rss = &dev->rss_info; | |
53 | int rc, i, j; | |
54 | int idx = 0; | |
55 | ||
56 | rc = -EINVAL; | |
57 | if (reta_size != dev->rss_info.rss_size) { | |
58 | otx2_err("Size of hash lookup table configured " | |
59 | "(%d) doesn't match the number hardware can supported " | |
60 | "(%d)", reta_size, dev->rss_info.rss_size); | |
61 | goto fail; | |
62 | } | |
63 | ||
64 | /* Copy RETA table */ | |
65 | for (i = 0; i < (dev->rss_info.rss_size / RTE_RETA_GROUP_SIZE); i++) { | |
66 | for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) { | |
67 | if ((reta_conf[i].mask >> j) & 0x01) | |
68 | rss->ind_tbl[idx] = reta_conf[i].reta[j]; | |
69 | idx++; | |
70 | } | |
71 | } | |
72 | ||
73 | return otx2_nix_rss_tbl_init(dev, 0, dev->rss_info.ind_tbl); | |
74 | ||
75 | fail: | |
76 | return rc; | |
77 | } | |
78 | ||
79 | int | |
80 | otx2_nix_dev_reta_query(struct rte_eth_dev *eth_dev, | |
81 | struct rte_eth_rss_reta_entry64 *reta_conf, | |
82 | uint16_t reta_size) | |
83 | { | |
84 | struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); | |
85 | struct otx2_rss_info *rss = &dev->rss_info; | |
86 | int rc, i, j; | |
87 | ||
88 | rc = -EINVAL; | |
89 | ||
90 | if (reta_size != dev->rss_info.rss_size) { | |
91 | otx2_err("Size of hash lookup table configured " | |
92 | "(%d) doesn't match the number hardware can supported " | |
93 | "(%d)", reta_size, dev->rss_info.rss_size); | |
94 | goto fail; | |
95 | } | |
96 | ||
97 | /* Copy RETA table */ | |
98 | for (i = 0; i < (dev->rss_info.rss_size / RTE_RETA_GROUP_SIZE); i++) { | |
99 | for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) | |
100 | if ((reta_conf[i].mask >> j) & 0x01) | |
101 | reta_conf[i].reta[j] = rss->ind_tbl[j]; | |
102 | } | |
103 | ||
104 | return 0; | |
105 | ||
106 | fail: | |
107 | return rc; | |
108 | } | |
109 | ||
110 | void | |
111 | otx2_nix_rss_set_key(struct otx2_eth_dev *dev, uint8_t *key, | |
112 | uint32_t key_len) | |
113 | { | |
114 | const uint8_t default_key[NIX_HASH_KEY_SIZE] = { | |
115 | 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, | |
116 | 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, | |
117 | 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, | |
118 | 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, | |
119 | 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, | |
120 | 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD | |
121 | }; | |
122 | struct otx2_rss_info *rss = &dev->rss_info; | |
123 | uint64_t *keyptr; | |
124 | uint64_t val; | |
125 | uint32_t idx; | |
126 | ||
127 | if (key == NULL || key == 0) { | |
128 | keyptr = (uint64_t *)(uintptr_t)default_key; | |
129 | key_len = NIX_HASH_KEY_SIZE; | |
130 | memset(rss->key, 0, key_len); | |
131 | } else { | |
132 | memcpy(rss->key, key, key_len); | |
133 | keyptr = (uint64_t *)rss->key; | |
134 | } | |
135 | ||
136 | for (idx = 0; idx < (key_len >> 3); idx++) { | |
137 | val = rte_cpu_to_be_64(*keyptr); | |
138 | otx2_write64(val, dev->base + NIX_LF_RX_SECRETX(idx)); | |
139 | keyptr++; | |
140 | } | |
141 | } | |
142 | ||
143 | static void | |
144 | rss_get_key(struct otx2_eth_dev *dev, uint8_t *key) | |
145 | { | |
146 | uint64_t *keyptr = (uint64_t *)key; | |
147 | uint64_t val; | |
148 | int idx; | |
149 | ||
150 | for (idx = 0; idx < (NIX_HASH_KEY_SIZE >> 3); idx++) { | |
151 | val = otx2_read64(dev->base + NIX_LF_RX_SECRETX(idx)); | |
152 | *keyptr = rte_be_to_cpu_64(val); | |
153 | keyptr++; | |
154 | } | |
155 | } | |
156 | ||
157 | #define RSS_IPV4_ENABLE ( \ | |
158 | ETH_RSS_IPV4 | \ | |
159 | ETH_RSS_FRAG_IPV4 | \ | |
160 | ETH_RSS_NONFRAG_IPV4_UDP | \ | |
161 | ETH_RSS_NONFRAG_IPV4_TCP | \ | |
162 | ETH_RSS_NONFRAG_IPV4_SCTP) | |
163 | ||
164 | #define RSS_IPV6_ENABLE ( \ | |
165 | ETH_RSS_IPV6 | \ | |
166 | ETH_RSS_FRAG_IPV6 | \ | |
167 | ETH_RSS_NONFRAG_IPV6_UDP | \ | |
168 | ETH_RSS_NONFRAG_IPV6_TCP | \ | |
169 | ETH_RSS_NONFRAG_IPV6_SCTP) | |
170 | ||
171 | #define RSS_IPV6_EX_ENABLE ( \ | |
172 | ETH_RSS_IPV6_EX | \ | |
173 | ETH_RSS_IPV6_TCP_EX | \ | |
174 | ETH_RSS_IPV6_UDP_EX) | |
175 | ||
176 | #define RSS_MAX_LEVELS 3 | |
177 | ||
178 | #define RSS_IPV4_INDEX 0 | |
179 | #define RSS_IPV6_INDEX 1 | |
180 | #define RSS_TCP_INDEX 2 | |
181 | #define RSS_UDP_INDEX 3 | |
182 | #define RSS_SCTP_INDEX 4 | |
183 | #define RSS_DMAC_INDEX 5 | |
184 | ||
185 | uint32_t | |
186 | otx2_rss_ethdev_to_nix(struct otx2_eth_dev *dev, uint64_t ethdev_rss, | |
187 | uint8_t rss_level) | |
188 | { | |
189 | uint32_t flow_key_type[RSS_MAX_LEVELS][6] = { | |
190 | { | |
191 | FLOW_KEY_TYPE_IPV4, FLOW_KEY_TYPE_IPV6, | |
192 | FLOW_KEY_TYPE_TCP, FLOW_KEY_TYPE_UDP, | |
193 | FLOW_KEY_TYPE_SCTP, FLOW_KEY_TYPE_ETH_DMAC | |
194 | }, | |
195 | { | |
196 | FLOW_KEY_TYPE_INNR_IPV4, FLOW_KEY_TYPE_INNR_IPV6, | |
197 | FLOW_KEY_TYPE_INNR_TCP, FLOW_KEY_TYPE_INNR_UDP, | |
198 | FLOW_KEY_TYPE_INNR_SCTP, FLOW_KEY_TYPE_INNR_ETH_DMAC | |
199 | }, | |
200 | { | |
201 | FLOW_KEY_TYPE_IPV4 | FLOW_KEY_TYPE_INNR_IPV4, | |
202 | FLOW_KEY_TYPE_IPV6 | FLOW_KEY_TYPE_INNR_IPV6, | |
203 | FLOW_KEY_TYPE_TCP | FLOW_KEY_TYPE_INNR_TCP, | |
204 | FLOW_KEY_TYPE_UDP | FLOW_KEY_TYPE_INNR_UDP, | |
205 | FLOW_KEY_TYPE_SCTP | FLOW_KEY_TYPE_INNR_SCTP, | |
206 | FLOW_KEY_TYPE_ETH_DMAC | FLOW_KEY_TYPE_INNR_ETH_DMAC | |
207 | } | |
208 | }; | |
209 | uint32_t flowkey_cfg = 0; | |
210 | ||
211 | dev->rss_info.nix_rss = ethdev_rss; | |
212 | ||
213 | if (ethdev_rss & ETH_RSS_L2_PAYLOAD && | |
214 | dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_LEN_90B) { | |
215 | flowkey_cfg |= FLOW_KEY_TYPE_CH_LEN_90B; | |
216 | } | |
217 | ||
218 | if (ethdev_rss & ETH_RSS_L3_SRC_ONLY) | |
219 | flowkey_cfg |= FLOW_KEY_TYPE_L3_SRC; | |
220 | ||
221 | if (ethdev_rss & ETH_RSS_L3_DST_ONLY) | |
222 | flowkey_cfg |= FLOW_KEY_TYPE_L3_DST; | |
223 | ||
224 | if (ethdev_rss & ETH_RSS_L4_SRC_ONLY) | |
225 | flowkey_cfg |= FLOW_KEY_TYPE_L4_SRC; | |
226 | ||
227 | if (ethdev_rss & ETH_RSS_L4_DST_ONLY) | |
228 | flowkey_cfg |= FLOW_KEY_TYPE_L4_DST; | |
229 | ||
230 | if (ethdev_rss & RSS_IPV4_ENABLE) | |
231 | flowkey_cfg |= flow_key_type[rss_level][RSS_IPV4_INDEX]; | |
232 | ||
233 | if (ethdev_rss & RSS_IPV6_ENABLE) | |
234 | flowkey_cfg |= flow_key_type[rss_level][RSS_IPV6_INDEX]; | |
235 | ||
236 | if (ethdev_rss & ETH_RSS_TCP) | |
237 | flowkey_cfg |= flow_key_type[rss_level][RSS_TCP_INDEX]; | |
238 | ||
239 | if (ethdev_rss & ETH_RSS_UDP) | |
240 | flowkey_cfg |= flow_key_type[rss_level][RSS_UDP_INDEX]; | |
241 | ||
242 | if (ethdev_rss & ETH_RSS_SCTP) | |
243 | flowkey_cfg |= flow_key_type[rss_level][RSS_SCTP_INDEX]; | |
244 | ||
245 | if (ethdev_rss & ETH_RSS_L2_PAYLOAD) | |
246 | flowkey_cfg |= flow_key_type[rss_level][RSS_DMAC_INDEX]; | |
247 | ||
248 | if (ethdev_rss & RSS_IPV6_EX_ENABLE) | |
249 | flowkey_cfg |= FLOW_KEY_TYPE_IPV6_EXT; | |
250 | ||
251 | if (ethdev_rss & ETH_RSS_PORT) | |
252 | flowkey_cfg |= FLOW_KEY_TYPE_PORT; | |
253 | ||
254 | if (ethdev_rss & ETH_RSS_NVGRE) | |
255 | flowkey_cfg |= FLOW_KEY_TYPE_NVGRE; | |
256 | ||
257 | if (ethdev_rss & ETH_RSS_VXLAN) | |
258 | flowkey_cfg |= FLOW_KEY_TYPE_VXLAN; | |
259 | ||
260 | if (ethdev_rss & ETH_RSS_GENEVE) | |
261 | flowkey_cfg |= FLOW_KEY_TYPE_GENEVE; | |
262 | ||
263 | if (ethdev_rss & ETH_RSS_GTPU) | |
264 | flowkey_cfg |= FLOW_KEY_TYPE_GTPU; | |
265 | ||
266 | return flowkey_cfg; | |
267 | } | |
268 | ||
269 | int | |
270 | otx2_rss_set_hf(struct otx2_eth_dev *dev, uint32_t flowkey_cfg, | |
271 | uint8_t *alg_idx, uint8_t group, int mcam_index) | |
272 | { | |
273 | struct nix_rss_flowkey_cfg_rsp *rss_rsp; | |
274 | struct otx2_mbox *mbox = dev->mbox; | |
275 | struct nix_rss_flowkey_cfg *cfg; | |
276 | int rc; | |
277 | ||
278 | rc = -EINVAL; | |
279 | ||
280 | dev->rss_info.flowkey_cfg = flowkey_cfg; | |
281 | ||
282 | cfg = otx2_mbox_alloc_msg_nix_rss_flowkey_cfg(mbox); | |
283 | ||
284 | cfg->flowkey_cfg = flowkey_cfg; | |
285 | cfg->mcam_index = mcam_index; /* -1 indicates default group */ | |
286 | cfg->group = group; /* 0 is default group */ | |
287 | ||
288 | rc = otx2_mbox_process_msg(mbox, (void *)&rss_rsp); | |
289 | if (rc) | |
290 | return rc; | |
291 | ||
292 | if (alg_idx) | |
293 | *alg_idx = rss_rsp->alg_idx; | |
294 | ||
295 | return rc; | |
296 | } | |
297 | ||
298 | int | |
299 | otx2_nix_rss_hash_update(struct rte_eth_dev *eth_dev, | |
300 | struct rte_eth_rss_conf *rss_conf) | |
301 | { | |
302 | struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); | |
303 | uint32_t flowkey_cfg; | |
304 | uint8_t alg_idx; | |
305 | int rc; | |
306 | ||
307 | rc = -EINVAL; | |
308 | ||
309 | if (rss_conf->rss_key && rss_conf->rss_key_len != NIX_HASH_KEY_SIZE) { | |
310 | otx2_err("Hash key size mismatch %d vs %d", | |
311 | rss_conf->rss_key_len, NIX_HASH_KEY_SIZE); | |
312 | goto fail; | |
313 | } | |
314 | ||
315 | if (rss_conf->rss_key) | |
316 | otx2_nix_rss_set_key(dev, rss_conf->rss_key, | |
317 | (uint32_t)rss_conf->rss_key_len); | |
318 | ||
319 | flowkey_cfg = otx2_rss_ethdev_to_nix(dev, rss_conf->rss_hf, 0); | |
320 | ||
321 | rc = otx2_rss_set_hf(dev, flowkey_cfg, &alg_idx, | |
322 | NIX_DEFAULT_RSS_CTX_GROUP, | |
323 | NIX_DEFAULT_RSS_MCAM_IDX); | |
324 | if (rc) { | |
325 | otx2_err("Failed to set RSS hash function rc=%d", rc); | |
326 | return rc; | |
327 | } | |
328 | ||
329 | dev->rss_info.alg_idx = alg_idx; | |
330 | ||
331 | fail: | |
332 | return rc; | |
333 | } | |
334 | ||
335 | int | |
336 | otx2_nix_rss_hash_conf_get(struct rte_eth_dev *eth_dev, | |
337 | struct rte_eth_rss_conf *rss_conf) | |
338 | { | |
339 | struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); | |
340 | ||
341 | if (rss_conf->rss_key) | |
342 | rss_get_key(dev, rss_conf->rss_key); | |
343 | ||
344 | rss_conf->rss_key_len = NIX_HASH_KEY_SIZE; | |
345 | rss_conf->rss_hf = dev->rss_info.nix_rss; | |
346 | ||
347 | return 0; | |
348 | } | |
349 | ||
350 | int | |
351 | otx2_nix_rss_config(struct rte_eth_dev *eth_dev) | |
352 | { | |
353 | struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); | |
354 | uint32_t idx, qcnt = eth_dev->data->nb_rx_queues; | |
355 | uint32_t flowkey_cfg; | |
356 | uint64_t rss_hf; | |
357 | uint8_t alg_idx; | |
358 | int rc; | |
359 | ||
360 | /* Skip further configuration if selected mode is not RSS */ | |
361 | if (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS || !qcnt) | |
362 | return 0; | |
363 | ||
364 | /* Update default RSS key and cfg */ | |
365 | otx2_nix_rss_set_key(dev, NULL, 0); | |
366 | ||
367 | /* Update default RSS RETA */ | |
368 | for (idx = 0; idx < dev->rss_info.rss_size; idx++) | |
369 | dev->rss_info.ind_tbl[idx] = idx % qcnt; | |
370 | ||
371 | /* Init RSS table context */ | |
372 | rc = otx2_nix_rss_tbl_init(dev, 0, dev->rss_info.ind_tbl); | |
373 | if (rc) { | |
374 | otx2_err("Failed to init RSS table rc=%d", rc); | |
375 | return rc; | |
376 | } | |
377 | ||
378 | rss_hf = eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; | |
379 | flowkey_cfg = otx2_rss_ethdev_to_nix(dev, rss_hf, 0); | |
380 | ||
381 | rc = otx2_rss_set_hf(dev, flowkey_cfg, &alg_idx, | |
382 | NIX_DEFAULT_RSS_CTX_GROUP, | |
383 | NIX_DEFAULT_RSS_MCAM_IDX); | |
384 | if (rc) { | |
385 | otx2_err("Failed to set RSS hash function rc=%d", rc); | |
386 | return rc; | |
387 | } | |
388 | ||
389 | dev->rss_info.alg_idx = alg_idx; | |
390 | ||
391 | return 0; | |
392 | } |