pci: remove eal prefix
[dpdk.git] / drivers / net / mlx4 / mlx4.c
index ff903e6..1e37dd9 100644 (file)
@@ -60,6 +60,7 @@
 
 #include <rte_ether.h>
 #include <rte_ethdev.h>
+#include <rte_ethdev_pci.h>
 #include <rte_dev.h>
 #include <rte_mbuf.h>
 #include <rte_errno.h>
@@ -3169,6 +3170,8 @@ mlx4_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
                        /* Increase out of memory counters. */
                        ++rxq->stats.rx_nombuf;
                        ++rxq->priv->dev->data->rx_mbuf_alloc_failed;
+                       /* Add SGE to array for repost. */
+                       sges[i] = elt->sge;
                        goto repost;
                }
 
@@ -3929,9 +3932,15 @@ mlx4_rx_queue_release(void *dpdk_rxq)
        priv_unlock(priv);
 }
 
-static void
+static int
 priv_dev_interrupt_handler_install(struct priv *, struct rte_eth_dev *);
 
+static int
+priv_dev_removal_interrupt_handler_install(struct priv *, struct rte_eth_dev *);
+
+static int
+priv_dev_link_interrupt_handler_install(struct priv *, struct rte_eth_dev *);
+
 /**
  * DPDK callback to start the device.
  *
@@ -3984,7 +3993,18 @@ mlx4_dev_start(struct rte_eth_dev *dev)
                     (void *)dev, strerror(ret));
                goto err;
        } while ((--r) && ((rxq = (*priv->rxqs)[++i]), i));
-       priv_dev_interrupt_handler_install(priv, dev);
+       ret = priv_dev_link_interrupt_handler_install(priv, dev);
+       if (ret) {
+               ERROR("%p: LSC handler install failed",
+                    (void *)dev);
+               goto err;
+       }
+       ret = priv_dev_removal_interrupt_handler_install(priv, dev);
+       if (ret) {
+               ERROR("%p: RMV handler install failed",
+                    (void *)dev);
+               goto err;
+       }
        ret = mlx4_priv_flow_start(priv);
        if (ret) {
                ERROR("%p: flow start failed: %s",
@@ -4103,9 +4123,16 @@ removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
        return 0;
 }
 
-static void
+static int
 priv_dev_interrupt_handler_uninstall(struct priv *, struct rte_eth_dev *);
 
+static int
+priv_dev_removal_interrupt_handler_uninstall(struct priv *,
+                                            struct rte_eth_dev *);
+
+static int
+priv_dev_link_interrupt_handler_uninstall(struct priv *, struct rte_eth_dev *);
+
 /**
  * DPDK callback to close the device.
  *
@@ -4168,7 +4195,8 @@ mlx4_dev_close(struct rte_eth_dev *dev)
                claim_zero(ibv_close_device(priv->ctx));
        } else
                assert(priv->ctx == NULL);
-       priv_dev_interrupt_handler_uninstall(priv, dev);
+       priv_dev_removal_interrupt_handler_uninstall(priv, dev);
+       priv_dev_link_interrupt_handler_uninstall(priv, dev);
        priv_unlock(priv);
        memset(priv, 0, sizeof(*priv));
 }
@@ -4728,6 +4756,10 @@ mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete)
        return -1;
 }
 
+static int
+mlx4_ibv_device_to_pci_addr(const struct ibv_device *device,
+                           struct rte_pci_addr *pci_addr);
+
 /**
  * DPDK callback to change the MTU.
  *
@@ -5251,35 +5283,44 @@ mlx4_getenv_int(const char *name)
 static void
 mlx4_dev_link_status_handler(void *);
 static void
-mlx4_dev_interrupt_handler(struct rte_intr_handle *, void *);
+mlx4_dev_interrupt_handler(void *);
 
 /**
- * Link status handler.
+ * Link/device status handler.
  *
  * @param priv
  *   Pointer to private structure.
  * @param dev
  *   Pointer to the rte_eth_dev structure.
+ * @param events
+ *   Pointer to event flags holder.
  *
  * @return
- *   Nonzero if the callback process can be called immediately.
+ *   Number of events
  */
 static int
