1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2019 Marvell International Ltd.
5 #include "otx2_ethdev.h"
8 otx2_nix_rss_tbl_init(struct otx2_eth_dev *dev,
9 uint8_t group, uint16_t *ind_tbl)
11 struct otx2_rss_info *rss = &dev->rss_info;
12 struct otx2_mbox *mbox = dev->mbox;
13 struct nix_aq_enq_req *req;
16 for (idx = 0; idx < rss->rss_size; idx++) {
17 req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
19 /* The shared memory buffer can be full.
22 otx2_mbox_msg_send(mbox, 0);
23 rc = otx2_mbox_wait_for_rsp(mbox, 0);
27 req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
31 req->rss.rq = ind_tbl[idx];
33 req->qidx = (group * rss->rss_size) + idx;
34 req->ctype = NIX_AQ_CTYPE_RSS;
35 req->op = NIX_AQ_INSTOP_INIT;
38 otx2_mbox_msg_send(mbox, 0);
39 rc = otx2_mbox_wait_for_rsp(mbox, 0);
47 otx2_nix_dev_reta_update(struct rte_eth_dev *eth_dev,
48 struct rte_eth_rss_reta_entry64 *reta_conf,
51 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
52 struct otx2_rss_info *rss = &dev->rss_info;
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);
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];
73 return otx2_nix_rss_tbl_init(dev, 0, dev->rss_info.ind_tbl);
80 otx2_nix_dev_reta_query(struct rte_eth_dev *eth_dev,
81 struct rte_eth_rss_reta_entry64 *reta_conf,
84 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
85 struct otx2_rss_info *rss = &dev->rss_info;
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);
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];
111 otx2_nix_rss_set_key(struct otx2_eth_dev *dev, uint8_t *key,
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
122 struct otx2_rss_info *rss = &dev->rss_info;
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);
132 memcpy(rss->key, key, key_len);
133 keyptr = (uint64_t *)rss->key;
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));
144 rss_get_key(struct otx2_eth_dev *dev, uint8_t *key)
146 uint64_t *keyptr = (uint64_t *)key;
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);
157 #define RSS_IPV4_ENABLE ( \
159 ETH_RSS_FRAG_IPV4 | \
160 ETH_RSS_NONFRAG_IPV4_UDP | \
161 ETH_RSS_NONFRAG_IPV4_TCP | \
162 ETH_RSS_NONFRAG_IPV4_SCTP)
164 #define RSS_IPV6_ENABLE ( \
166 ETH_RSS_FRAG_IPV6 | \
167 ETH_RSS_NONFRAG_IPV6_UDP | \
168 ETH_RSS_NONFRAG_IPV6_TCP | \
169 ETH_RSS_NONFRAG_IPV6_SCTP)
171 #define RSS_IPV6_EX_ENABLE ( \
173 ETH_RSS_IPV6_TCP_EX | \
176 #define RSS_MAX_LEVELS 3
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
186 otx2_rss_ethdev_to_nix(struct otx2_eth_dev *dev, uint64_t ethdev_rss,
189 uint32_t flow_key_type[RSS_MAX_LEVELS][6] = {
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
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
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
209 uint32_t flowkey_cfg = 0;
211 dev->rss_info.nix_rss = ethdev_rss;
213 if (ethdev_rss & RSS_IPV4_ENABLE)
214 flowkey_cfg |= flow_key_type[rss_level][RSS_IPV4_INDEX];
216 if (ethdev_rss & RSS_IPV6_ENABLE)
217 flowkey_cfg |= flow_key_type[rss_level][RSS_IPV6_INDEX];
219 if (ethdev_rss & ETH_RSS_TCP)
220 flowkey_cfg |= flow_key_type[rss_level][RSS_TCP_INDEX];
222 if (ethdev_rss & ETH_RSS_UDP)
223 flowkey_cfg |= flow_key_type[rss_level][RSS_UDP_INDEX];
225 if (ethdev_rss & ETH_RSS_SCTP)
226 flowkey_cfg |= flow_key_type[rss_level][RSS_SCTP_INDEX];
228 if (ethdev_rss & ETH_RSS_L2_PAYLOAD)
229 flowkey_cfg |= flow_key_type[rss_level][RSS_DMAC_INDEX];
231 if (ethdev_rss & RSS_IPV6_EX_ENABLE)
232 flowkey_cfg |= FLOW_KEY_TYPE_IPV6_EXT;
234 if (ethdev_rss & ETH_RSS_PORT)
235 flowkey_cfg |= FLOW_KEY_TYPE_PORT;
237 if (ethdev_rss & ETH_RSS_NVGRE)
238 flowkey_cfg |= FLOW_KEY_TYPE_NVGRE;
240 if (ethdev_rss & ETH_RSS_VXLAN)
241 flowkey_cfg |= FLOW_KEY_TYPE_VXLAN;
243 if (ethdev_rss & ETH_RSS_GENEVE)
244 flowkey_cfg |= FLOW_KEY_TYPE_GENEVE;
250 otx2_rss_set_hf(struct otx2_eth_dev *dev, uint32_t flowkey_cfg,
251 uint8_t *alg_idx, uint8_t group, int mcam_index)
253 struct nix_rss_flowkey_cfg_rsp *rss_rsp;
254 struct otx2_mbox *mbox = dev->mbox;
255 struct nix_rss_flowkey_cfg *cfg;
260 dev->rss_info.flowkey_cfg = flowkey_cfg;
262 cfg = otx2_mbox_alloc_msg_nix_rss_flowkey_cfg(mbox);
264 cfg->flowkey_cfg = flowkey_cfg;
265 cfg->mcam_index = mcam_index; /* -1 indicates default group */
266 cfg->group = group; /* 0 is default group */
268 rc = otx2_mbox_process_msg(mbox, (void *)&rss_rsp);
273 *alg_idx = rss_rsp->alg_idx;
279 otx2_nix_rss_hash_update(struct rte_eth_dev *eth_dev,
280 struct rte_eth_rss_conf *rss_conf)
282 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
283 uint32_t flowkey_cfg;
289 if (rss_conf->rss_key && rss_conf->rss_key_len != NIX_HASH_KEY_SIZE) {
290 otx2_err("Hash key size mismatch %d vs %d",
291 rss_conf->rss_key_len, NIX_HASH_KEY_SIZE);
295 if (rss_conf->rss_key)
296 otx2_nix_rss_set_key(dev, rss_conf->rss_key,
297 (uint32_t)rss_conf->rss_key_len);
299 flowkey_cfg = otx2_rss_ethdev_to_nix(dev, rss_conf->rss_hf, 0);
301 rc = otx2_rss_set_hf(dev, flowkey_cfg, &alg_idx,
302 NIX_DEFAULT_RSS_CTX_GROUP,
303 NIX_DEFAULT_RSS_MCAM_IDX);
305 otx2_err("Failed to set RSS hash function rc=%d", rc);
309 dev->rss_info.alg_idx = alg_idx;
316 otx2_nix_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
317 struct rte_eth_rss_conf *rss_conf)
319 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
321 if (rss_conf->rss_key)
322 rss_get_key(dev, rss_conf->rss_key);
324 rss_conf->rss_key_len = NIX_HASH_KEY_SIZE;
325 rss_conf->rss_hf = dev->rss_info.nix_rss;
331 otx2_nix_rss_config(struct rte_eth_dev *eth_dev)
333 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
334 uint32_t idx, qcnt = eth_dev->data->nb_rx_queues;
335 uint32_t flowkey_cfg;
340 /* Skip further configuration if selected mode is not RSS */
341 if (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS)
344 /* Update default RSS key and cfg */
345 otx2_nix_rss_set_key(dev, NULL, 0);
347 /* Update default RSS RETA */
348 for (idx = 0; idx < dev->rss_info.rss_size; idx++)
349 dev->rss_info.ind_tbl[idx] = idx % qcnt;
351 /* Init RSS table context */
352 rc = otx2_nix_rss_tbl_init(dev, 0, dev->rss_info.ind_tbl);
354 otx2_err("Failed to init RSS table rc=%d", rc);
358 rss_hf = eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
359 flowkey_cfg = otx2_rss_ethdev_to_nix(dev, rss_hf, 0);
361 rc = otx2_rss_set_hf(dev, flowkey_cfg, &alg_idx,
362 NIX_DEFAULT_RSS_CTX_GROUP,
363 NIX_DEFAULT_RSS_MCAM_IDX);
365 otx2_err("Failed to set RSS hash function rc=%d", rc);
369 dev->rss_info.alg_idx = alg_idx;