Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / main.c
index fa1ca28e8b5a38a6efede6ed843fb1a55a6e5413..1545a944c309bf3205ad49fc1de90bd21c3eaacd 100644 (file)
 #include <linux/delay.h>
 #include <linux/mlx5/mlx5_ifc.h>
 #include "mlx5_core.h"
+#include "fs_core.h"
+#ifdef CONFIG_MLX5_CORE_EN
+#include "eswitch.h"
+#endif
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox Connect-IB, ConnectX-4 core driver");
@@ -501,6 +505,9 @@ static int set_hca_ctrl(struct mlx5_core_dev *dev)
        struct mlx5_reg_host_endianess he_out;
        int err;
 
+       if (!mlx5_core_is_pf(dev))
+               return 0;
+
        memset(&he_in, 0, sizeof(he_in));
        he_in.he = MLX5_SET_HOST_ENDIANNESS;
        err = mlx5_core_access_reg(dev, &he_in,  sizeof(he_in),
@@ -509,42 +516,52 @@ static int set_hca_ctrl(struct mlx5_core_dev *dev)
        return err;
 }
 
-static int mlx5_core_enable_hca(struct mlx5_core_dev *dev)
+int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id)
 {
+       u32 out[MLX5_ST_SZ_DW(enable_hca_out)];
+       u32 in[MLX5_ST_SZ_DW(enable_hca_in)];
        int err;
-       struct mlx5_enable_hca_mbox_in in;
-       struct mlx5_enable_hca_mbox_out out;
 
-       memset(&in, 0, sizeof(in));
-       memset(&out, 0, sizeof(out));
-       in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ENABLE_HCA);
+       memset(in, 0, sizeof(in));
+       MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA);
+       MLX5_SET(enable_hca_in, in, function_id, func_id);
+       memset(out, 0, sizeof(out));
+
        err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
        if (err)
                return err;
 
-       if (out.hdr.status)
-               return mlx5_cmd_status_to_err(&out.hdr);
-
-       return 0;
+       return mlx5_cmd_status_to_err_v2(out);
 }
 
-static int mlx5_core_disable_hca(struct mlx5_core_dev *dev)
+int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id)
 {
+       u32 out[MLX5_ST_SZ_DW(disable_hca_out)];
+       u32 in[MLX5_ST_SZ_DW(disable_hca_in)];
        int err;
-       struct mlx5_disable_hca_mbox_in in;
-       struct mlx5_disable_hca_mbox_out out;
 
-       memset(&in, 0, sizeof(in));
-       memset(&out, 0, sizeof(out));
-       in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DISABLE_HCA);
-       err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
+       memset(in, 0, sizeof(in));
+       MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA);
+       MLX5_SET(disable_hca_in, in, function_id, func_id);
+       memset(out, 0, sizeof(out));
+       err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
        if (err)
                return err;
 
-       if (out.hdr.status)
-               return mlx5_cmd_status_to_err(&out.hdr);
+       return mlx5_cmd_status_to_err_v2(out);
+}
 
-       return 0;
+cycle_t mlx5_read_internal_timer(struct mlx5_core_dev *dev)
+{
+       u32 timer_h, timer_h1, timer_l;
+
+       timer_h = ioread32be(&dev->iseg->internal_timer_h);
+       timer_l = ioread32be(&dev->iseg->internal_timer_l);
+       timer_h1 = ioread32be(&dev->iseg->internal_timer_h);
+       if (timer_h != timer_h1) /* wrap around */
+               timer_l = ioread32be(&dev->iseg->internal_timer_l);
+
+       return (cycle_t)timer_l | (cycle_t)timer_h1 << 32;
 }
 
 static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
@@ -615,7 +632,8 @@ static void mlx5_irq_clear_affinity_hints(struct mlx5_core_dev *mdev)
                mlx5_irq_clear_affinity_hint(mdev, i);
 }
 
