net/mlx4_core: Implement pci_resume callback
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx4 / main.c
index f8674ae..5d45aa3 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/io-mapping.h>
 #include <linux/delay.h>
 #include <linux/kmod.h>
+#include <net/devlink.h>
 
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/doorbell.h>
@@ -104,6 +105,11 @@ module_param(enable_64b_cqe_eqe, bool, 0444);
 MODULE_PARM_DESC(enable_64b_cqe_eqe,
                 "Enable 64 byte CQEs/EQEs when the FW supports this (default: True)");
 
+static bool enable_4k_uar;
+module_param(enable_4k_uar, bool, 0444);
+MODULE_PARM_DESC(enable_4k_uar,
+                "Enable using 4K UAR. Should not be enabled if have VFs which do not support 4K UARs (default: false)");
+
 #define PF_CONTEXT_BEHAVIOUR_MASK      (MLX4_FUNC_CAP_64B_EQE_CQE | \
                                         MLX4_FUNC_CAP_EQE_CQE_STRIDE | \
                                         MLX4_FUNC_CAP_DMFS_A0_STATIC)
@@ -422,7 +428,11 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                /* Virtual PCI function needs to determine UAR page size from
                 * firmware. Only master PCI function can set the uar page size
                 */
-               dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT;
+               if (enable_4k_uar)
+                       dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT;
+               else
+                       dev->uar_page_shift = PAGE_SHIFT;
+
                mlx4_set_num_reserved_uars(dev, dev_cap);
        }
 
@@ -1081,36 +1091,20 @@ static ssize_t show_port_type(struct device *dev,
        return strlen(buf);
 }
 
-static ssize_t set_port_type(struct device *dev,
-                            struct device_attribute *attr,
-                            const char *buf, size_t count)
+static int __set_port_type(struct mlx4_port_info *info,
+                          enum mlx4_port_type port_type)
 {
-       struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
-                                                  port_attr);
        struct mlx4_dev *mdev = info->dev;
        struct mlx4_priv *priv = mlx4_priv(mdev);
        enum mlx4_port_type types[MLX4_MAX_PORTS];
        enum mlx4_port_type new_types[MLX4_MAX_PORTS];
-       static DEFINE_MUTEX(set_port_type_mutex);
        int i;
        int err = 0;
 
-       mutex_lock(&set_port_type_mutex);
-
-       if (!strcmp(buf, "ib\n"))
-               info->tmp_type = MLX4_PORT_TYPE_IB;
-       else if (!strcmp(buf, "eth\n"))
-               info->tmp_type = MLX4_PORT_TYPE_ETH;
-       else if (!strcmp(buf, "auto\n"))
-               info->tmp_type = MLX4_PORT_TYPE_AUTO;
-       else {
-               mlx4_err(mdev, "%s is not supported port type\n", buf);
-               err = -EINVAL;
-               goto err_out;
-       }
-
        mlx4_stop_sense(mdev);
        mutex_lock(&priv->port_mutex);
+       info->tmp_type = port_type;
+
        /* Possible type is always the one that was delivered */
        mdev->caps.possible_type[info->port] = info->tmp_type;
 
@@ -1152,6 +1146,37 @@ static ssize_t set_port_type(struct device *dev,
 out:
        mlx4_start_sense(mdev);
        mutex_unlock(&priv->port_mutex);
+
+       return err;
+}
+
+static ssize_t set_port_type(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
+                                                  port_attr);
+       struct mlx4_dev *mdev = info->dev;
+       enum mlx4_port_type port_type;
+       static DEFINE_MUTEX(set_port_type_mutex);
+       int err;
+
+       mutex_lock(&set_port_type_mutex);
+
+       if (!strcmp(buf, "ib\n")) {
+               port_type = MLX4_PORT_TYPE_IB;
+       } else if (!strcmp(buf, "eth\n")) {
+               port_type = MLX4_PORT_TYPE_ETH;
+       } else if (!strcmp(buf, "auto\n")) {
+               port_type = MLX4_PORT_TYPE_AUTO;
+       } else {
+               mlx4_err(mdev, "%s is not supported port type\n", buf);
+               err = -EINVAL;
+               goto err_out;
+       }
+
+       err = __set_port_type(info, port_type);
+
 err_out:
        mutex_unlock(&set_port_type_mutex);
 
