pci: introduce library and driver
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
index eef403f..c31ea4b 100644 (file)
@@ -31,6 +31,8 @@
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define _GNU_SOURCE
+
 #include <stddef.h>
 #include <assert.h>
 #include <unistd.h>
 #include <linux/version.h>
 #include <fcntl.h>
 #include <stdalign.h>
+#include <sys/un.h>
 
 #include <rte_atomic.h>
 #include <rte_ethdev.h>
+#include <rte_bus_pci.h>
 #include <rte_mbuf.h>
 #include <rte_common.h>
 #include <rte_interrupts.h>
@@ -162,7 +166,7 @@ priv_get_ifname(const struct priv *priv, char (*ifname)[IF_NAMESIZE])
        char match[IF_NAMESIZE] = "";
 
        {
-               MKSTR(path, "%s/device/net", priv->ctx->device->ibdev_path);
+               MKSTR(path, "%s/device/net", priv->ibdev_path);
 
                dir = opendir(path);
                if (dir == NULL)
@@ -180,7 +184,7 @@ priv_get_ifname(const struct priv *priv, char (*ifname)[IF_NAMESIZE])
                        continue;
 
                MKSTR(path, "%s/device/net/%s/%s",
-                     priv->ctx->device->ibdev_path, name,
+                     priv->ibdev_path, name,
                      (dev_type ? "dev_id" : "dev_port"));
 
                file = fopen(path, "rb");
@@ -268,11 +272,11 @@ priv_sysfs_read(const struct priv *priv, const char *entry,
 
        if (priv_is_ib_cntr(entry)) {
                MKSTR(path, "%s/ports/1/hw_counters/%s",
-                     priv->ctx->device->ibdev_path, entry);
+                     priv->ibdev_path, entry);
                file = fopen(path, "rb");
        } else {
                MKSTR(path, "%s/device/net/%s/%s",
-                     priv->ctx->device->ibdev_path, ifname, entry);
+                     priv->ibdev_path, ifname, entry);
                file = fopen(path, "rb");
        }
        if (file == NULL)
@@ -315,8 +319,7 @@ priv_sysfs_write(const struct priv *priv, const char *entry,
        if (priv_get_ifname(priv, &ifname))
                return -1;
 
-       MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
-             ifname, entry);
+       MKSTR(path, "%s/device/net/%s/%s", priv->ibdev_path, ifname, entry);
 
        file = fopen(path, "wb");
        if (file == NULL)
@@ -573,8 +576,29 @@ dev_configure(struct rte_eth_dev *dev)
        unsigned int i;
        unsigned int j;
        unsigned int reta_idx_n;
+       const uint8_t use_app_rss_key =
+               !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len;
 
-       priv->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
+       if (use_app_rss_key &&
+           (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
+            rss_hash_default_key_len)) {
+               /* MLX5 RSS only support 40bytes key. */
+               return EINVAL;
+       }
+       priv->rss_conf.rss_key =
+               rte_realloc(priv->rss_conf.rss_key,
+                           rss_hash_default_key_len, 0);
+       if (!priv->rss_conf.rss_key) {
+               ERROR("cannot allocate RSS hash key memory (%u)", rxqs_n);
+               return ENOMEM;
+       }
+       memcpy(priv->rss_conf.rss_key,
+              use_app_rss_key ?
+              dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
+              rss_hash_default_key,
+              rss_hash_default_key_len);
+       priv->rss_conf.rss_key_len = rss_hash_default_key_len;
+       priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
        priv->rxqs = (void *)dev->data->rx_queues;
        priv->txqs = (void *)dev->data->tx_queues;
        if (txqs_n != priv->txqs_n) {
@@ -660,8 +684,8 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
         * Since we need one CQ per QP, the limit is the minimum number
         * between the two values.
         */
-       max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ?
-              priv->device_attr.max_qp : priv->device_attr.max_cq);
+       max = RTE_MIN(priv->device_attr.orig_attr.max_cq,
+                     priv->device_attr.orig_attr.max_qp);
        /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
        if (max >= 65535)
                max = 65535;
@@ -674,7 +698,9 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
                  DEV_RX_OFFLOAD_UDP_CKSUM |
                  DEV_RX_OFFLOAD_TCP_CKSUM) :
                 0) |
