#include <rte_cycles.h>
#include <rte_kvargs.h>
#include <rte_dev.h>
-#include <rte_ethdev.h>
#include <rte_fslmc.h>
#include <fslmc_logs.h>
static struct rte_dpaa2_driver rte_dpaa2_pmd;
static int dpaa2_dev_uninit(struct rte_eth_dev *eth_dev);
+static int dpaa2_dev_link_update(struct rte_eth_dev *dev,
+ int wait_to_complete);
static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev);
static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev);
static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return -1;
}
ret = dpni_enable_vlan_filter(dpni, CMD_PRI_LOW,
priv->token, false);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to set vlan filter ret = %d",
+ RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
ret);
}
}
}
}
- /* Check for correct configuration */
- if (eth_conf->rxmode.mq_mode != ETH_MQ_RX_RSS &&
- data->nb_rx_queues > 1) {
- PMD_INIT_LOG(ERR, "Distribution is not enabled, "
- "but Rx queues more than 1\n");
- return -1;
- }
-
if (eth_conf->rxmode.mq_mode == ETH_MQ_RX_RSS) {
- /* Return in case number of Rx queues is 1 */
- if (data->nb_rx_queues == 1)
- return 0;
ret = dpaa2_setup_flow_dist(dev,
eth_conf->rx_adv_conf.rss_conf.rss_hf);
if (ret) {
return ret;
}
}
+
+ /* update the current status */
+ dpaa2_dev_link_update(dev, 0);
+
return 0;
}
/*enabling per rx queue congestion control */
taildrop.threshold = CONG_THRESHOLD_RX_Q;
taildrop.units = DPNI_CONGESTION_UNIT_BYTES;
+ taildrop.oal = CONG_RX_OAL;
PMD_INIT_LOG(DEBUG, "Enabling Early Drop on queue = %d",
rx_queue_id);
ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token,
}
dpaa2_q->tc_index = tc_id;
- if (priv->flags & DPAA2_TX_CGR_SUPPORT) {
+ if (!(priv->flags & DPAA2_TX_CGR_OFF)) {
struct dpni_congestion_notification_cfg cong_notif_cfg;
cong_notif_cfg.units = DPNI_CONGESTION_UNIT_FRAMES;
return NULL;
}
+/**
+ * Dpaa2 link Interrupt handler
+ *
+ * @param param
+ * The address of parameter (struct rte_eth_dev *) regsitered before.
+ *
+ * @return
+ * void
+ */
+static void
+dpaa2_interrupt_handler(void *param)
+{
+ struct rte_eth_dev *dev = param;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+ int ret;
+ int irq_index = DPNI_IRQ_INDEX;
+ unsigned int status = 0, clear = 0;
+
+ PMD_INIT_FUNC_TRACE();
+
+ if (dpni == NULL) {
+ RTE_LOG(ERR, PMD, "dpni is NULL");
+ return;
+ }
+
+ ret = dpni_get_irq_status(dpni, CMD_PRI_LOW, priv->token,
+ irq_index, &status);
+ if (unlikely(ret)) {
+ RTE_LOG(ERR, PMD, "Can't get irq status (err %d)", ret);
+ clear = 0xffffffff;
+ goto out;
+ }
+
+ if (status & DPNI_IRQ_EVENT_LINK_CHANGED) {
+ clear = DPNI_IRQ_EVENT_LINK_CHANGED;
+ dpaa2_dev_link_update(dev, 0);
+ /* calling all the apps registered for link status event */
+ _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
+ NULL, NULL);
+ }
+out:
+ ret = dpni_clear_irq_status(dpni, CMD_PRI_LOW, priv->token,
+ irq_index, clear);
+ if (unlikely(ret))
+ RTE_LOG(ERR, PMD, "Can't clear irq status (err %d)", ret);
+}
+
+static int
+dpaa2_eth_setup_irqs(struct rte_eth_dev *dev, int enable)
+{
+ int err = 0;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+ int irq_index = DPNI_IRQ_INDEX;
+ unsigned int mask = DPNI_IRQ_EVENT_LINK_CHANGED;
+
+ PMD_INIT_FUNC_TRACE();
+
+ err = dpni_set_irq_mask(dpni, CMD_PRI_LOW, priv->token,
+ irq_index, mask);
+ if (err < 0) {
+ PMD_INIT_LOG(ERR, "Error: dpni_set_irq_mask():%d (%s)", err,
+ strerror(-err));
+ return err;
+ }
+
+ err = dpni_set_irq_enable(dpni, CMD_PRI_LOW, priv->token,
+ irq_index, enable);
+ if (err < 0)
+ PMD_INIT_LOG(ERR, "Error: dpni_set_irq_enable():%d (%s)", err,
+ strerror(-err));
+
+ return err;
+}
+
static int
dpaa2_dev_start(struct rte_eth_dev *dev)
{
+ struct rte_device *rdev = dev->device;
+ struct rte_dpaa2_device *dpaa2_dev;
struct rte_eth_dev_data *data = dev->data;
struct dpaa2_dev_priv *priv = data->dev_private;
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
struct dpni_queue_id qid;
struct dpaa2_queue *dpaa2_q;
int ret, i;
+ struct rte_intr_handle *intr_handle;
+
+ dpaa2_dev = container_of(rdev, struct rte_dpaa2_device, device);
+ intr_handle = &dpaa2_dev->intr_handle;
PMD_INIT_FUNC_TRACE();
return ret;
}
- /* Power up the phy. Needed to make the link go Up */
+ /* Power up the phy. Needed to make the link go UP */
dpaa2_dev_set_link_up(dev);
ret = dpni_get_qdid(dpni, CMD_PRI_LOW, priv->token,
if (priv->max_vlan_filters)
dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+ /* if the interrupts were configured on this devices*/
+ if (intr_handle && (intr_handle->fd) &&
+ (dev->data->dev_conf.intr_conf.lsc != 0)) {
+ /* Registering LSC interrupt handler */
+ rte_intr_callback_register(intr_handle,
+ dpaa2_interrupt_handler,
+ (void *)dev);
+
+ /* enable vfio intr/eventfd mapping
+ * Interrupt index 0 is required, so we can not use
+ * rte_intr_enable.
+ */
+ rte_dpaa2_intr_enable(intr_handle, DPNI_IRQ_INDEX);
+
+ /* enable dpni_irqs */
+ dpaa2_eth_setup_irqs(dev, 1);
+ }
+
return 0;
}
struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
int ret;
struct rte_eth_link link;
+ struct rte_intr_handle *intr_handle = dev->intr_handle;
PMD_INIT_FUNC_TRACE();
+ /* reset interrupt callback */
+ if (intr_handle && (intr_handle->fd) &&
+ (dev->data->dev_conf.intr_conf.lsc != 0)) {
+ /*disable dpni irqs */
+ dpaa2_eth_setup_irqs(dev, 0);
+
+ /* disable vfio intr before callback unregister */
+ rte_dpaa2_intr_disable(intr_handle, DPNI_IRQ_INDEX);
+
+ /* Unregistering LSC interrupt handler */
+ rte_intr_callback_unregister(intr_handle,
+ dpaa2_interrupt_handler,
+ (void *)dev);
+ }
+
dpaa2_dev_set_link_down(dev);
ret = dpni_disable(dpni, CMD_PRI_LOW, priv->token);
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
ret = dpni_set_unicast_promisc(dpni, CMD_PRI_LOW, priv->token, true);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to enable U promisc mode %d", ret);
+ RTE_LOG(ERR, PMD, "Unable to enable U promisc mode %d\n", ret);
ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, true);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to enable M promisc mode %d", ret);
+ RTE_LOG(ERR, PMD, "Unable to enable M promisc mode %d\n", ret);
}
static void
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
ret = dpni_set_unicast_promisc(dpni, CMD_PRI_LOW, priv->token, false);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to disable U promisc mode %d", ret);
+ RTE_LOG(ERR, PMD, "Unable to disable U promisc mode %d\n", ret);
if (dev->data->all_multicast == 0) {
ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW,
priv->token, false);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to disable M promisc mode %d",
+ RTE_LOG(ERR, PMD,
+ "Unable to disable M promisc mode %d\n",
ret);
}
}
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, true);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to enable multicast mode %d", ret);
+ RTE_LOG(ERR, PMD, "Unable to enable multicast mode %d\n", ret);
}
static void
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, false);
if (ret < 0)
- RTE_LOG(ERR, PMD, "Unable to disable multicast mode %d", ret);
+ RTE_LOG(ERR, PMD, "Unable to disable multicast mode %d\n", ret);
}
static int
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return -EINVAL;
}
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return -1;
}
ret = dpni_add_mac_addr(dpni, CMD_PRI_LOW,
priv->token, addr->addr_bytes);
if (ret)
- RTE_LOG(ERR, PMD, "error: Adding the MAC ADDR failed:"
- " err = %d", ret);
+ RTE_LOG(ERR, PMD,
+ "error: Adding the MAC ADDR failed: err = %d\n", ret);
return 0;
}
macaddr = &data->mac_addrs[index];
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
ret = dpni_remove_mac_addr(dpni, CMD_PRI_LOW,
priv->token, macaddr->addr_bytes);
if (ret)
- RTE_LOG(ERR, PMD, "error: Removing the MAC ADDR failed:"
- " err = %d", ret);
+ RTE_LOG(ERR, PMD,
+ "error: Removing the MAC ADDR failed: err = %d\n", ret);
}
static void
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
priv->token, addr->addr_bytes);
if (ret)
- RTE_LOG(ERR, PMD, "error: Setting the MAC ADDR failed %d", ret);
+ RTE_LOG(ERR, PMD,
+ "error: Setting the MAC ADDR failed %d\n", ret);
}
static
void dpaa2_dev_stats_get(struct rte_eth_dev *dev,
PMD_INIT_FUNC_TRACE();
if (!dpni) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
if (!stats) {
- RTE_LOG(ERR, PMD, "stats is NULL");
+ RTE_LOG(ERR, PMD, "stats is NULL\n");
return;
}
/*Get Counters from page_0*/
retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
- page0, &value);
+ page0, 0, &value);
if (retcode)
goto err;
/*Get Counters from page_1*/
retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
- page1, &value);
+ page1, 0, &value);
if (retcode)
goto err;
/*Get Counters from page_2*/
retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
- page2, &value);
+ page2, 0, &value);
if (retcode)
goto err;
PMD_INIT_FUNC_TRACE();
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return;
}
struct rte_eth_link link, old;
struct dpni_link_state state = {0};
- PMD_INIT_FUNC_TRACE();
-
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "error : dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return 0;
}
memset(&old, 0, sizeof(old));
ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
if (ret < 0) {
- RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d", ret);
+ RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d\n", ret);
return -1;
}
if (link.link_status)
PMD_DRV_LOG(INFO, "Port %d Link is Up\n", dev->data->port_id);
else
- PMD_DRV_LOG(INFO, "Port %d Link is Down\n", dev->data->port_id);
+ PMD_DRV_LOG(INFO, "Port %d Link is Down", dev->data->port_id);
return 0;
}
struct dpaa2_dev_priv *priv;
struct fsl_mc_io *dpni;
int en = 0;
-
- PMD_INIT_FUNC_TRACE();
+ struct dpni_link_state state = {0};
priv = dev->data->dev_private;
dpni = (struct fsl_mc_io *)priv->hw;
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "Device has not yet been configured");
+ RTE_LOG(ERR, PMD, "DPNI is NULL\n");
return ret;
}
return -EINVAL;
}
}
+ ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
+ if (ret < 0) {
+ RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d\n", ret);
+ return -1;
+ }
+
/* changing tx burst function to start enqueues */
dev->tx_pkt_burst = dpaa2_dev_tx;
- dev->data->dev_link.link_status = 1;
+ dev->data->dev_link.link_status = state.up;
- PMD_DRV_LOG(INFO, "Port %d Link UP successful", dev->data->port_id);
+ if (state.up)
+ PMD_DRV_LOG(INFO, "Port %d Link is set as UP",
+ dev->data->port_id);
+ else
+ PMD_DRV_LOG(INFO, "Port %d Link is DOWN", dev->data->port_id);
return ret;
}
dpni = (struct fsl_mc_io *)priv->hw;
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "Device has not yet been configured");
+ RTE_LOG(ERR, PMD, "Device has not yet been configured\n");
return ret;
}
dpni = (struct fsl_mc_io *)priv->hw;
if (dpni == NULL || fc_conf == NULL) {
- RTE_LOG(ERR, PMD, "device not configured");
+ RTE_LOG(ERR, PMD, "device not configured\n");
return ret;
}
ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
if (ret) {
- RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d", ret);
+ RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d\n", ret);
return ret;
}
dpni = (struct fsl_mc_io *)priv->hw;
if (dpni == NULL) {
- RTE_LOG(ERR, PMD, "dpni is NULL");
+ RTE_LOG(ERR, PMD, "dpni is NULL\n");
return ret;
}
*/
ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
if (ret) {
- RTE_LOG(ERR, PMD, "Unable to get link state (err=%d)", ret);
+ RTE_LOG(ERR, PMD, "Unable to get link state (err=%d)\n", ret);
return -1;
}
*/
cfg.options |= DPNI_LINK_OPT_PAUSE;
cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
+ break;
case RTE_FC_TX_PAUSE:
/* Enable RX flow control
* OPT_PAUSE not set;
cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
break;
default:
- RTE_LOG(ERR, PMD, "Incorrect Flow control flag (%d)",
+ RTE_LOG(ERR, PMD, "Incorrect Flow control flag (%d)\n",
fc_conf->mode);
return -1;
}
ret = dpni_set_link_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg);
if (ret)
- RTE_LOG(ERR, PMD, "Unable to set Link configuration (err=%d)",
+ RTE_LOG(ERR, PMD,
+ "Unable to set Link configuration (err=%d)\n",
ret);
/* Enable link */
return ret;
}
+static int
+dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct rte_eth_dev_data *data = dev->data;
+ struct rte_eth_conf *eth_conf = &data->dev_conf;
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ if (rss_conf->rss_hf) {
+ ret = dpaa2_setup_flow_dist(dev, rss_conf->rss_hf);
+ if (ret) {
+ PMD_INIT_LOG(ERR, "unable to set flow dist");
+ return ret;
+ }
+ } else {
+ ret = dpaa2_remove_flow_dist(dev, 0);
+ if (ret) {
+ PMD_INIT_LOG(ERR, "unable to remove flow dist");
+ return ret;
+ }
+ }
+ eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_conf->rss_hf;
+ return 0;
+}
+
+static int
+dpaa2_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct rte_eth_dev_data *data = dev->data;
+ struct rte_eth_conf *eth_conf = &data->dev_conf;
+
+ /* dpaa2 does not support rss_key, so length should be 0*/
+ rss_conf->rss_key_len = 0;
+ rss_conf->rss_hf = eth_conf->rx_adv_conf.rss_conf.rss_hf;
+ return 0;
+}
+
static struct eth_dev_ops dpaa2_ethdev_ops = {
.dev_configure = dpaa2_eth_dev_configure,
.dev_start = dpaa2_dev_start,
.mac_addr_add = dpaa2_dev_add_mac_addr,
.mac_addr_remove = dpaa2_dev_remove_mac_addr,
.mac_addr_set = dpaa2_dev_set_mac_addr,
+ .rss_hash_update = dpaa2_dev_rss_hash_update,
+ .rss_hash_conf_get = dpaa2_dev_rss_hash_conf_get,
};
static int
goto init_err;
}
- priv->num_tc = attr.num_tcs;
+ priv->num_rx_tc = attr.num_rx_tcs;
- /* Resetting the "num_rx_vqueues" to equal number of queues in first TC
+ /* Resetting the "num_rx_queues" to equal number of queues in first TC
* as only one TC is supported on Rx Side. Once Multiple TCs will be
* in use for Rx processing then this will be changed or removed.
*/
priv->nb_rx_queues = attr.num_queues;
- /* TODO:Using hard coded value for number of TX queues due to dependency
- * in MC.
- */
- priv->nb_tx_queues = 8;
+ /* Using number of TX queues as number of TX TCs */
+ priv->nb_tx_queues = attr.num_tx_tcs;
- PMD_INIT_LOG(DEBUG, "num TC - RX %d", priv->num_tc);
- PMD_INIT_LOG(DEBUG, "nb_tx_queues %d", priv->nb_tx_queues);
- PMD_INIT_LOG(DEBUG, "nb_rx_queues %d", priv->nb_rx_queues);
+ PMD_DRV_LOG(DEBUG, "RX-TC= %d, nb_rx_queues= %d, nb_tx_queues=%d",
+ priv->num_tc, priv->nb_rx_queues, priv->nb_tx_queues);
priv->hw = dpni_dev;
priv->hw_id = hw_id;
}
eth_dev->dev_ops = &dpaa2_ethdev_ops;
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx;
eth_dev->tx_pkt_burst = dpaa2_dev_tx;
PMD_INIT_FUNC_TRACE();
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
- return -EPERM;
+ return 0;
if (!dpni) {
PMD_INIT_LOG(WARNING, "Already closed or not started");
struct rte_dpaa2_device *dpaa2_dev)
{
struct rte_eth_dev *eth_dev;
- char ethdev_name[RTE_ETH_NAME_MAX_LEN];
-
int diag;
- sprintf(ethdev_name, "dpni-%d", dpaa2_dev->object_id);
-
- eth_dev = rte_eth_dev_allocate(ethdev_name);
- if (eth_dev == NULL)
- return -ENOMEM;
-
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ eth_dev = rte_eth_dev_allocate(dpaa2_dev->device.name);
+ if (!eth_dev)
+ return -ENODEV;
eth_dev->data->dev_private = rte_zmalloc(
"ethdev private structure",
sizeof(struct dpaa2_dev_priv),
rte_eth_dev_release_port(eth_dev);
return -ENOMEM;
}
+ } else {
+ eth_dev = rte_eth_dev_attach_secondary(dpaa2_dev->device.name);
+ if (!eth_dev)
+ return -ENODEV;
}
+
eth_dev->device = &dpaa2_dev->device;
eth_dev->device->driver = &dpaa2_drv->driver;
}
static struct rte_dpaa2_driver rte_dpaa2_pmd = {
- .drv_type = DPAA2_MC_DPNI_DEVID,
+ .drv_type = DPAA2_ETH,
.probe = rte_dpaa2_probe,
.remove = rte_dpaa2_remove,
};