summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavan Nikhilesh <pbhagavatula@marvell.com>2019-11-11 18:49:07 +0530
committerFerruh Yigit <ferruh.yigit@intel.com>2019-11-11 16:15:37 +0100
commit1daa33805824e2fb6c93723604750d7b4013a355 (patch)
tree506f4fedfa2fc573782dc2ba4600a97113e1561d
parent5d308972954cbad07d469e9b708aa517787e9948 (diff)
downloaddpdk-1daa33805824e2fb6c93723604750d7b4013a355.zip
dpdk-1daa33805824e2fb6c93723604750d7b4013a355.tar.gz
dpdk-1daa33805824e2fb6c93723604750d7b4013a355.tar.xz
ethdev: validate offloads set by PMD
Some PMDs cannot work when certain offloads are enable/disabled, as a workaround PMDs auto enable/disable offloads internally and expose it through dev->data->dev_conf.rxmode.offloads. After device specific dev_configure is called compare the requested offloads to the offloads exposed by the PMD and, if the PMD failed to enable a given offload then log it and return -EINVAL from rte_eth_dev_configure, else if the PMD failed to disable a given offload log and continue with rte_eth_dev_configure. Suggested-by: Andrew Rybchenko <arybchenko@solarflare.com> Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
-rw-r--r--lib/librte_ethdev/rte_ethdev.c83
1 files changed, 76 insertions, 7 deletions
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 153d50e..bebd522 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -1137,6 +1137,57 @@ rte_eth_dev_tx_offload_name(uint64_t offload)
return name;
}
+/*
+ * Validate offloads that are requested through rte_eth_dev_configure against
+ * the offloads successfuly set by the ethernet device.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param req_offloads
+ * The offloads that have been requested through `rte_eth_dev_configure`.
+ * @param set_offloads
+ * The offloads successfuly set by the ethernet device.
+ * @param offload_type
+ * The offload type i.e. Rx/Tx string.
+ * @param offload_name
+ * The function that prints the offload name.
+ * @return
+ * - (0) if validation successful.
+ * - (-EINVAL) if requested offload has been silently disabled.
+ *
+ */
+static int
+validate_offloads(uint16_t port_id, uint64_t req_offloads,
+ uint64_t set_offloads, const char *offload_type,
+ const char *(*offload_name)(uint64_t))
+{
+ uint64_t offloads_diff = req_offloads ^ set_offloads;
+ uint64_t offload;
+ int ret = 0;
+
+ while (offloads_diff != 0) {
+ /* Check if any offload is requested but not enabled. */
+ offload = 1ULL << __builtin_ctzll(offloads_diff);
+ if (offload & req_offloads) {
+ RTE_ETHDEV_LOG(ERR,
+ "Port %u failed to enable %s offload %s\n",
+ port_id, offload_type, offload_name(offload));
+ ret = -EINVAL;
+ }
+
+ /* Chech if offload couldn't be disabled. */
+ if (offload & set_offloads) {
+ RTE_ETHDEV_LOG(INFO,
+ "Port %u failed to disable %s offload %s\n",
+ port_id, offload_type, offload_name(offload));
+ }
+
+ offloads_diff &= ~offload;
+ }
+
+ return ret;
+}
+
int
rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
const struct rte_eth_conf *dev_conf)
@@ -1343,10 +1394,8 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
if (diag != 0) {
RTE_ETHDEV_LOG(ERR, "Port%u dev_configure = %d\n",
port_id, diag);
- rte_eth_dev_rx_queue_config(dev, 0);
- rte_eth_dev_tx_queue_config(dev, 0);
ret = eth_err(port_id, diag);
- goto rollback;
+ goto reset_queues;
}
/* Initialize Rx profiling if enabled at compilation time. */
@@ -1354,14 +1403,34 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
if (diag != 0) {
RTE_ETHDEV_LOG(ERR, "Port%u __rte_eth_dev_profile_init = %d\n",
port_id, diag);
- rte_eth_dev_rx_queue_config(dev, 0);
- rte_eth_dev_tx_queue_config(dev, 0);
ret = eth_err(port_id, diag);
- goto rollback;
+ goto reset_queues;
}
- return 0;
+ /* Validate Rx offloads. */
+ diag = validate_offloads(port_id,
+ dev_conf->rxmode.offloads,
+ dev->data->dev_conf.rxmode.offloads, "Rx",
+ rte_eth_dev_rx_offload_name);
+ if (diag != 0) {
+ ret = diag;
+ goto reset_queues;
+ }
+
+ /* Validate Tx offloads. */
+ diag = validate_offloads(port_id,
+ dev_conf->txmode.offloads,
+ dev->data->dev_conf.txmode.offloads, "Tx",
+ rte_eth_dev_tx_offload_name);
+ if (diag != 0) {
+ ret = diag;
+ goto reset_queues;
+ }
+ return 0;
+reset_queues:
+ rte_eth_dev_rx_queue_config(dev, 0);
+ rte_eth_dev_tx_queue_config(dev, 0);
rollback:
memcpy(&dev->data->dev_conf, &orig_conf, sizeof(dev->data->dev_conf));