]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright 2015 6WIND S.A. | |
3 | * Copyright 2015 Mellanox Technologies, Ltd | |
4 | */ | |
5 | ||
6 | #include <stddef.h> | |
7 | #include <stdint.h> | |
8 | #include <errno.h> | |
9 | #include <string.h> | |
11fdf7f2 TL |
10 | |
11 | /* Verbs header. */ | |
12 | /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ | |
13 | #ifdef PEDANTIC | |
14 | #pragma GCC diagnostic ignored "-Wpedantic" | |
15 | #endif | |
16 | #include <infiniband/verbs.h> | |
17 | #ifdef PEDANTIC | |
18 | #pragma GCC diagnostic error "-Wpedantic" | |
19 | #endif | |
20 | ||
21 | #include <rte_malloc.h> | |
22 | #include <rte_ethdev_driver.h> | |
23 | ||
11fdf7f2 | 24 | #include "mlx5_defs.h" |
f67539c2 | 25 | #include "mlx5.h" |
11fdf7f2 TL |
26 | #include "mlx5_rxtx.h" |
27 | ||
28 | /** | |
29 | * DPDK callback to update the RSS hash configuration. | |
30 | * | |
31 | * @param dev | |
32 | * Pointer to Ethernet device structure. | |
33 | * @param[in] rss_conf | |
34 | * RSS configuration data. | |
35 | * | |
36 | * @return | |
37 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
38 | */ | |
39 | int | |
40 | mlx5_rss_hash_update(struct rte_eth_dev *dev, | |
41 | struct rte_eth_rss_conf *rss_conf) | |
42 | { | |
9f95a23c | 43 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
44 | unsigned int i; |
45 | unsigned int idx; | |
46 | ||
47 | if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { | |
48 | rte_errno = EINVAL; | |
49 | return -rte_errno; | |
50 | } | |
51 | if (rss_conf->rss_key && rss_conf->rss_key_len) { | |
52 | if (rss_conf->rss_key_len != MLX5_RSS_HASH_KEY_LEN) { | |
53 | DRV_LOG(ERR, | |
54 | "port %u RSS key len must be %s Bytes long", | |
55 | dev->data->port_id, | |
56 | RTE_STR(MLX5_RSS_HASH_KEY_LEN)); | |
57 | rte_errno = EINVAL; | |
58 | return -rte_errno; | |
59 | } | |
60 | priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, | |
61 | rss_conf->rss_key_len, 0); | |
62 | if (!priv->rss_conf.rss_key) { | |
63 | rte_errno = ENOMEM; | |
64 | return -rte_errno; | |
65 | } | |
66 | memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, | |
67 | rss_conf->rss_key_len); | |
68 | priv->rss_conf.rss_key_len = rss_conf->rss_key_len; | |
69 | } | |
70 | priv->rss_conf.rss_hf = rss_conf->rss_hf; | |
71 | /* Enable the RSS hash in all Rx queues. */ | |
72 | for (i = 0, idx = 0; idx != priv->rxqs_n; ++i) { | |
73 | if (!(*priv->rxqs)[i]) | |
74 | continue; | |
75 | (*priv->rxqs)[i]->rss_hash = !!rss_conf->rss_hf && | |
76 | !!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS); | |
77 | ++idx; | |
78 | } | |
79 | return 0; | |
80 | } | |
81 | ||
82 | /** | |
83 | * DPDK callback to get the RSS hash configuration. | |
84 | * | |
85 | * @param dev | |
86 | * Pointer to Ethernet device structure. | |
87 | * @param[in, out] rss_conf | |
88 | * RSS configuration data. | |
89 | * | |
90 | * @return | |
91 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
92 | */ | |
93 | int | |
94 | mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, | |
95 | struct rte_eth_rss_conf *rss_conf) | |
96 | { | |
9f95a23c | 97 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
98 | |
99 | if (!rss_conf) { | |
100 | rte_errno = EINVAL; | |
101 | return -rte_errno; | |
102 | } | |
103 | if (rss_conf->rss_key && | |
104 | (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { | |
105 | memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, | |
106 | priv->rss_conf.rss_key_len); | |
107 | } | |
108 | rss_conf->rss_key_len = priv->rss_conf.rss_key_len; | |
109 | rss_conf->rss_hf = priv->rss_conf.rss_hf; | |
110 | return 0; | |
111 | } | |
112 | ||
113 | /** | |
114 | * Allocate/reallocate RETA index table. | |
115 | * | |
116 | * @param dev | |
117 | * Pointer to Ethernet device. | |
118 | * @praram reta_size | |
119 | * The size of the array to allocate. | |
120 | * | |
121 | * @return | |
122 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
123 | */ | |
124 | int | |
125 | mlx5_rss_reta_index_resize(struct rte_eth_dev *dev, unsigned int reta_size) | |
126 | { | |
9f95a23c | 127 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
128 | void *mem; |
129 | unsigned int old_size = priv->reta_idx_n; | |
130 | ||
131 | if (priv->reta_idx_n == reta_size) | |
132 | return 0; | |
133 | ||
134 | mem = rte_realloc(priv->reta_idx, | |
135 | reta_size * sizeof((*priv->reta_idx)[0]), 0); | |
136 | if (!mem) { | |
137 | rte_errno = ENOMEM; | |
138 | return -rte_errno; | |
139 | } | |
140 | priv->reta_idx = mem; | |
141 | priv->reta_idx_n = reta_size; | |
142 | if (old_size < reta_size) | |
143 | memset(&(*priv->reta_idx)[old_size], 0, | |
144 | (reta_size - old_size) * | |
145 | sizeof((*priv->reta_idx)[0])); | |
146 | return 0; | |
147 | } | |
148 | ||
149 | /** | |
150 | * DPDK callback to get the RETA indirection table. | |
151 | * | |
152 | * @param dev | |
153 | * Pointer to Ethernet device structure. | |
154 | * @param reta_conf | |
155 | * Pointer to RETA configuration structure array. | |
156 | * @param reta_size | |
157 | * Size of the RETA table. | |
158 | * | |
159 | * @return | |
160 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
161 | */ | |
162 | int | |
163 | mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, | |
164 | struct rte_eth_rss_reta_entry64 *reta_conf, | |
165 | uint16_t reta_size) | |
166 | { | |
9f95a23c | 167 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
168 | unsigned int idx; |
169 | unsigned int i; | |
170 | ||
171 | if (!reta_size || reta_size > priv->reta_idx_n) { | |
172 | rte_errno = EINVAL; | |
173 | return -rte_errno; | |
174 | } | |
175 | /* Fill each entry of the table even if its bit is not set. */ | |
176 | for (idx = 0, i = 0; (i != reta_size); ++i) { | |
177 | idx = i / RTE_RETA_GROUP_SIZE; | |
178 | reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = | |
179 | (*priv->reta_idx)[i]; | |
180 | } | |
181 | return 0; | |
182 | } | |
183 | ||
184 | /** | |
185 | * DPDK callback to update the RETA indirection table. | |
186 | * | |
187 | * @param dev | |
188 | * Pointer to Ethernet device structure. | |
189 | * @param reta_conf | |
190 | * Pointer to RETA configuration structure array. | |
191 | * @param reta_size | |
192 | * Size of the RETA table. | |
193 | * | |
194 | * @return | |
195 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
196 | */ | |
197 | int | |
198 | mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, | |
199 | struct rte_eth_rss_reta_entry64 *reta_conf, | |
200 | uint16_t reta_size) | |
201 | { | |
202 | int ret; | |
9f95a23c | 203 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
204 | unsigned int idx; |
205 | unsigned int i; | |
206 | unsigned int pos; | |
207 | ||
208 | if (!reta_size) { | |
209 | rte_errno = EINVAL; | |
210 | return -rte_errno; | |
211 | } | |
212 | ret = mlx5_rss_reta_index_resize(dev, reta_size); | |
213 | if (ret) | |
214 | return ret; | |
215 | for (idx = 0, i = 0; (i != reta_size); ++i) { | |
216 | idx = i / RTE_RETA_GROUP_SIZE; | |
217 | pos = i % RTE_RETA_GROUP_SIZE; | |
218 | if (((reta_conf[idx].mask >> i) & 0x1) == 0) | |
219 | continue; | |
f67539c2 | 220 | MLX5_ASSERT(reta_conf[idx].reta[pos] < priv->rxqs_n); |
11fdf7f2 TL |
221 | (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; |
222 | } | |
223 | if (dev->data->dev_started) { | |
224 | mlx5_dev_stop(dev); | |
f67539c2 | 225 | priv->skip_default_rss_reta = 1; |
11fdf7f2 TL |
226 | return mlx5_dev_start(dev); |
227 | } | |
228 | return 0; | |
229 | } |