-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn)
+int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
+                   unsigned int *irqn)
 {
        struct mlx5_eq_table *table = &dev->priv.eq_table;
        struct mlx5_eq *eq, *n;
@@ -987,7 +1005,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
 
        mlx5_pagealloc_init(dev);
 
-       err = mlx5_core_enable_hca(dev);
+       err = mlx5_core_enable_hca(dev, 0);
        if (err) {
                dev_err(&pdev->dev, "enable hca failed\n");
                goto err_pagealloc_cleanup;
@@ -1101,6 +1119,25 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
        mlx5_init_srq_table(dev);
        mlx5_init_mr_table(dev);
 
+       err = mlx5_init_fs(dev);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to init flow steering\n");
+               goto err_fs;
+       }
+#ifdef CONFIG_MLX5_CORE_EN
+       err = mlx5_eswitch_init(dev);
+       if (err) {
+               dev_err(&pdev->dev, "eswitch init failed %d\n", err);
+               goto err_reg_dev;
+       }
+#endif
+
+       err = mlx5_sriov_init(dev);
+       if (err) {
+               dev_err(&pdev->dev, "sriov init failed %d\n", err);
+               goto err_sriov;
+       }
+
        err = mlx5_register_device(dev);
        if (err) {
                dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
@@ -1117,7 +1154,16 @@ out:
 
        return 0;
 
+err_sriov:
+       if (mlx5_sriov_cleanup(dev))
+               dev_err(&dev->pdev->dev, "sriov cleanup failed\n");
+
+#ifdef CONFIG_MLX5_CORE_EN
+       mlx5_eswitch_cleanup(dev->priv.eswitch);
+#endif
 err_reg_dev:
+       mlx5_cleanup_fs(dev);
+err_fs:
        mlx5_cleanup_mr_table(dev);
        mlx5_cleanup_srq_table(dev);
        mlx5_cleanup_qp_table(dev);
@@ -1155,7 +1201,7 @@ reclaim_boot_pages:
        mlx5_reclaim_startup_pages(dev);
 
 err_disable_hca:
-       mlx5_core_disable_hca(dev);
+       mlx5_core_disable_hca(dev, 0);
 
 err_pagealloc_cleanup:
        mlx5_pagealloc_cleanup(dev);
@@ -1172,6 +1218,13 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
 {
        int err = 0;
 
+       err = mlx5_sriov_cleanup(dev);
+       if (err) {
+               dev_warn(&dev->pdev->dev, "%s: sriov cleanup failed - abort\n",
+                        __func__);
+               return err;
+       }
+
        mutex_lock(&dev->intf_state_mutex);
        if (dev->interface_state == MLX5_INTERFACE_STATE_DOWN) {
                dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
@@ -1179,6 +1232,11 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
                goto out;
        }
        mlx5_unregister_device(dev);
+#ifdef CONFIG_MLX5_CORE_EN
+       mlx5_eswitch_cleanup(dev->priv.eswitch);
+#endif
+
+       mlx5_cleanup_fs(dev);
        mlx5_cleanup_mr_table(dev);
        mlx5_cleanup_srq_table(dev);
        mlx5_cleanup_qp_table(dev);
@@ -1198,7 +1256,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
        }
        mlx5_pagealloc_stop(dev);
        mlx5_reclaim_startup_pages(dev);
-       mlx5_core_disable_hca(dev);
+       mlx5_core_disable_hca(dev, 0);
        mlx5_pagealloc_cleanup(dev);
        mlx5_cmd_cleanup(dev);
 
@@ -1244,6 +1302,7 @@ static int init_one(struct pci_dev *pdev,
                return -ENOMEM;
        }
        priv = &dev->priv;
+       priv->pci_dev_data = id->driver_data;
 
        pci_set_drvdata(pdev, dev);
 
@@ -1414,12 +1473,12 @@ static const struct pci_error_handlers mlx5_err_handler = {
 };
 
 static const struct pci_device_id mlx5_core_pci_table[] = {
-       { PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */
-       { PCI_VDEVICE(MELLANOX, 0x1012) }, /* Connect-IB VF */
-       { PCI_VDEVICE(MELLANOX, 0x1013) }, /* ConnectX-4 */
-       { PCI_VDEVICE(MELLANOX, 0x1014) }, /* ConnectX-4 VF */
-       { PCI_VDEVICE(MELLANOX, 0x1015) }, /* ConnectX-4LX */
-       { PCI_VDEVICE(MELLANOX, 0x1016) }, /* ConnectX-4LX VF */
+       { PCI_VDEVICE(MELLANOX, 0x1011) },                      /* Connect-IB */
+       { PCI_VDEVICE(MELLANOX, 0x1012), MLX5_PCI_DEV_IS_VF},   /* Connect-IB VF */
+       { PCI_VDEVICE(MELLANOX, 0x1013) },                      /* ConnectX-4 */
+       { PCI_VDEVICE(MELLANOX, 0x1014), MLX5_PCI_DEV_IS_VF},   /* ConnectX-4 VF */
+       { PCI_VDEVICE(MELLANOX, 0x1015) },                      /* ConnectX-4LX */
+       { PCI_VDEVICE(MELLANOX, 0x1016), MLX5_PCI_DEV_IS_VF},   /* ConnectX-4LX VF */
        { 0, }
 };
 
@@ -1430,7 +1489,8 @@ static struct pci_driver mlx5_core_driver = {
        .id_table       = mlx5_core_pci_table,
        .probe          = init_one,
        .remove         = remove_one,
-       .err_handler    = &mlx5_err_handler
+       .err_handler    = &mlx5_err_handler,
+       .sriov_configure   = mlx5_core_sriov_configure,
 };
 
 static int __init init(void)