-               (priv->hw_vlan_strip ? DEV_RX_OFFLOAD_VLAN_STRIP : 0);
+               (priv->hw_vlan_strip ? DEV_RX_OFFLOAD_VLAN_STRIP : 0) |
+               DEV_RX_OFFLOAD_TIMESTAMP;
+
        if (!priv->mps)
                info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT;
        if (priv->hw_csum)
@@ -692,9 +718,7 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
                info->if_index = if_nametoindex(ifname);
        info->reta_size = priv->reta_idx_n ?
                priv->reta_idx_n : priv->ind_table_max_size;
-       info->hash_key_size = ((*priv->rss_conf) ?
-                              (*priv->rss_conf)[0]->rss_key_len :
-                              0);
+       info->hash_key_size = priv->rss_conf.rss_key_len;
        info->speed_capa = priv->link_speed_capa;
        priv_unlock(priv);
 }
@@ -1173,6 +1197,9 @@ priv_dev_status_handler(struct priv *priv)
                        event.event_type == IBV_EVENT_PORT_ERR) &&
                        (priv->dev->data->dev_conf.intr_conf.lsc == 1))
                        ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
+               else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
+                       priv->dev->data->dev_conf.intr_conf.rmv == 1)
+                       ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
                else
                        DEBUG("event type %d on port %d not handled",
                              event.event_type, event.element.port_num);
@@ -1228,6 +1255,26 @@ mlx5_dev_interrupt_handler(void *cb_arg)
        if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
                _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL,
                                              NULL);
+       if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL,
+                                             NULL);
+}
+
+/**
+ * Handle interrupts from the socket.
+ *
+ * @param cb_arg
+ *   Callback argument.
+ */
+static void
+mlx5_dev_handler_socket(void *cb_arg)
+{
+       struct rte_eth_dev *dev = cb_arg;
+       struct priv *priv = dev->data->dev_private;
+
+       priv_lock(priv);
+       priv_socket_handle(priv);
+       priv_unlock(priv);
 }
 
 /**
@@ -1241,16 +1288,20 @@ mlx5_dev_interrupt_handler(void *cb_arg)
 void
 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,
-                                    mlx5_dev_interrupt_handler,
-                                    dev);
+       if (dev->data->dev_conf.intr_conf.lsc ||
+           dev->data->dev_conf.intr_conf.rmv)
+               rte_intr_callback_unregister(&priv->intr_handle,
+                                            mlx5_dev_interrupt_handler, dev);
+       if (priv->primary_socket)
+               rte_intr_callback_unregister(&priv->intr_handle_socket,
+                                            mlx5_dev_handler_socket, dev);
        if (priv->pending_alarm)
                rte_eal_alarm_cancel(mlx5_dev_link_status_handler, dev);
        priv->pending_alarm = 0;
        priv->intr_handle.fd = 0;
        priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+       priv->intr_handle_socket.fd = 0;
+       priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
 }
 
 /**
@@ -1266,20 +1317,29 @@ priv_dev_interrupt_handler_install(struct priv *priv, struct rte_eth_dev *dev)
 {
        int rc, flags;
 
-       if (!dev->data->dev_conf.intr_conf.lsc)
-               return;
+       assert(!mlx5_is_secondary());
        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;
-       } else {
+               dev->data->dev_conf.intr_conf.rmv = 0;
+       }
+       if (dev->data->dev_conf.intr_conf.lsc ||
+           dev->data->dev_conf.intr_conf.rmv) {
                priv->intr_handle.fd = priv->ctx->async_fd;
                priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
                rte_intr_callback_register(&priv->intr_handle,
-                                          mlx5_dev_interrupt_handler,
-                                          dev);
+                                          mlx5_dev_interrupt_handler, dev);
+       }
+
+       rc = priv_socket_init(priv);
+       if (!rc && priv->primary_socket) {
+               priv->intr_handle_socket.fd = priv->primary_socket;
+               priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
+               rte_intr_callback_register(&priv->intr_handle_socket,
+                                          mlx5_dev_handler_socket, dev);
        }
 }
 
@@ -1287,7 +1347,9 @@ priv_dev_interrupt_handler_install(struct priv *priv, struct rte_eth_dev *dev)
  * Change the link state (UP / DOWN).
  *
  * @param priv
- *   Pointer to Ethernet device structure.
+ *   Pointer to private data structure.
+ * @param dev
+ *   Pointer to rte_eth_dev structure.
  * @param up
  *   Nonzero for link up, otherwise link down.
  *
@@ -1295,17 +1357,16 @@ priv_dev_interrupt_handler_install(struct priv *priv, struct rte_eth_dev *dev)
  *   0 on success, errno value on failure.
  */
 static int
