Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Mucse IC Design Ltd.
3 : : */
4 : :
5 : : #include <stdint.h>
6 : :
7 : : #include "base/rnp_bdq_if.h"
8 : : #include "base/rnp_eth_regs.h"
9 : :
10 : : #include "rnp.h"
11 : : #include "rnp_rxtx.h"
12 : : #include "rnp_rss.h"
13 : :
14 : : static const struct rnp_rss_hash_cfg rnp_rss_cfg[] = {
15 : : {RNP_RSS_IPV4, RNP_RSS_HASH_IPV4, RTE_ETH_RSS_IPV4},
16 : : {RNP_RSS_IPV4, RNP_RSS_HASH_IPV4, RTE_ETH_RSS_FRAG_IPV4},
17 : : {RNP_RSS_IPV4, RNP_RSS_HASH_IPV4, RTE_ETH_RSS_NONFRAG_IPV4_OTHER},
18 : : {RNP_RSS_IPV6, RNP_RSS_HASH_IPV6, RTE_ETH_RSS_IPV6},
19 : : {RNP_RSS_IPV6, RNP_RSS_HASH_IPV6, RTE_ETH_RSS_FRAG_IPV6},
20 : : {RNP_RSS_IPV6, RNP_RSS_HASH_IPV6, RTE_ETH_RSS_NONFRAG_IPV6_OTHER},
21 : : {RNP_RSS_IPV4_TCP, RNP_RSS_HASH_IPV4_TCP, RTE_ETH_RSS_NONFRAG_IPV4_TCP},
22 : : {RNP_RSS_IPV4_UDP, RNP_RSS_HASH_IPV4_UDP, RTE_ETH_RSS_NONFRAG_IPV4_UDP},
23 : : {RNP_RSS_IPV4_SCTP, RNP_RSS_HASH_IPV4_SCTP, RTE_ETH_RSS_NONFRAG_IPV4_SCTP},
24 : : {RNP_RSS_IPV6_TCP, RNP_RSS_HASH_IPV6_TCP, RTE_ETH_RSS_NONFRAG_IPV6_TCP},
25 : : {RNP_RSS_IPV6_UDP, RNP_RSS_HASH_IPV6_UDP, RTE_ETH_RSS_NONFRAG_IPV6_UDP},
26 : : {RNP_RSS_IPV6_SCTP, RNP_RSS_HASH_IPV6_SCTP, RTE_ETH_RSS_NONFRAG_IPV6_SCTP}
27 : : };
28 : :
29 : : static uint8_t rnp_rss_default_key[40] = {
30 : : 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
31 : : 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
32 : : 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
33 : : 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
34 : : 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
35 : : };
36 : :
37 : : int
38 : 0 : rnp_dev_rss_reta_update(struct rte_eth_dev *dev,
39 : : struct rte_eth_rss_reta_entry64 *reta_conf,
40 : : uint16_t reta_size)
41 : : {
42 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
43 : 0 : uint16_t port_offset = port->attr.port_offset;
44 : 0 : uint32_t *indirtbl = &port->indirtbl[0];
45 : 0 : uint16_t lane = port->attr.nr_lane;
46 : 0 : struct rnp_hw *hw = port->hw;
47 : : struct rnp_rx_queue *rxq;
48 : : uint16_t i, idx, shift;
49 : : uint16_t hwrid;
50 : : uint16_t qid = 0;
51 : :
52 [ # # ]: 0 : if (reta_size > RNP_RSS_INDIR_SIZE) {
53 : 0 : RNP_PMD_ERR("Invalid reta size, reta_size:%d", reta_size);
54 : 0 : return -EINVAL;
55 : : }
56 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
57 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
58 : 0 : shift = i % RTE_ETH_RETA_GROUP_SIZE;
59 [ # # ]: 0 : if (reta_conf[idx].mask & (1ULL << shift))
60 : 0 : indirtbl[i] = reta_conf[idx].reta[shift];
61 : : }
62 [ # # ]: 0 : for (i = 0; i < RNP_RSS_INDIR_SIZE; i++) {
63 : 0 : qid = indirtbl[i];
64 [ # # ]: 0 : if (qid < dev->data->nb_rx_queues) {
65 : 0 : rxq = dev->data->rx_queues[qid];
66 : 0 : hwrid = rxq->attr.index - port_offset;
67 : 0 : RNP_E_REG_WR(hw, RNP_RSS_REDIR_TB(lane, i), hwrid);
68 : 0 : rxq->rx_offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
69 : : } else {
70 : 0 : RNP_PMD_WARN("port[%d] reta[%d]-queue=%d "
71 : : "rx queue is out range of cur Settings",
72 : : dev->data->port_id, i, qid);
73 : : }
74 : : }
75 : 0 : port->reta_has_cfg = true;
76 : :
77 : 0 : return 0;
78 : : }
79 : :
80 : : static uint16_t
81 : : rnp_hwrid_to_queue_id(struct rte_eth_dev *dev, uint16_t hwrid)
82 : : {
83 : : struct rnp_rx_queue *rxq;
84 : : bool find = false;
85 : : uint16_t idx;
86 : :
87 [ # # ]: 0 : for (idx = 0; idx < dev->data->nb_rx_queues; idx++) {
88 : 0 : rxq = dev->data->rx_queues[idx];
89 [ # # ]: 0 : if (!rxq)
90 : 0 : continue;
91 [ # # ]: 0 : if (rxq->attr.index == hwrid) {
92 : : find = true;
93 : : break;
94 : : }
95 : : }
96 [ # # ]: 0 : if (find)
97 : 0 : return rxq->attr.queue_id;
98 : :
99 : : return UINT16_MAX;
100 : : }
101 : :
102 : : int
103 : 0 : rnp_dev_rss_reta_query(struct rte_eth_dev *dev,
104 : : struct rte_eth_rss_reta_entry64 *reta_conf,
105 : : uint16_t reta_size)
106 : : {
107 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
108 : 0 : uint16_t port_offset = port->attr.port_offset;
109 : 0 : struct rnp_hw *hw = port->hw;
110 : 0 : uint32_t *indirtbl = &port->indirtbl[0];
111 : 0 : uint16_t lane = port->attr.nr_lane;
112 : : uint16_t i, idx, shift;
113 : : uint16_t hwrid;
114 : : uint16_t queue_id;
115 : :
116 [ # # ]: 0 : if (reta_size > RNP_RSS_INDIR_SIZE) {
117 : 0 : RNP_PMD_ERR("Invalid reta size, reta_size:%d", reta_size);
118 : 0 : return -EINVAL;
119 : : }
120 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
121 : 0 : hwrid = RNP_E_REG_RD(hw, RNP_RSS_REDIR_TB(lane, i));
122 : 0 : hwrid = hwrid + port_offset;
123 : : queue_id = rnp_hwrid_to_queue_id(dev, hwrid);
124 [ # # ]: 0 : if (queue_id == UINT16_MAX) {
125 : 0 : RNP_PMD_ERR("Invalid rss-table value is the"
126 : : " Sw-queue not Match Hardware?");
127 : 0 : return -EINVAL;
128 : : }
129 : 0 : indirtbl[i] = queue_id;
130 : : }
131 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
132 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
133 : 0 : shift = i % RTE_ETH_RETA_GROUP_SIZE;
134 [ # # ]: 0 : if (reta_conf[idx].mask & (1ULL << shift))
135 : 0 : reta_conf[idx].reta[shift] = (uint16_t)indirtbl[i];
136 : : }
137 : :
138 : : return 0;
139 : : }
140 : :
141 : 0 : static void rnp_disable_rss(struct rte_eth_dev *dev)
142 : : {
143 : 0 : struct rnp_eth_adapter *adapter = RNP_DEV_TO_ADAPTER(dev);
144 : : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
145 : 0 : struct rte_eth_rss_conf *conf = &port->rss_conf;
146 : : struct rnp_rx_queue *rxq = NULL;
147 : : struct rnp_hw *hw = port->hw;
148 : : uint8_t rss_disable = 0;
149 : : uint32_t mrqc_reg = 0;
150 : : uint16_t lane, index;
151 : : uint16_t idx;
152 : :
153 : : memset(conf, 0, sizeof(*conf));
154 : 0 : lane = port->attr.nr_lane;
155 [ # # ]: 0 : for (idx = 0; idx < hw->max_port_num; idx++) {
156 [ # # ]: 0 : if (adapter->ports[idx] == NULL) {
157 : 0 : rss_disable++;
158 : 0 : continue;
159 : : }
160 [ # # ]: 0 : if (!adapter->ports[idx]->rss_conf.rss_hf)
161 : 0 : rss_disable++;
162 : : }
163 : :
164 [ # # ]: 0 : for (idx = 0; idx < dev->data->nb_rx_queues; idx++) {
165 : 0 : rxq = dev->data->rx_queues[idx];
166 [ # # ]: 0 : if (!rxq)
167 : 0 : continue;
168 : 0 : rxq->rx_offloads &= ~RTE_ETH_RX_OFFLOAD_RSS_HASH;
169 : : }
170 : : /* we use software way to achieve multiple port mode
171 : : * rss feature disable by set RSS table to default ring.
172 : : * So when re enable RSS,the rss reta table need to set
173 : : * last user set State
174 : : */
175 : 0 : rxq = dev->data->rx_queues[0];
176 : 0 : index = rxq->attr.index - port->attr.port_offset;
177 [ # # ]: 0 : for (idx = 0; idx < RNP_RSS_INDIR_SIZE; idx++)
178 : 0 : RNP_E_REG_WR(hw, RNP_RSS_REDIR_TB(lane, idx), index);
179 [ # # ]: 0 : if (rss_disable == hw->max_port_num) {
180 : 0 : mrqc_reg = RNP_E_REG_RD(hw, RNP_RSS_MRQC_ADDR);
181 : 0 : mrqc_reg &= ~RNP_RSS_HASH_CFG_MASK;
182 : 0 : RNP_E_REG_WR(hw, RNP_RSS_MRQC_ADDR, mrqc_reg);
183 : : }
184 : 0 : }
185 : :
186 : : static void
187 : 0 : rnp_rss_hash_set(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf)
188 : : {
189 : 0 : uint64_t rss_hash_level = RTE_ETH_RSS_LEVEL(rss_conf->rss_hf);
190 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
191 : : struct rnp_rx_queue *rxq = NULL;
192 : 0 : struct rnp_hw *hw = port->hw;
193 : : uint8_t *hash_key;
194 : : uint32_t mrqc_reg = 0;
195 : : uint32_t rss_key;
196 : : uint64_t rss_hf;
197 : : uint16_t i;
198 : :
199 : : rss_hf = rss_conf->rss_hf;
200 : 0 : hash_key = rss_conf->rss_key;
201 [ # # ]: 0 : if (hash_key != NULL) {
202 [ # # ]: 0 : for (i = 0; i < RNP_MAX_HASH_KEY_SIZE; i++) {
203 : 0 : rss_key = hash_key[(i * 4)];
204 : 0 : rss_key |= hash_key[(i * 4) + 1] << 8;
205 : 0 : rss_key |= hash_key[(i * 4) + 2] << 16;
206 : 0 : rss_key |= hash_key[(i * 4) + 3] << 24;
207 [ # # ]: 0 : rss_key = rte_cpu_to_be_32(rss_key);
208 : 0 : RNP_E_REG_WR(hw, RNP_RSS_KEY_TABLE(9 - i), rss_key);
209 : : }
210 : : }
211 [ # # ]: 0 : if (rss_hf) {
212 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rnp_rss_cfg); i++)
213 [ # # ]: 0 : if (rnp_rss_cfg[i].rss_flag & rss_hf)
214 : 0 : mrqc_reg |= rnp_rss_cfg[i].reg_val;
215 : : /* Enable inner rss mode
216 : : * If enable, outer(vxlan/nvgre) rss won't cals
217 : : */
218 [ # # ]: 0 : if (rss_hash_level == RNP_RSS_LEVEL_INNER)
219 : 0 : RNP_E_REG_WR(hw, RNP_RSS_INNER_CTRL, RNP_INNER_RSS_EN);
220 : : else
221 : 0 : RNP_E_REG_WR(hw, RNP_RSS_INNER_CTRL, RNP_INNER_RSS_DIS);
222 : 0 : RNP_E_REG_WR(hw, RNP_RSS_MRQC_ADDR, mrqc_reg);
223 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
224 : 0 : rxq = dev->data->rx_queues[i];
225 [ # # ]: 0 : if (!rxq)
226 : 0 : continue;
227 : 0 : rxq->rx_offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
228 : : }
229 : : }
230 : 0 : }
231 : :
232 : : static void
233 : 0 : rnp_reta_table_update(struct rte_eth_dev *dev)
234 : : {
235 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
236 : 0 : uint16_t port_offset = port->attr.port_offset;
237 : 0 : uint32_t *indirtbl = &port->indirtbl[0];
238 : 0 : struct rnp_hw *hw = port->hw;
239 : : struct rnp_rx_queue *rxq;
240 : : int i = 0, qid = 0, p_id;
241 : : uint16_t hwrid;
242 : :
243 : 0 : p_id = port->attr.nr_lane;
244 [ # # ]: 0 : for (i = 0; i < RNP_RSS_INDIR_SIZE; i++) {
245 : 0 : qid = indirtbl[i];
246 [ # # ]: 0 : if (qid < dev->data->nb_rx_queues) {
247 : 0 : rxq = dev->data->rx_queues[qid];
248 : 0 : hwrid = rxq->attr.index - port_offset;
249 : 0 : RNP_E_REG_WR(hw, RNP_RSS_REDIR_TB(p_id, i), hwrid);
250 : 0 : rxq->rx_offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
251 : : } else {
252 : 0 : RNP_PMD_LOG(WARNING, "port[%d] reta[%d]-queue=%d "
253 : : "rx queues is out range of cur set",
254 : : dev->data->port_id, i, qid);
255 : : }
256 : : }
257 : 0 : }
258 : :
259 : : int
260 : 0 : rnp_dev_rss_hash_update(struct rte_eth_dev *dev,
261 : : struct rte_eth_rss_conf *rss_conf)
262 : : {
263 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
264 : :
265 [ # # ]: 0 : if (rss_conf->rss_key &&
266 [ # # ]: 0 : rss_conf->rss_key_len > RNP_MAX_HASH_KEY_SIZE) {
267 : 0 : RNP_PMD_ERR("Invalid rss key, rss_key_len:%d",
268 : : rss_conf->rss_key_len);
269 : 0 : return -EINVAL;
270 : : }
271 [ # # ]: 0 : if (rss_conf->rss_hf &&
272 [ # # ]: 0 : (!(rss_conf->rss_hf & RNP_SUPPORT_RSS_OFFLOAD_ALL))) {
273 : 0 : RNP_PMD_ERR("RSS type don't support");
274 : 0 : return -EINVAL;
275 : : }
276 [ # # ]: 0 : if (!rss_conf->rss_hf) {
277 : 0 : rnp_disable_rss(dev);
278 : : } else {
279 : 0 : rnp_rss_hash_set(dev, rss_conf);
280 : 0 : rnp_reta_table_update(dev);
281 : : }
282 : 0 : port->rss_conf = *rss_conf;
283 : :
284 : 0 : return 0;
285 : : }
286 : :
287 : : int
288 : 0 : rnp_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
289 : : struct rte_eth_rss_conf *rss_conf)
290 : : {
291 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
292 : 0 : struct rnp_hw *hw = port->hw;
293 : : uint8_t *hash_key;
294 : : uint32_t rss_key;
295 : : uint64_t rss_hf;
296 : : uint32_t mrqc;
297 : : uint16_t i;
298 : :
299 : 0 : hash_key = rss_conf->rss_key;
300 [ # # ]: 0 : if (hash_key != NULL) {
301 [ # # ]: 0 : for (i = 0; i < 10; i++) {
302 : 0 : rss_key = RNP_E_REG_RD(hw, RNP_RSS_KEY_TABLE(9 - i));
303 [ # # ]: 0 : rss_key = rte_be_to_cpu_32(rss_key);
304 : 0 : hash_key[(i * 4)] = rss_key & 0x000000FF;
305 : 0 : hash_key[(i * 4) + 1] = (rss_key >> 8) & 0x000000FF;
306 : 0 : hash_key[(i * 4) + 2] = (rss_key >> 16) & 0x000000FF;
307 : 0 : hash_key[(i * 4) + 3] = (rss_key >> 24) & 0x000000FF;
308 : : }
309 : : }
310 : : rss_hf = 0;
311 : 0 : mrqc = RNP_E_REG_RD(hw, RNP_RSS_MRQC_ADDR) & RNP_RSS_HASH_CFG_MASK;
312 [ # # ]: 0 : if (mrqc == 0) {
313 : 0 : rss_conf->rss_hf = 0;
314 : 0 : return 0;
315 : : }
316 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rnp_rss_cfg); i++)
317 [ # # ]: 0 : if (rnp_rss_cfg[i].reg_val & mrqc)
318 : 0 : rss_hf |= rnp_rss_cfg[i].rss_flag;
319 : :
320 : 0 : rss_conf->rss_hf = rss_hf;
321 : :
322 : 0 : return 0;
323 : : }
324 : :
325 : 0 : int rnp_dev_rss_configure(struct rte_eth_dev *dev)
326 : : {
327 : 0 : struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
328 : 0 : uint32_t *indirtbl = port->indirtbl;
329 : : enum rte_eth_rx_mq_mode mq_mode = 0;
330 : : struct rte_eth_rss_conf rss_conf;
331 : : struct rnp_rx_queue *rxq;
332 : : int i, j;
333 : :
334 : 0 : mq_mode = dev->data->dev_conf.rxmode.mq_mode;
335 [ # # ]: 0 : if (dev->data->rx_queues == NULL) {
336 : 0 : RNP_PMD_ERR("rx_queue is not setup skip rss set");
337 : 0 : return -EINVAL;
338 : : }
339 : 0 : rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;
340 [ # # ]: 0 : if (!(rss_conf.rss_hf & RNP_SUPPORT_RSS_OFFLOAD_ALL) ||
341 [ # # ]: 0 : !(mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)) {
342 : 0 : rnp_disable_rss(dev);
343 : :
344 : 0 : return 0;
345 : : }
346 [ # # ]: 0 : if (rss_conf.rss_key == NULL)
347 : 0 : rss_conf.rss_key = rnp_rss_default_key;
348 : :
349 [ # # # # ]: 0 : if (port->rxq_num_changed || !port->reta_has_cfg) {
350 : : /* set default reta policy */
351 [ # # ]: 0 : for (i = 0; i < RNP_RSS_INDIR_SIZE; i++) {
352 : 0 : j = i % dev->data->nb_rx_queues;
353 : 0 : rxq = dev->data->rx_queues[j];
354 [ # # ]: 0 : if (!rxq) {
355 : 0 : RNP_PMD_ERR("rss Set reta-cfg rxq %d Is NULL", i);
356 : 0 : return -EINVAL;
357 : : }
358 : 0 : indirtbl[i] = rxq->attr.queue_id;
359 : : }
360 : : }
361 : 0 : rnp_reta_table_update(dev);
362 : 0 : port->rss_conf = rss_conf;
363 : : /* setup rss key and hash func */
364 : 0 : rnp_rss_hash_set(dev, &rss_conf);
365 : :
366 : 0 : return 0;
367 : : }
|