@@ -2217,11 +2242,14 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 
                dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1;
 
-               /* Always set UAR page size 4KB, set log_uar_sz accordingly */
-               init_hca.log_uar_sz = ilog2(dev->caps.num_uars) +
-                                     PAGE_SHIFT -
-                                     DEFAULT_UAR_PAGE_SHIFT;
-               init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12;
+               if (enable_4k_uar) {
+                       init_hca.log_uar_sz = ilog2(dev->caps.num_uars) +
+                                                   PAGE_SHIFT - DEFAULT_UAR_PAGE_SHIFT;
+                       init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12;
+               } else {
+                       init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
+                       init_hca.uar_page_sz = PAGE_SHIFT - 12;
+               }
 
                init_hca.mw_enabled = 0;
                if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW ||
@@ -2889,8 +2917,13 @@ no_msi:
 
 static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
 {
+       struct devlink *devlink = priv_to_devlink(mlx4_priv(dev));
        struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
-       int err = 0;
+       int err;
+
+       err = devlink_port_register(devlink, &info->devlink_port, port);
+       if (err)
+               return err;
 
        info->dev = dev;
        info->port = port;
@@ -2915,6 +2948,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
        err = device_create_file(&dev->persist->pdev->dev, &info->port_attr);
        if (err) {
                mlx4_err(dev, "Failed to create file for port %d\n", port);
+               devlink_port_unregister(&info->devlink_port);
                info->port = -1;
        }
 
@@ -3686,23 +3720,54 @@ err_disable_pdev:
        return err;
 }
 
+static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
+                                     enum devlink_port_type port_type)
+{
+       struct mlx4_port_info *info = container_of(devlink_port,
+                                                  struct mlx4_port_info,
+                                                  devlink_port);
+       enum mlx4_port_type mlx4_port_type;
+
+       switch (port_type) {
+       case DEVLINK_PORT_TYPE_AUTO:
+               mlx4_port_type = MLX4_PORT_TYPE_AUTO;
+               break;
+       case DEVLINK_PORT_TYPE_ETH:
+               mlx4_port_type = MLX4_PORT_TYPE_ETH;
+               break;
+       case DEVLINK_PORT_TYPE_IB:
+               mlx4_port_type = MLX4_PORT_TYPE_IB;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return __set_port_type(info, mlx4_port_type);
+}
+
+static const struct devlink_ops mlx4_devlink_ops = {
+       .port_type_set  = mlx4_devlink_port_type_set,
+};
+
 static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+       struct devlink *devlink;
        struct mlx4_priv *priv;
        struct mlx4_dev *dev;
        int ret;
 
        printk_once(KERN_INFO "%s", mlx4_version);
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
+       devlink = devlink_alloc(&mlx4_devlink_ops, sizeof(*priv));
+       if (!devlink)
                return -ENOMEM;
+       priv = devlink_priv(devlink);
 
        dev       = &priv->dev;
        dev->persist = kzalloc(sizeof(*dev->persist), GFP_KERNEL);
        if (!dev->persist) {
-               kfree(priv);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_devlink_free;
        }
        dev->persist->pdev = pdev;
        dev->persist->dev = dev;
@@ -3711,14 +3776,23 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        mutex_init(&dev->persist->device_state_mutex);
        mutex_init(&dev->persist->interface_state_mutex);
 
+       ret = devlink_register(devlink, &pdev->dev);
+       if (ret)
+               goto err_persist_free;
+
        ret =  __mlx4_init_one(pdev, id->driver_data, priv);
-       if (ret) {
-               kfree(dev->persist);
-               kfree(priv);
-       } else {
-               pci_save_state(pdev);
-       }
+       if (ret)
+               goto err_devlink_unregister;
+
+       pci_save_state(pdev);
+       return 0;
 
+err_devlink_unregister:
+       devlink_unregister(devlink);
+err_persist_free:
+       kfree(dev->persist);
+err_devlink_free:
+       devlink_free(devlink);
        return ret;
 }
 
