1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2019 Solarflare Communications Inc.
6 * This software was jointly developed between OKTET Labs (under contract
7 * for Solarflare) and Solarflare Communications, Inc.
12 #include <rte_ethdev.h>
13 #include <rte_malloc.h>
14 #include <ethdev_driver.h>
19 #include "sfc_debug.h"
21 #include "sfc_ethdev_state.h"
22 #include "sfc_repr_proxy_api.h"
23 #include "sfc_switch.h"
25 /** Multi-process shared representor private data */
26 struct sfc_repr_shared {
29 uint16_t switch_domain_id;
30 uint16_t switch_port_id;
33 /** Primary process representor private data */
36 * PMD setup and configuration is not thread safe. Since it is not
37 * performance sensitive, it is better to guarantee thread-safety
38 * and add device level lock. Adapter control operations which
39 * change its state should acquire the lock.
42 enum sfc_ethdev_state state;
45 #define sfcr_err(sr, ...) \
47 const struct sfc_repr *_sr = (sr); \
50 SFC_GENERIC_LOG(ERR, __VA_ARGS__); \
53 #define sfcr_info(sr, ...) \
55 const struct sfc_repr *_sr = (sr); \
58 SFC_GENERIC_LOG(INFO, \
60 RTE_FMT_HEAD(__VA_ARGS__ ,), \
62 RTE_FMT_TAIL(__VA_ARGS__ ,))); \
65 static inline struct sfc_repr_shared *
66 sfc_repr_shared_by_eth_dev(struct rte_eth_dev *eth_dev)
68 struct sfc_repr_shared *srs = eth_dev->data->dev_private;
73 static inline struct sfc_repr *
74 sfc_repr_by_eth_dev(struct rte_eth_dev *eth_dev)
76 struct sfc_repr *sr = eth_dev->process_private;
82 * Add wrapper functions to acquire/release lock to be able to remove or
83 * change the lock in one place.
87 sfc_repr_lock_init(struct sfc_repr *sr)
89 rte_spinlock_init(&sr->lock);
92 #if defined(RTE_LIBRTE_SFC_EFX_DEBUG) || defined(RTE_ENABLE_ASSERT)
95 sfc_repr_lock_is_locked(struct sfc_repr *sr)
97 return rte_spinlock_is_locked(&sr->lock);
103 sfc_repr_lock(struct sfc_repr *sr)
105 rte_spinlock_lock(&sr->lock);
109 sfc_repr_unlock(struct sfc_repr *sr)
111 rte_spinlock_unlock(&sr->lock);
115 sfc_repr_lock_fini(__rte_unused struct sfc_repr *sr)
117 /* Just for symmetry of the API */
121 sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues,
122 const struct rte_eth_conf *conf)
124 const struct rte_eth_rss_conf *rss_conf;
127 sfcr_info(sr, "entry");
129 if (conf->link_speeds != 0) {
130 sfcr_err(sr, "specific link speeds not supported");
134 switch (conf->rxmode.mq_mode) {
136 if (nb_rx_queues != 1) {
137 sfcr_err(sr, "Rx RSS is not supported with %u queues",
143 rss_conf = &conf->rx_adv_conf.rss_conf;
144 if (rss_conf->rss_key != NULL || rss_conf->rss_key_len != 0 ||
145 rss_conf->rss_hf != 0) {
146 sfcr_err(sr, "Rx RSS configuration is not supported");
153 sfcr_err(sr, "Rx mode MQ modes other than RSS not supported");
158 if (conf->txmode.mq_mode != ETH_MQ_TX_NONE) {
159 sfcr_err(sr, "Tx mode MQ modes not supported");
163 if (conf->lpbk_mode != 0) {
164 sfcr_err(sr, "loopback not supported");
168 if (conf->dcb_capability_en != 0) {
169 sfcr_err(sr, "priority-based flow control not supported");
173 if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) {
174 sfcr_err(sr, "Flow Director not supported");
178 if (conf->intr_conf.lsc != 0) {
179 sfcr_err(sr, "link status change interrupt not supported");
183 if (conf->intr_conf.rxq != 0) {
184 sfcr_err(sr, "receive queue interrupt not supported");
188 if (conf->intr_conf.rmv != 0) {
189 sfcr_err(sr, "remove interrupt not supported");
193 sfcr_info(sr, "done %d", ret);
200 sfc_repr_configure(struct sfc_repr *sr, uint16_t nb_rx_queues,
201 const struct rte_eth_conf *conf)
205 sfcr_info(sr, "entry");
207 SFC_ASSERT(sfc_repr_lock_is_locked(sr));
209 ret = sfc_repr_check_conf(sr, nb_rx_queues, conf);
211 goto fail_check_conf;
213 sr->state = SFC_ETHDEV_CONFIGURED;
215 sfcr_info(sr, "done");
220 sfcr_info(sr, "failed %s", rte_strerror(-ret));
225 sfc_repr_dev_configure(struct rte_eth_dev *dev)
227 struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
228 struct rte_eth_dev_data *dev_data = dev->data;
231 sfcr_info(sr, "entry n_rxq=%u n_txq=%u",
232 dev_data->nb_rx_queues, dev_data->nb_tx_queues);
236 case SFC_ETHDEV_CONFIGURED:
238 case SFC_ETHDEV_INITIALIZED:
239 ret = sfc_repr_configure(sr, dev_data->nb_rx_queues,
240 &dev_data->dev_conf);
243 sfcr_err(sr, "unexpected adapter state %u to configure",
250 sfcr_info(sr, "done %s", rte_strerror(-ret));
256 sfc_repr_dev_infos_get(struct rte_eth_dev *dev,
257 struct rte_eth_dev_info *dev_info)
259 struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
261 dev_info->device = dev->device;
263 dev_info->max_rx_queues = SFC_REPR_RXQ_MAX;
264 dev_info->max_tx_queues = SFC_REPR_TXQ_MAX;
265 dev_info->default_rxconf.rx_drop_en = 1;
266 dev_info->switch_info.domain_id = srs->switch_domain_id;
267 dev_info->switch_info.port_id = srs->switch_port_id;
273 sfc_repr_close(struct sfc_repr *sr)
275 SFC_ASSERT(sfc_repr_lock_is_locked(sr));
277 SFC_ASSERT(sr->state == SFC_ETHDEV_CONFIGURED);
278 sr->state = SFC_ETHDEV_CLOSING;
280 /* Put representor close actions here */
282 sr->state = SFC_ETHDEV_INITIALIZED;
286 sfc_repr_dev_close(struct rte_eth_dev *dev)
288 struct sfc_repr *sr = sfc_repr_by_eth_dev(dev);
289 struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
291 sfcr_info(sr, "entry");
295 case SFC_ETHDEV_CONFIGURED:
297 SFC_ASSERT(sr->state == SFC_ETHDEV_INITIALIZED);
299 case SFC_ETHDEV_INITIALIZED:
302 sfcr_err(sr, "unexpected adapter state %u on close", sr->state);
307 * Cleanup all resources.
308 * Rollback primary process sfc_repr_eth_dev_init() below.
311 (void)sfc_repr_proxy_del_port(srs->pf_port_id, srs->repr_id);
316 sfc_repr_lock_fini(sr);
318 sfcr_info(sr, "done");
325 static const struct eth_dev_ops sfc_repr_dev_ops = {
326 .dev_configure = sfc_repr_dev_configure,
327 .dev_close = sfc_repr_dev_close,
328 .dev_infos_get = sfc_repr_dev_infos_get,
332 struct sfc_repr_init_data {
335 uint16_t switch_domain_id;
336 efx_mport_sel_t mport_sel;
340 sfc_repr_assign_mae_switch_port(uint16_t switch_domain_id,
341 const struct sfc_mae_switch_port_request *req,
342 uint16_t *switch_port_id)
346 rc = sfc_mae_assign_switch_port(switch_domain_id, req, switch_port_id);
353 sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
355 const struct sfc_repr_init_data *repr_data = init_params;
356 struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
357 struct sfc_mae_switch_port_request switch_port_request;
358 efx_mport_sel_t ethdev_mport_sel;
363 * Currently there is no mport we can use for representor's
364 * ethdev. Use an invalid one for now. This way representors
365 * can be instantiated.
367 efx_mae_mport_invalid(ðdev_mport_sel);
369 memset(&switch_port_request, 0, sizeof(switch_port_request));
370 switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
371 switch_port_request.ethdev_mportp = ðdev_mport_sel;
372 switch_port_request.entity_mportp = &repr_data->mport_sel;
373 switch_port_request.ethdev_port_id = dev->data->port_id;
375 ret = sfc_repr_assign_mae_switch_port(repr_data->switch_domain_id,
376 &switch_port_request,
377 &srs->switch_port_id);
380 "%s() failed to assign MAE switch port (domain id %u)",
381 __func__, repr_data->switch_domain_id);
382 goto fail_mae_assign_switch_port;
385 ret = sfc_repr_proxy_add_port(repr_data->pf_port_id,
388 &repr_data->mport_sel);
390 SFC_GENERIC_LOG(ERR, "%s() failed to add repr proxy port",
394 goto fail_create_port;
398 * Allocate process private data from heap, since it should not
399 * be located in shared memory allocated using rte_malloc() API.
401 sr = calloc(1, sizeof(*sr));
407 sfc_repr_lock_init(sr);
410 dev->process_private = sr;
412 srs->pf_port_id = repr_data->pf_port_id;
413 srs->repr_id = repr_data->repr_id;
414 srs->switch_domain_id = repr_data->switch_domain_id;
416 dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
417 dev->data->representor_id = srs->repr_id;
418 dev->data->backer_port_id = srs->pf_port_id;
420 dev->data->mac_addrs = rte_zmalloc("sfcr", RTE_ETHER_ADDR_LEN, 0);
421 if (dev->data->mac_addrs == NULL) {
426 dev->dev_ops = &sfc_repr_dev_ops;
428 sr->state = SFC_ETHDEV_INITIALIZED;
438 (void)sfc_repr_proxy_del_port(repr_data->pf_port_id,
442 fail_mae_assign_switch_port:
443 SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
448 sfc_repr_create(struct rte_eth_dev *parent, uint16_t representor_id,
449 uint16_t switch_domain_id, const efx_mport_sel_t *mport_sel)
451 struct sfc_repr_init_data repr_data;
452 char name[RTE_ETH_NAME_MAX_LEN];
455 if (snprintf(name, sizeof(name), "net_%s_representor_%u",
456 parent->device->name, representor_id) >=
458 SFC_GENERIC_LOG(ERR, "%s() failed name too long", __func__);
459 return -ENAMETOOLONG;
462 memset(&repr_data, 0, sizeof(repr_data));
463 repr_data.pf_port_id = parent->data->port_id;
464 repr_data.repr_id = representor_id;
465 repr_data.switch_domain_id = switch_domain_id;
466 repr_data.mport_sel = *mport_sel;
468 ret = rte_eth_dev_create(parent->device, name,
469 sizeof(struct sfc_repr_shared),
471 sfc_repr_eth_dev_init, &repr_data);
473 SFC_GENERIC_LOG(ERR, "%s() failed to create device", __func__);
475 SFC_GENERIC_LOG(INFO, "%s() done: %s", __func__, rte_strerror(-ret));