X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_trigger.c;h=94dd56709e38cbac1688d6ce54d4fc11c4651049;hb=46413898cf1df5798b8d1ea04522da0f0ce97205;hp=28ce8dd9cbfaef042fa508a8aa8e3fac738c839e;hpb=37cd4501e873f30c69f738c3efe4730e7c95d60a;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index 28ce8dd9cb..94dd56709e 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -6,9 +6,10 @@ #include #include -#include +#include #include #include +#include #include @@ -77,6 +78,7 @@ mlx5_txq_start(struct rte_eth_dev *dev) } if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) { size_t size = txq_data->cqe_s * sizeof(*txq_data->fcqs); + txq_data->fcqs = mlx5_malloc(flags, size, RTE_CACHE_LINE_SIZE, txq_ctrl->socket); @@ -218,6 +220,8 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev) struct mlx5_devx_obj *rq; unsigned int i; int ret = 0; + bool need_auto = false; + uint16_t self_port = dev->data->port_id; for (i = 0; i != priv->txqs_n; ++i) { txq_ctrl = mlx5_txq_get(dev, i); @@ -227,6 +231,28 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev) mlx5_txq_release(dev, i); continue; } + if (txq_ctrl->hairpin_conf.peers[0].port != self_port) + continue; + if (txq_ctrl->hairpin_conf.manual_bind) { + mlx5_txq_release(dev, i); + return 0; + } + need_auto = true; + mlx5_txq_release(dev, i); + } + if (!need_auto) + return 0; + for (i = 0; i != priv->txqs_n; ++i) { + txq_ctrl = mlx5_txq_get(dev, i); + if (!txq_ctrl) + continue; + if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) { + mlx5_txq_release(dev, i); + continue; + } + /* Skip hairpin queues with other peer ports. */ + if (txq_ctrl->hairpin_conf.peers[0].port != self_port) + continue; if (!txq_ctrl->obj) { rte_errno = ENOMEM; DRV_LOG(ERR, "port %u no txq object found: %d", @@ -275,6 +301,9 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev) ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr); if (ret) goto error; + /* Qs with auto-bind will be destroyed directly. */ + rxq_ctrl->hairpin_status = 1; + txq_ctrl->hairpin_status = 1; mlx5_txq_release(dev, i); mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue); } @@ -906,7 +935,96 @@ mlx5_hairpin_unbind(struct rte_eth_dev *dev, uint16_t rx_port) return ret; } else - ret = mlx5_hairpin_bind_single_port(dev, rx_port); + ret = mlx5_hairpin_unbind_single_port(dev, rx_port); + return ret; +} + +/* + * DPDK callback to get the hairpin peer ports list. + * This will return the actual number of peer ports and save the identifiers + * into the array (sorted, may be different from that when setting up the + * hairpin peer queues). + * The peer port ID could be the same as the port ID of the current device. + * + * @param dev + * Pointer to Ethernet device structure. + * @param peer_ports + * Pointer to array to save the port identifiers. + * @param len + * The length of the array. + * @param direction + * Current port to peer port direction. + * positive - current used as Tx to get all peer Rx ports. + * zero - current used as Rx to get all peer Tx ports. + * + * @return + * 0 or positive value on success, actual number of peer ports. + * a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports, + size_t len, uint32_t direction) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_txq_ctrl *txq_ctrl; + struct mlx5_rxq_ctrl *rxq_ctrl; + uint32_t i; + uint16_t pp; + uint32_t bits[(RTE_MAX_ETHPORTS + 31) / 32] = {0}; + int ret = 0; + + if (direction) { + for (i = 0; i < priv->txqs_n; i++) { + txq_ctrl = mlx5_txq_get(dev, i); + if (!txq_ctrl) + continue; + if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) { + mlx5_txq_release(dev, i); + continue; + } + pp = txq_ctrl->hairpin_conf.peers[0].port; + if (pp >= RTE_MAX_ETHPORTS) { + rte_errno = ERANGE; + mlx5_txq_release(dev, i); + DRV_LOG(ERR, "port %hu queue %u peer port " + "out of range %hu", + priv->dev_data->port_id, i, pp); + return -rte_errno; + } + bits[pp / 32] |= 1 << (pp % 32); + mlx5_txq_release(dev, i); + } + } else { + for (i = 0; i < priv->rxqs_n; i++) { + rxq_ctrl = mlx5_rxq_get(dev, i); + if (!rxq_ctrl) + continue; + if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) { + mlx5_rxq_release(dev, i); + continue; + } + pp = rxq_ctrl->hairpin_conf.peers[0].port; + if (pp >= RTE_MAX_ETHPORTS) { + rte_errno = ERANGE; + mlx5_rxq_release(dev, i); + DRV_LOG(ERR, "port %hu queue %u peer port " + "out of range %hu", + priv->dev_data->port_id, i, pp); + return -rte_errno; + } + bits[pp / 32] |= 1 << (pp % 32); + mlx5_rxq_release(dev, i); + } + } + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if (bits[i / 32] & (1 << (i % 32))) { + if ((size_t)ret >= len) { + rte_errno = E2BIG; + return -rte_errno; + } + peer_ports[ret++] = i; + } + } return ret; } @@ -961,9 +1079,13 @@ mlx5_dev_start(struct rte_eth_dev *dev) dev->data->port_id, strerror(rte_errno)); goto error; } + /* + * Such step will be skipped if there is no hairpin TX queue configured + * with RX peer queue from the same device. + */ ret = mlx5_hairpin_auto_bind(dev); if (ret) { - DRV_LOG(ERR, "port %u hairpin binding failed: %s", + DRV_LOG(ERR, "port %u hairpin auto binding failed: %s", dev->data->port_id, strerror(rte_errno)); goto error; } @@ -1050,7 +1172,7 @@ mlx5_dev_stop(struct rte_eth_dev *dev) rte_wmb(); /* Disable datapath on secondary process. */ mlx5_mp_os_req_stop_rxtx(dev); - usleep(1000 * priv->rxqs_n); + rte_delay_us_sleep(1000 * priv->rxqs_n); DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id); mlx5_flow_stop_default(dev); /* Control flows for default traffic can be removed firstly. */ @@ -1114,7 +1236,11 @@ mlx5_traffic_enable(struct rte_eth_dev *dev) struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i); if (!txq_ctrl) continue; - if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) { + /* Only Tx implicit mode requires the default Tx flow. */ + if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN && + txq_ctrl->hairpin_conf.tx_explicit == 0 && + txq_ctrl->hairpin_conf.peers[0].port == + priv->dev_data->port_id) { ret = mlx5_ctrl_flow_source_queue(dev, i); if (ret) { mlx5_txq_release(dev, i); @@ -1190,8 +1316,12 @@ mlx5_traffic_enable(struct rte_eth_dev *dev) goto error; ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec, &ipv6_multi_mask); - if (ret) - goto error; + if (ret) { + /* Do not fail on IPv6 broadcast creation failure. */ + DRV_LOG(WARNING, + "IPv6 broadcast is not supported"); + ret = 0; + } } } /* Add MAC address flows. */