drivers: remove direct access to interrupt handle
[dpdk.git] / drivers / net / mlx4 / mlx4.c
index 3e57875..cccc71f 100644 (file)
@@ -33,8 +33,8 @@
 #include <rte_common.h>
 #include <rte_dev.h>
 #include <rte_errno.h>
-#include <rte_ethdev_driver.h>
-#include <rte_ethdev_pci.h>
+#include <ethdev_driver.h>
+#include <ethdev_pci.h>
 #include <rte_ether.h>
 #include <rte_flow.h>
 #include <rte_interrupts.h>
@@ -81,7 +81,7 @@ const char *pmd_mlx4_init_params[] = {
        NULL,
 };
 
-static void mlx4_dev_stop(struct rte_eth_dev *dev);
+static int mlx4_dev_stop(struct rte_eth_dev *dev);
 
 /**
  * Initialize shared data between primary and secondary process.
@@ -195,25 +195,26 @@ mlx4_free_verbs_buf(void *ptr, void *data __rte_unused)
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static int
+int
 mlx4_proc_priv_init(struct rte_eth_dev *dev)
 {
        struct mlx4_proc_priv *ppriv;
        size_t ppriv_size;
 
+       mlx4_proc_priv_uninit(dev);
        /*
         * UAR register table follows the process private structure. BlueFlame
         * registers for Tx queues are stored in the table.
         */
        ppriv_size = sizeof(struct mlx4_proc_priv) +
                     dev->data->nb_tx_queues * sizeof(void *);
-       ppriv = rte_malloc_socket("mlx4_proc_priv", ppriv_size,
-                                 RTE_CACHE_LINE_SIZE, dev->device->numa_node);
+       ppriv = rte_zmalloc_socket("mlx4_proc_priv", ppriv_size,
+                                  RTE_CACHE_LINE_SIZE, dev->device->numa_node);
        if (!ppriv) {
                rte_errno = ENOMEM;
                return -rte_errno;
        }
-       ppriv->uar_table_sz = ppriv_size;
+       ppriv->uar_table_sz = dev->data->nb_tx_queues;
        dev->process_private = ppriv;
        return 0;
 }
@@ -224,7 +225,7 @@ mlx4_proc_priv_init(struct rte_eth_dev *dev)
  * @param dev
  *   Pointer to Ethernet device structure.
  */
