Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx4 / main.c
index 309470ec02190471476744602f98be74ab02f57b..fce9b3a2434720ac3ec2f0a9562e8b5cc2176b0f 100644 (file)
@@ -2292,23 +2292,31 @@ static int mlx4_init_fw(struct mlx4_dev *dev)
 static int mlx4_init_hca(struct mlx4_dev *dev)
 {
        struct mlx4_priv          *priv = mlx4_priv(dev);
+       struct mlx4_init_hca_param *init_hca = NULL;
+       struct mlx4_dev_cap       *dev_cap = NULL;
        struct mlx4_adapter        adapter;
-       struct mlx4_dev_cap        dev_cap;
        struct mlx4_profile        profile;
-       struct mlx4_init_hca_param init_hca;
        u64 icm_size;
        struct mlx4_config_dev_params params;
        int err;
 
        if (!mlx4_is_slave(dev)) {
-               err = mlx4_dev_cap(dev, &dev_cap);
+               dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL);
+               init_hca = kzalloc(sizeof(*init_hca), GFP_KERNEL);
+
+               if (!dev_cap || !init_hca) {
+                       err = -ENOMEM;
+                       goto out_free;
+               }
+
+               err = mlx4_dev_cap(dev, dev_cap);
                if (err) {
                        mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting\n");
-                       return err;
+                       goto out_free;
                }
 
-               choose_steering_mode(dev, &dev_cap);
-               choose_tunnel_offload_mode(dev, &dev_cap);
+               choose_steering_mode(dev, dev_cap);
+               choose_tunnel_offload_mode(dev, dev_cap);
 
                if (dev->caps.dmfs_high_steer_mode == MLX4_STEERING_DMFS_A0_STATIC &&
                    mlx4_is_master(dev))
@@ -2331,48 +2339,48 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                    MLX4_STEERING_MODE_DEVICE_MANAGED)
                        profile.num_mcg = MLX4_FS_NUM_MCG;
 
-               icm_size = mlx4_make_profile(dev, &profile, &dev_cap,
-                                            &init_hca);
+               icm_size = mlx4_make_profile(dev, &profile, dev_cap,
+                                            init_hca);
                if ((long long) icm_size < 0) {
                        err = icm_size;
-                       return err;
+                       goto out_free;
                }
 
                dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1;
 
                if (enable_4k_uar || !dev->persist->num_vfs) {
-                       init_hca.log_uar_sz = ilog2(dev->caps.num_uars) +
+                       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;
+                       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->log_uar_sz = ilog2(dev->caps.num_uars);
+                       init_hca->uar_page_sz = PAGE_SHIFT - 12;
                }
 
-               init_hca.mw_enabled = 0;
+               init_hca->mw_enabled = 0;
                if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW ||
                    dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN)
-                       init_hca.mw_enabled = INIT_HCA_TPT_MW_ENABLE;
+                       init_hca->mw_enabled = INIT_HCA_TPT_MW_ENABLE;
 
-               err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);
+               err = mlx4_init_icm(dev, dev_cap, init_hca, icm_size);
                if (err)
-                       return err;
+                       goto out_free;
 
-               err = mlx4_INIT_HCA(dev, &init_hca);
+               err = mlx4_INIT_HCA(dev, init_hca);
                if (err) {
                        mlx4_err(dev, "INIT_HCA command failed, aborting\n");
                        goto err_free_icm;
                }
 
-               if (dev_cap.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) {
-                       err = mlx4_query_func(dev, &dev_cap);
+               if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) {
+                       err = mlx4_query_func(dev, dev_cap);
                        if (err < 0) {
                                mlx4_err(dev, "QUERY_FUNC command failed, aborting.\n");
                                goto err_close;
                        } else if (err & MLX4_QUERY_FUNC_NUM_SYS_EQS) {
-                               dev->caps.num_eqs = dev_cap.max_eqs;
-                               dev->caps.reserved_eqs = dev_cap.reserved_eqs;
-                               dev->caps.reserved_uars = dev_cap.reserved_uars;
+                               dev->caps.num_eqs = dev_cap->max_eqs;
+                               dev->caps.reserved_eqs = dev_cap->reserved_eqs;
+                               dev->caps.reserved_uars = dev_cap->reserved_uars;
                        }
                }
 
@@ -2381,14 +2389,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                 * read HCA frequency by QUERY_HCA command
                 */
                if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