-priv_dev_link_status_handler(struct priv *priv, struct rte_eth_dev *dev)
+priv_dev_status_handler(struct priv *priv, struct rte_eth_dev *dev,
+                       uint32_t *events)
 {
        struct ibv_async_event event;
        int port_change = 0;
        int ret = 0;
 
+       *events = 0;
        /* Read all message and acknowledge them. */
        for (;;) {
                if (ibv_get_async_event(priv->ctx, &event))
                        break;
-
-               if (event.event_type == IBV_EVENT_PORT_ACTIVE ||
-                   event.event_type == IBV_EVENT_PORT_ERR)
+               if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
+                    event.event_type == IBV_EVENT_PORT_ERR) &&
+                   (priv->intr_conf.lsc == 1)) {
                        port_change = 1;
-               else
+                       ret++;
+               } else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
+                          priv->intr_conf.rmv == 1) {
+                       *events |= (1 << RTE_ETH_EVENT_INTR_RMV);
+                       ret++;
+               } else
                        DEBUG("event type %d on port %d not handled",
                              event.event_type, event.element.port_num);
                ibv_ack_async_event(&event);
@@ -5297,8 +5338,9 @@ priv_dev_link_status_handler(struct priv *priv, struct rte_eth_dev *dev)
                        rte_eal_alarm_set(MLX4_ALARM_TIMEOUT_US,
                                          mlx4_dev_link_status_handler,
                                          dev);
-               } else
-                       ret = 1;
+               } else {
+                       *events |= (1 << RTE_ETH_EVENT_INTR_LSC);
+               }
        }
        return ret;
 }
@@ -5314,13 +5356,14 @@ mlx4_dev_link_status_handler(void *arg)
 {
        struct rte_eth_dev *dev = arg;
        struct priv *priv = dev->data->dev_private;
+       uint32_t events;
        int ret;
 
        priv_lock(priv);
        assert(priv->pending_alarm == 1);
-       ret = priv_dev_link_status_handler(priv, dev);
+       ret = priv_dev_status_handler(priv, dev, &events);
        priv_unlock(priv);
-       if (ret)
+       if (ret > 0 && events & (1 << RTE_ETH_EVENT_INTR_LSC))
                _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
 }
 
@@ -5333,18 +5376,31 @@ mlx4_dev_link_status_handler(void *arg)
  *   Callback argument.
  */
 static void
-mlx4_dev_interrupt_handler(struct rte_intr_handle *intr_handle, void *cb_arg)
+mlx4_dev_interrupt_handler(void *cb_arg)
 {
        struct rte_eth_dev *dev = cb_arg;
        struct priv *priv = dev->data->dev_private;
        int ret;
+       uint32_t ev;
+       int i;
 
-       (void)intr_handle;
        priv_lock(priv);
-       ret = priv_dev_link_status_handler(priv, dev);
+       ret = priv_dev_status_handler(priv, dev, &ev);
        priv_unlock(priv);
-       if (ret)
-               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+       if (ret > 0) {
+               for (i = RTE_ETH_EVENT_UNKNOWN;
+                    i < RTE_ETH_EVENT_MAX;
+                    i++) {
+                       if (ev & (1 << i)) {
+                               ev &= ~(1 << i);
+                               _rte_eth_dev_callback_process(dev, i, NULL);
+                               ret--;
+                       }
+               }
+               if (ret)
+                       WARN("%d event%s not processed", ret,
+                            (ret > 1 ? "s were" : " was"));
+       }
 }
 
 /**
@@ -5354,20 +5410,30 @@ mlx4_dev_interrupt_handler(struct rte_intr_handle *intr_handle, void *cb_arg)
  *   Pointer to private structure.
  * @param dev
  *   Pointer to the rte_eth_dev structure.
+ * @return
+ *   0 on success, negative errno value on failure.
  */