-static void
+void
 mlx4_proc_priv_uninit(struct rte_eth_dev *dev)
 {
        if (!dev->process_private)
@@ -249,9 +250,6 @@ mlx4_dev_configure(struct rte_eth_dev *dev)
        struct rte_flow_error error;
        int ret;
 
-       if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
-               dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
-
        /* Prepare internal flow rules. */
        ret = mlx4_flow_sync(priv, &error);
        if (ret) {
@@ -343,13 +341,13 @@ err:
  * @param dev
  *   Pointer to Ethernet device structure.
  */
-static void
+static int
 mlx4_dev_stop(struct rte_eth_dev *dev)
 {
        struct mlx4_priv *priv = dev->data->dev_private;
 
        if (!priv->started)
-               return;
+               return 0;
        DEBUG("%p: detaching flows from all RX queues", (void *)dev);
        priv->started = 0;
        dev->tx_pkt_burst = mlx4_tx_burst_removed;
@@ -360,6 +358,8 @@ mlx4_dev_stop(struct rte_eth_dev *dev)
        mlx4_flow_sync(priv, NULL);
        mlx4_rxq_intr_disable(priv);
        mlx4_rss_deinit(priv);
+
+       return 0;
 }
 
 /**
@@ -376,6 +376,10 @@ mlx4_dev_close(struct rte_eth_dev *dev)
        struct mlx4_priv *priv = dev->data->dev_private;
        unsigned int i;
 
+       if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+               rte_eth_dev_release_port(dev);
+               return 0;
+       }
        DEBUG("%p: closing device \"%s\"",
              (void *)dev,
              ((priv->ctx != NULL) ? priv->ctx->device->name : ""));
@@ -387,9 +391,9 @@ mlx4_dev_close(struct rte_eth_dev *dev)
        mlx4_flow_clean(priv);
        mlx4_rss_deinit(priv);
        for (i = 0; i != dev->data->nb_rx_queues; ++i)
-               mlx4_rx_queue_release(dev->data->rx_queues[i]);
+               mlx4_rx_queue_release(dev, i);
        for (i = 0; i != dev->data->nb_tx_queues; ++i)
-               mlx4_tx_queue_release(dev->data->tx_queues[i]);
+               mlx4_tx_queue_release(dev, i);
        mlx4_proc_priv_uninit(dev);
        mlx4_mr_release(dev);
        if (priv->pd != NULL) {
@@ -434,7 +438,7 @@ static const struct eth_dev_ops mlx4_dev_ops = {
        .flow_ctrl_get = mlx4_flow_ctrl_get,
        .flow_ctrl_set = mlx4_flow_ctrl_set,
        .mtu_set = mlx4_mtu_set,
-       .filter_ctrl = mlx4_filter_ctrl,
+       .flow_ops_get = mlx4_flow_ops_get,
        .rx_queue_intr_enable = mlx4_rx_intr_enable,
        .rx_queue_intr_disable = mlx4_rx_intr_disable,
        .is_removed = mlx4_is_removed,
@@ -763,6 +767,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
        struct ibv_context *attr_ctx = NULL;
        struct ibv_device_attr device_attr;
        struct ibv_device_attr_ex device_attr_ex;
+       struct rte_eth_dev *prev_dev = NULL;
        struct mlx4_conf conf = {
                .ports.present = 0,
                .mr_ext_memseg_en = 1,
@@ -877,7 +882,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                                ERROR("can not attach rte ethdev");
                                rte_errno = ENOMEM;
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        priv = eth_dev->data->dev_private;
                        if (!priv->verbs_alloc_ctx.enabled) {
@@ -886,24 +891,24 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                                      " from Verbs");
                                rte_errno = ENOTSUP;
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        eth_dev->device = &pci_dev->device;
                        eth_dev->dev_ops = &mlx4_dev_sec_ops;
                        err = mlx4_proc_priv_init(eth_dev);
                        if (err)
-                               goto error;
+                               goto err_secondary;
                        /* Receive command fd from primary process. */
                        err = mlx4_mp_req_verbs_cmd_fd(eth_dev);
                        if (err < 0) {
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        /* Remap UAR for Tx queues. */
                        err = mlx4_tx_uar_init_secondary(eth_dev, err);
                        if (err) {
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        /*
                         * Ethdev pointer is still required as input since
@@ -915,7 +920,14 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                        claim_zero(mlx4_glue->close_device(ctx));
                        rte_eth_copy_pci_info(eth_dev, pci_dev);
                        rte_eth_dev_probing_finish(eth_dev);
+                       prev_dev = eth_dev;
                        continue;
+err_secondary:
+                       claim_zero(mlx4_glue->close_device(ctx));
+                       rte_eth_dev_release_port(eth_dev);
+                       if (prev_dev)
+                               rte_eth_dev_release_port(prev_dev);
+                       break;
                }
                /* Check port status. */
                err = mlx4_glue->query_port(ctx, port, &port_attr);
@@ -1002,11 +1014,8 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                              " (error: %s)", strerror(err));
                        goto port_error;
                }
-               INFO("port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x",
-                    priv->port,
-                    mac.addr_bytes[0], mac.addr_bytes[1],
-                    mac.addr_bytes[2], mac.addr_bytes[3],
-                    mac.addr_bytes[4], mac.addr_bytes[5]);
+               INFO("port %u MAC address is " RTE_ETHER_ADDR_PRT_FMT,
+                    priv->port, RTE_ETHER_ADDR_BYTES(&mac));
                /* Register MAC address. */
                priv->mac[0] = mac;
 
@@ -1031,10 +1040,21 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                eth_dev->data->mac_addrs = priv->mac;
                eth_dev->device = &pci_dev->device;
                rte_eth_copy_pci_info(eth_dev, pci_dev);
+               eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
                /* Initialize local interrupt handle for current port. */
-               memset(&priv->intr_handle, 0, sizeof(struct rte_intr_handle));
-               priv->intr_handle.fd = -1;
-               priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
+               priv->intr_handle =
+                       rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
+               if (priv->intr_handle == NULL) {
+                       RTE_LOG(ERR, EAL, "Fail to allocate intr_handle\n");
+                       goto port_error;
+               }
+
+               if (rte_intr_fd_set(priv->intr_handle, -1))
+                       goto port_error;
+
+               if (rte_intr_type_set(priv->intr_handle, RTE_INTR_HANDLE_EXT))
+                       goto port_error;
+
                /*
                 * Override ethdev interrupt handle pointer with private
                 * handle instead of that of the parent PCI device used by
@@ -1047,7 +1067,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                 * besides setting up eth_dev->intr_handle, the rest is
                 * handled by rte_intr_rx_ctl().
                 */
-               eth_dev->intr_handle = &priv->intr_handle;
+               eth_dev->intr_handle = priv->intr_handle;
                priv->dev_data = eth_dev->data;
                eth_dev->dev_ops = &mlx4_dev_ops;
 #ifdef HAVE_IBV_MLX4_BUF_ALLOCATORS
@@ -1089,8 +1109,10 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                                 priv, mem_event_cb);
                rte_rwlock_write_unlock(&mlx4_shared_data->mem_event_rwlock);
                rte_eth_dev_probing_finish(eth_dev);
+               prev_dev = eth_dev;
                continue;
 port_error:
+               rte_intr_instance_free(priv->intr_handle);
                rte_free(priv);
                if (eth_dev != NULL)
                        eth_dev->data->dev_private = NULL;
@@ -1103,14 +1125,10 @@ port_error:
                        eth_dev->data->mac_addrs = NULL;
                        rte_eth_dev_release_port(eth_dev);
                }