-priv_set_link(struct priv *priv, int up)
+priv_dev_set_link(struct priv *priv, struct rte_eth_dev *dev, int up)
 {
-       struct rte_eth_dev *dev = priv->dev;
        int err;
 
        if (up) {
                err = priv_set_flags(priv, ~IFF_UP, IFF_UP);
                if (err)
                        return err;
-               priv_select_tx_function(priv);
-               priv_select_rx_function(priv);
+               priv_dev_select_tx_function(priv, dev);
+               priv_dev_select_rx_function(priv, dev);
        } else {
                err = priv_set_flags(priv, ~IFF_UP, ~IFF_UP);
                if (err)
@@ -1332,7 +1393,7 @@ mlx5_set_link_down(struct rte_eth_dev *dev)
        int err;
 
        priv_lock(priv);
-       err = priv_set_link(priv, 0);
+       err = priv_dev_set_link(priv, dev, 0);
        priv_unlock(priv);
        return err;
 }
@@ -1353,7 +1414,7 @@ mlx5_set_link_up(struct rte_eth_dev *dev)
        int err;
 
        priv_lock(priv);
-       err = priv_set_link(priv, 1);
+       err = priv_dev_set_link(priv, dev, 1);
        priv_unlock(priv);
        return err;
 }
@@ -1362,29 +1423,33 @@ mlx5_set_link_up(struct rte_eth_dev *dev)
  * Configure the TX function to use.
  *
  * @param priv
- *   Pointer to private structure.
+ *   Pointer to private data structure.
+ * @param dev
+ *   Pointer to rte_eth_dev structure.
  */
 void
-priv_select_tx_function(struct priv *priv)
+priv_dev_select_tx_function(struct priv *priv, struct rte_eth_dev *dev)
 {
-       priv->dev->tx_pkt_burst = mlx5_tx_burst;
+       assert(priv != NULL);
+       assert(dev != NULL);
+       dev->tx_pkt_burst = mlx5_tx_burst;
        /* Select appropriate TX function. */
        if (priv->mps == MLX5_MPW_ENHANCED) {
                if (priv_check_vec_tx_support(priv) > 0) {
                        if (priv_check_raw_vec_tx_support(priv) > 0)
-                               priv->dev->tx_pkt_burst = mlx5_tx_burst_raw_vec;
+                               dev->tx_pkt_burst = mlx5_tx_burst_raw_vec;
                        else
-                               priv->dev->tx_pkt_burst = mlx5_tx_burst_vec;
+                               dev->tx_pkt_burst = mlx5_tx_burst_vec;
                        DEBUG("selected Enhanced MPW TX vectorized function");
                } else {
-                       priv->dev->tx_pkt_burst = mlx5_tx_burst_empw;
+                       dev->tx_pkt_burst = mlx5_tx_burst_empw;
                        DEBUG("selected Enhanced MPW TX function");
                }
        } else if (priv->mps && priv->txq_inline) {
-               priv->dev->tx_pkt_burst = mlx5_tx_burst_mpw_inline;
+               dev->tx_pkt_burst = mlx5_tx_burst_mpw_inline;
                DEBUG("selected MPW inline TX function");
        } else if (priv->mps) {
-               priv->dev->tx_pkt_burst = mlx5_tx_burst_mpw;
+               dev->tx_pkt_burst = mlx5_tx_burst_mpw;
                DEBUG("selected MPW TX function");
        }
 }
@@ -1393,15 +1458,19 @@ priv_select_tx_function(struct priv *priv)
  * Configure the RX function to use.
  *
  * @param priv
- *   Pointer to private structure.
+ *   Pointer to private data structure.
+ * @param dev
+ *   Pointer to rte_eth_dev structure.
  */
 void
-priv_select_rx_function(struct priv *priv)
+priv_dev_select_rx_function(struct priv *priv, struct rte_eth_dev *dev)
 {
+       assert(priv != NULL);
+       assert(dev != NULL);
        if (priv_check_vec_rx_support(priv) > 0) {
-               priv->dev->rx_pkt_burst = mlx5_rx_burst_vec;
+               dev->rx_pkt_burst = mlx5_rx_burst_vec;
                DEBUG("selected RX vectorized function");
        } else {
-               priv->dev->rx_pkt_burst = mlx5_rx_burst;
+               dev->rx_pkt_burst = mlx5_rx_burst;
        }
 }