-static void
+static int
 priv_dev_interrupt_handler_uninstall(struct priv *priv, struct rte_eth_dev *dev)
 {
-       if (!dev->data->dev_conf.intr_conf.lsc)
-               return;
-       rte_intr_callback_unregister(&priv->intr_handle,
-                                    mlx4_dev_interrupt_handler,
-                                    dev);
-       if (priv->pending_alarm)
-               rte_eal_alarm_cancel(mlx4_dev_link_status_handler, dev);
-       priv->pending_alarm = 0;
+       int ret;
+
+       if (priv->intr_conf.lsc ||
+           priv->intr_conf.rmv)
+               return 0;
+       ret = rte_intr_callback_unregister(&priv->intr_handle,
+                                          mlx4_dev_interrupt_handler,
+                                          dev);
+       if (ret < 0) {
+               ERROR("rte_intr_callback_unregister failed with %d"
+                     "%s%s%s", ret,
+                     (errno ? " (errno: " : ""),
+                     (errno ? strerror(errno) : ""),
+                     (errno ? ")" : ""));
+       }
        priv->intr_handle.fd = 0;
        priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+       return ret;
 }
 
 /**
@@ -5377,27 +5443,148 @@ priv_dev_interrupt_handler_uninstall(struct priv *priv, struct rte_eth_dev *dev)
  *   Pointer to private structure.
  * @param dev
  *   Pointer to the rte_eth_dev structure.
+ * @return
+ *   0 on success, negative errno value on failure.
  */