+               if (prev_dev)
+                       mlx4_dev_close(prev_dev);
                break;
        }
-       /*
-        * XXX if something went wrong in the loop above, there is a resource
-        * leak (ctx, pd, priv, dpdk ethdev) but we can do nothing about it as
-        * long as the dpdk does not provide a way to deallocate a ethdev and a
-        * way to enumerate the registered ethdevs to free the previous ones.
-        */
 error:
        if (attr_ctx)
                claim_zero(mlx4_glue->close_device(attr_ctx));
@@ -1121,6 +1139,36 @@ error:
        return -err;
 }
 
+/**
+ * DPDK callback to remove a PCI device.
+ *
+ * This function removes all Ethernet devices belong to a given PCI device.
+ *
+ * @param[in] pci_dev
+ *   Pointer to the PCI device.
+ *
+ * @return
+ *   0 on success, the function cannot fail.
+ */
+static int
+mlx4_pci_remove(struct rte_pci_device *pci_dev)
+{
+       uint16_t port_id;
+       int ret = 0;
+
+       RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) {
+               /*
+                * mlx4_dev_close() is not registered to secondary process,
+                * call the close function explicitly for secondary process.
+                */
+               if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+                       ret |= mlx4_dev_close(&rte_eth_devices[port_id]);
+               else
+                       ret |= rte_eth_dev_close(port_id);
+       }
+       return ret == 0 ? 0 : -EIO;
+}
+
 static const struct rte_pci_id mlx4_pci_id_map[] = {
        {
                RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX,
@@ -1145,6 +1193,7 @@ static struct rte_pci_driver mlx4_driver = {
        },
        .id_table = mlx4_pci_id_map,
        .probe = mlx4_pci_probe,
+       .remove = mlx4_pci_remove,
        .drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_INTR_RMV,
 };
 
@@ -1279,7 +1328,7 @@ glue_error:
 #endif
 
 /* Initialize driver log type. */
-RTE_LOG_REGISTER(mlx4_logtype, pmd.net.mlx4, NOTICE)
+RTE_LOG_REGISTER_DEFAULT(mlx4_logtype, NOTICE)
 
 /**
  * Driver initialization routine.