@@ -3819,6 +3893,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
        struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
        struct mlx4_dev  *dev  = persist->dev;
        struct mlx4_priv *priv = mlx4_priv(dev);
+       struct devlink *devlink = priv_to_devlink(priv);
        int active_vfs = 0;
 
        mutex_lock(&persist->interface_state_mutex);
@@ -3849,8 +3924,9 @@ static void mlx4_remove_one(struct pci_dev *pdev)
 
        pci_release_regions(pdev);
        pci_disable_device(pdev);
+       devlink_unregister(devlink);
        kfree(dev->persist);
-       kfree(priv);
+       devlink_free(devlink);
        pci_set_drvdata(pdev, NULL);
 }
 
@@ -3974,45 +4050,53 @@ static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
 {
        struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
        struct mlx4_dev  *dev  = persist->dev;
-       struct mlx4_priv *priv = mlx4_priv(dev);
-       int               ret;
-       int nvfs[MLX4_MAX_PORTS + 1] = {0, 0, 0};
-       int total_vfs;
+       int err;
 
        mlx4_err(dev, "mlx4_pci_slot_reset was called\n");
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               mlx4_err(dev, "Can not re-enable device, ret=%d\n", ret);
+       err = pci_enable_device(pdev);
+       if (err) {
+               mlx4_err(dev, "Can not re-enable device, err=%d\n", err);
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
        pci_set_master(pdev);
        pci_restore_state(pdev);
        pci_save_state(pdev);
+       return PCI_ERS_RESULT_RECOVERED;
+}
 
+static void mlx4_pci_resume(struct pci_dev *pdev)
+{
+       struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
+       struct mlx4_dev  *dev  = persist->dev;
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int nvfs[MLX4_MAX_PORTS + 1] = {0, 0, 0};
+       int total_vfs;
+       int err;
+
+       mlx4_err(dev, "%s was called\n", __func__);
        total_vfs = dev->persist->num_vfs;
        memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs));
 
        mutex_lock(&persist->interface_state_mutex);
        if (!(persist->interface_state & MLX4_INTERFACE_STATE_UP)) {
-               ret = mlx4_load_one(pdev, priv->pci_dev_data, total_vfs, nvfs,
+               err = mlx4_load_one(pdev, priv->pci_dev_data, total_vfs, nvfs,
                                    priv, 1);
-               if (ret) {
-                       mlx4_err(dev, "%s: mlx4_load_one failed, ret=%d\n",
-                                __func__,  ret);
+               if (err) {
+                       mlx4_err(dev, "%s: mlx4_load_one failed, err=%d\n",
+                                __func__,  err);
                        goto end;
                }
 
-               ret = restore_current_port_types(dev, dev->persist->
+               err = restore_current_port_types(dev, dev->persist->
                                                 curr_port_type, dev->persist->
                                                 curr_port_poss_type);
-               if (ret)
-                       mlx4_err(dev, "could not restore original port types (%d)\n", ret);
+               if (err)
+                       mlx4_err(dev, "could not restore original port types (%d)\n", err);
        }
 end:
        mutex_unlock(&persist->interface_state_mutex);
 
-       return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
 }
 
 static void mlx4_shutdown(struct pci_dev *pdev)
@@ -4029,6 +4113,7 @@ static void mlx4_shutdown(struct pci_dev *pdev)
 static const struct pci_error_handlers mlx4_err_handler = {
        .error_detected = mlx4_pci_err_detected,
        .slot_reset     = mlx4_pci_slot_reset,
+       .resume         = mlx4_pci_resume,
 };
 
 static struct pci_driver mlx4_driver = {