-static void
-priv_dev_interrupt_handler_install(struct priv *priv, struct rte_eth_dev *dev)
+static int
+priv_dev_interrupt_handler_install(struct priv *priv,
+                                  struct rte_eth_dev *dev)
 {
-       int rc, flags;
+       int flags;
+       int rc;
 
-       if (!dev->data->dev_conf.intr_conf.lsc)
-               return;
+       /* Check whether the interrupt handler has already been installed
+        * for either type of interrupt
+        */
+       if (priv->intr_conf.lsc &&
+           priv->intr_conf.rmv &&
+           priv->intr_handle.fd)
+               return 0;
        assert(priv->ctx->async_fd > 0);
        flags = fcntl(priv->ctx->async_fd, F_GETFL);
        rc = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
        if (rc < 0) {
                INFO("failed to change file descriptor async event queue");
                dev->data->dev_conf.intr_conf.lsc = 0;
+               dev->data->dev_conf.intr_conf.rmv = 0;
+               return -errno;
        } else {
                priv->intr_handle.fd = priv->ctx->async_fd;
                priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
-               rte_intr_callback_register(&priv->intr_handle,
-                                          mlx4_dev_interrupt_handler,
-                                          dev);
+               rc = rte_intr_callback_register(&priv->intr_handle,
+                                                mlx4_dev_interrupt_handler,
+                                                dev);
+               if (rc) {
+                       ERROR("rte_intr_callback_register failed "
+                             " (errno: %s)", strerror(errno));
+                       return rc;
+               }
+       }
+       return 0;
+}
+
+/**
+ * Uninstall interrupt handler.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param dev
+ *   Pointer to the rte_eth_dev structure.
+ * @return
+ *   0 on success, negative value on error.
+ */
+static int
+priv_dev_removal_interrupt_handler_uninstall(struct priv *priv,
+                                           struct rte_eth_dev *dev)
+{
+       if (dev->data->dev_conf.intr_conf.rmv) {
+               priv->intr_conf.rmv = 0;
+               return priv_dev_interrupt_handler_uninstall(priv, dev);
+       }
+       return 0;
+}
+
+/**
+ * Uninstall interrupt handler.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param dev
+ *   Pointer to the rte_eth_dev structure.
+ * @return
+ *   0 on success, negative value on error,
+ */
+static int
+priv_dev_link_interrupt_handler_uninstall(struct priv *priv,
+                                         struct rte_eth_dev *dev)
+{
+       int ret = 0;
+
+       if (dev->data->dev_conf.intr_conf.lsc) {
+               priv->intr_conf.lsc = 0;
+               ret = priv_dev_interrupt_handler_uninstall(priv, dev);
+               if (ret)
+                       return ret;
+       }
+       if (priv->pending_alarm)
+               if (rte_eal_alarm_cancel(mlx4_dev_link_status_handler,
+                                        dev)) {
+                       ERROR("rte_eal_alarm_cancel failed "
+                             " (errno: %s)", strerror(rte_errno));
+                       return -rte_errno;
+               }
+       priv->pending_alarm = 0;
+       return 0;
+}
+
+/**
+ * Install link interrupt handler.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param dev
+ *   Pointer to the rte_eth_dev structure.
+ * @return
+ *   0 on success, negative value on error.
+ */
+static int
+priv_dev_link_interrupt_handler_install(struct priv *priv,
+                                       struct rte_eth_dev *dev)
+{
+       int ret;
+
+       if (dev->data->dev_conf.intr_conf.lsc) {
+               ret = priv_dev_interrupt_handler_install(priv, dev);
+               if (ret)
+                       return ret;
+               priv->intr_conf.lsc = 1;
+       }
+       return 0;
+}
+
+/**
+ * Install removal interrupt handler.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param dev
+ *   Pointer to the rte_eth_dev structure.
+ * @return
+ *   0 on success, negative value on error.
+ */
+static int
+priv_dev_removal_interrupt_handler_install(struct priv *priv,
+                                          struct rte_eth_dev *dev)
+{
+       int ret;
+
+       if (dev->data->dev_conf.intr_conf.rmv) {
+               ret = priv_dev_interrupt_handler_install(priv, dev);
+               if (ret)
+                       return ret;
+               priv->intr_conf.rmv = 1;
        }
+       return 0;
 }
 
 /**
@@ -5478,7 +5665,7 @@ free_kvlist:
        return ret;
 }
 
-static struct eth_driver mlx4_driver;
+static struct rte_pci_driver mlx4_driver;
 
 /**
  * DPDK callback to register a PCI device.
@@ -5510,7 +5697,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
        int i;
 
        (void)pci_drv;
-       assert(pci_drv == &mlx4_driver.pci_drv);
+       assert(pci_drv == &mlx4_driver);
        /* Get mlx4_dev[] index. */
        idx = mlx4_dev_idx(&pci_dev->addr);
        if (idx == -1) {
@@ -5809,7 +5996,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 
                rte_eth_copy_pci_info(eth_dev, pci_dev);
 
-               eth_dev->driver = &mlx4_driver;
+               eth_dev->device->driver = &mlx4_driver.driver;
 
                priv->dev = eth_dev;
                eth_dev->dev_ops = &mlx4_dev_ops;
@@ -5873,16 +6060,14 @@ static const struct rte_pci_id mlx4_pci_id_map[] = {
        }
 };
 
-static struct eth_driver mlx4_driver = {
-       .pci_drv = {
-               .driver = {
-                       .name = MLX4_DRIVER_NAME
-               },
-               .id_table = mlx4_pci_id_map,
-               .probe = mlx4_pci_probe,
-               .drv_flags = RTE_PCI_DRV_INTR_LSC,
+static struct rte_pci_driver mlx4_driver = {
+       .driver = {
+               .name = MLX4_DRIVER_NAME
        },
-       .dev_private_size = sizeof(struct priv)
+       .id_table = mlx4_pci_id_map,
+       .probe = mlx4_pci_probe,
+       .drv_flags = RTE_PCI_DRV_INTR_LSC |
+                    RTE_PCI_DRV_INTR_RMV,
 };
 
 /**
@@ -5901,7 +6086,7 @@ rte_mlx4_pmd_init(void)
         */
        setenv("RDMAV_HUGEPAGES_SAFE", "1", 1);
        ibv_fork_init();
-       rte_eal_pci_register(&mlx4_driver.pci_drv);
+       rte_pci_register(&mlx4_driver);
 }
 
 RTE_PMD_EXPORT_NAME(net_mlx4, __COUNTER__);