-                       memset(&init_hca, 0, sizeof(init_hca));
-                       err = mlx4_QUERY_HCA(dev, &init_hca);
+                       err = mlx4_QUERY_HCA(dev, init_hca);
                        if (err) {
                                mlx4_err(dev, "QUERY_HCA command failed, disable timestamp\n");
                                dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
                        } else {
                                dev->caps.hca_core_clock =
-                                       init_hca.hca_core_clock;
+                                       init_hca->hca_core_clock;
                        }
 
                        /* In case we got HCA frequency 0 - disable timestamping
@@ -2464,7 +2471,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
        priv->eq_table.inta_pin = adapter.inta_pin;
        memcpy(dev->board_id, adapter.board_id, sizeof(dev->board_id));
 
-       return 0;
+       err = 0;
+       goto out_free;
 
 unmap_bf:
        unmap_internal_clock(dev);
@@ -2483,6 +2491,10 @@ err_free_icm:
        if (!mlx4_is_slave(dev))
                mlx4_free_icms(dev);
 
+out_free:
+       kfree(dev_cap);
+       kfree(init_hca);
+
        return err;
 }
 
@@ -3919,26 +3931,43 @@ static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink)
        }
 }
 
-static int mlx4_devlink_reload(struct devlink *devlink,
-                              struct netlink_ext_ack *extack)
+static void mlx4_restart_one_down(struct pci_dev *pdev);
+static int mlx4_restart_one_up(struct pci_dev *pdev, bool reload,
+                              struct devlink *devlink);
+
+static int mlx4_devlink_reload_down(struct devlink *devlink,
+                                   struct netlink_ext_ack *extack)
 {
        struct mlx4_priv *priv = devlink_priv(devlink);
        struct mlx4_dev *dev = &priv->dev;
        struct mlx4_dev_persistent *persist = dev->persist;
-       int err;
 
        if (persist->num_vfs)
                mlx4_warn(persist->dev, "Reload performed on PF, will cause reset on operating Virtual Functions\n");
-       err = mlx4_restart_one(persist->pdev, true, devlink);
+       mlx4_restart_one_down(persist->pdev);
+       return 0;
+}
+
+static int mlx4_devlink_reload_up(struct devlink *devlink,
+                                 struct netlink_ext_ack *extack)
+{
+       struct mlx4_priv *priv = devlink_priv(devlink);
+       struct mlx4_dev *dev = &priv->dev;
+       struct mlx4_dev_persistent *persist = dev->persist;
+       int err;
+
+       err = mlx4_restart_one_up(persist->pdev, true, devlink);
        if (err)
-               mlx4_err(persist->dev, "mlx4_restart_one failed, ret=%d\n", err);
+               mlx4_err(persist->dev, "mlx4_restart_one_up failed, ret=%d\n",
+                        err);
 
        return err;
 }
 
 static const struct devlink_ops mlx4_devlink_ops = {
        .port_type_set  = mlx4_devlink_port_type_set,
-       .reload         = mlx4_devlink_reload,
+       .reload_down    = mlx4_devlink_reload_down,
+       .reload_up      = mlx4_devlink_reload_up,
 };
 
 static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -4151,7 +4180,13 @@ static int restore_current_port_types(struct mlx4_dev *dev,
        return err;
 }
 
-int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink)
+static void mlx4_restart_one_down(struct pci_dev *pdev)
+{
+       mlx4_unload_one(pdev);
+}
+
+static int mlx4_restart_one_up(struct pci_dev *pdev, bool reload,
+                              struct devlink *devlink)
 {
        struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
        struct mlx4_dev  *dev  = persist->dev;
@@ -4163,7 +4198,6 @@ int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink)
        total_vfs = dev->persist->num_vfs;
        memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs));
 
-       mlx4_unload_one(pdev);
        if (reload)
                mlx4_devlink_param_load_driverinit_values(devlink);
        err = mlx4_load_one(pdev, pci_dev_data, total_vfs, nvfs, priv, 1);
@@ -4182,6 +4216,12 @@ int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink)
        return err;
 }
 
+int mlx4_restart_one(struct pci_dev *pdev)
+{
+       mlx4_restart_one_down(pdev);
+       return mlx4_restart_one_up(pdev, false, NULL);
+}
+
 #define MLX_SP(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_FORCE_SENSE_PORT }
 #define MLX_VF(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_IS_VF }
 #define MLX_GN(id) { PCI_VDEVICE(MELLANOX, id), 0 }