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