lkml.org 
[lkml]   [2015]   [Apr]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 126/155] net/mlx4_core: Preserve pci_dev_data after __mlx4_remove_one()
    Date
    From: Wei Yang <weiyang@linux.vnet.ibm.com>

    3.12-stable review patch. If anyone has any objections, please let me know.

    ===============

    [ Upstream commit befdf8978accecac2e0739e6b5075afc62db37fe ]

    pci_match_id() just match the static pci_device_id, which may return NULL if
    someone binds the driver to a device manually using
    /sys/bus/pci/drivers/.../new_id.

    This patch wrap up a helper function __mlx4_remove_one() which does the tear
    down function but preserve the drv_data. Functions like
    mlx4_pci_err_detected() and mlx4_restart_one() will call this one with out
    releasing drvdata.

    Fixes: 97a5221 "net/mlx4_core: pass pci_device_id.driver_data to __mlx4_init_one during reset".

    CC: Bjorn Helgaas <bhelgaas@google.com>
    CC: Amir Vadai <amirv@mellanox.com>
    CC: Jack Morgenstein <jackm@dev.mellanox.co.il>
    CC: Or Gerlitz <ogerlitz@mellanox.com>
    Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
    Acked-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    ---
    drivers/net/ethernet/mellanox/mlx4/main.c | 170 +++++++++++++++++-------------
    drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 +
    2 files changed, 95 insertions(+), 76 deletions(-)

    diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
    index 4aa9d48ef72b..d98586085cab 100644
    --- a/drivers/net/ethernet/mellanox/mlx4/main.c
    +++ b/drivers/net/ethernet/mellanox/mlx4/main.c
    @@ -2134,13 +2134,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
    /* Allow large DMA segments, up to the firmware limit of 1 GB */
    dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);

    - priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    - if (!priv) {
    - err = -ENOMEM;
    - goto err_release_regions;
    - }
    -
    - dev = &priv->dev;
    + dev = pci_get_drvdata(pdev);
    + priv = mlx4_priv(dev);
    dev->pdev = pdev;
    INIT_LIST_HEAD(&priv->ctx_list);
    spin_lock_init(&priv->ctx_lock);
    @@ -2308,8 +2303,7 @@ slave_start:
    mlx4_sense_init(dev);
    mlx4_start_sense(dev);

    - priv->pci_dev_data = pci_dev_data;
    - pci_set_drvdata(pdev, dev);
    + priv->removed = 0;

    return 0;

    @@ -2375,84 +2369,108 @@ err_disable_pdev:

    static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
    {
    + struct mlx4_priv *priv;
    + struct mlx4_dev *dev;
    +
    printk_once(KERN_INFO "%s", mlx4_version);

    + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    + if (!priv)
    + return -ENOMEM;
    +
    + dev = &priv->dev;
    + pci_set_drvdata(pdev, dev);
    + priv->pci_dev_data = id->driver_data;
    +
    return __mlx4_init_one(pdev, id->driver_data);
    }

    -static void mlx4_remove_one(struct pci_dev *pdev)
    +static void __mlx4_remove_one(struct pci_dev *pdev)
    {
    struct mlx4_dev *dev = pci_get_drvdata(pdev);
    struct mlx4_priv *priv = mlx4_priv(dev);
    + int pci_dev_data;
    int p;

    - if (dev) {
    - /* in SRIOV it is not allowed to unload the pf's
    - * driver while there are alive vf's */
    - if (mlx4_is_master(dev)) {
    - if (mlx4_how_many_lives_vf(dev))
    - printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
    - }
    - mlx4_stop_sense(dev);
    - mlx4_unregister_device(dev);
    + if (priv->removed)
    + return;

    - for (p = 1; p <= dev->caps.num_ports; p++) {
    - mlx4_cleanup_port_info(&priv->port[p]);
    - mlx4_CLOSE_PORT(dev, p);
    - }
    + pci_dev_data = priv->pci_dev_data;

    - if (mlx4_is_master(dev))
    - mlx4_free_resource_tracker(dev,
    - RES_TR_FREE_SLAVES_ONLY);
    -
    - mlx4_cleanup_counters_table(dev);
    - mlx4_cleanup_qp_table(dev);
    - mlx4_cleanup_srq_table(dev);
    - mlx4_cleanup_cq_table(dev);
    - mlx4_cmd_use_polling(dev);
    - mlx4_cleanup_eq_table(dev);
    - mlx4_cleanup_mcg_table(dev);
    - mlx4_cleanup_mr_table(dev);
    - mlx4_cleanup_xrcd_table(dev);
    - mlx4_cleanup_pd_table(dev);
    + /* in SRIOV it is not allowed to unload the pf's
    + * driver while there are alive vf's */
    + if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev))
    + printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
    + mlx4_stop_sense(dev);
    + mlx4_unregister_device(dev);

    - if (mlx4_is_master(dev))
    - mlx4_free_resource_tracker(dev,
    - RES_TR_FREE_STRUCTS_ONLY);
    -
    - iounmap(priv->kar);
    - mlx4_uar_free(dev, &priv->driver_uar);
    - mlx4_cleanup_uar_table(dev);
    - if (!mlx4_is_slave(dev))
    - mlx4_clear_steering(dev);
    - mlx4_free_eq_table(dev);
    - if (mlx4_is_master(dev))
    - mlx4_multi_func_cleanup(dev);
    - mlx4_close_hca(dev);
    - if (mlx4_is_slave(dev))
    - mlx4_multi_func_cleanup(dev);
    - mlx4_cmd_cleanup(dev);
    -
    - if (dev->flags & MLX4_FLAG_MSI_X)
    - pci_disable_msix(pdev);
    - if (dev->flags & MLX4_FLAG_SRIOV) {
    - mlx4_warn(dev, "Disabling SR-IOV\n");
    - pci_disable_sriov(pdev);
    - }
    + for (p = 1; p <= dev->caps.num_ports; p++) {
    + mlx4_cleanup_port_info(&priv->port[p]);
    + mlx4_CLOSE_PORT(dev, p);
    + }

    - if (!mlx4_is_slave(dev))
    - mlx4_free_ownership(dev);
    + if (mlx4_is_master(dev))
    + mlx4_free_resource_tracker(dev,
    + RES_TR_FREE_SLAVES_ONLY);
    +
    + mlx4_cleanup_counters_table(dev);
    + mlx4_cleanup_qp_table(dev);
    + mlx4_cleanup_srq_table(dev);
    + mlx4_cleanup_cq_table(dev);
    + mlx4_cmd_use_polling(dev);
    + mlx4_cleanup_eq_table(dev);
    + mlx4_cleanup_mcg_table(dev);
    + mlx4_cleanup_mr_table(dev);
    + mlx4_cleanup_xrcd_table(dev);
    + mlx4_cleanup_pd_table(dev);

    - kfree(dev->caps.qp0_tunnel);
    - kfree(dev->caps.qp0_proxy);
    - kfree(dev->caps.qp1_tunnel);
    - kfree(dev->caps.qp1_proxy);
    + if (mlx4_is_master(dev))
    + mlx4_free_resource_tracker(dev,
    + RES_TR_FREE_STRUCTS_ONLY);

    - kfree(priv);
    - pci_release_regions(pdev);
    - pci_disable_device(pdev);
    - pci_set_drvdata(pdev, NULL);
    + iounmap(priv->kar);
    + mlx4_uar_free(dev, &priv->driver_uar);
    + mlx4_cleanup_uar_table(dev);
    + if (!mlx4_is_slave(dev))
    + mlx4_clear_steering(dev);
    + mlx4_free_eq_table(dev);
    + if (mlx4_is_master(dev))
    + mlx4_multi_func_cleanup(dev);
    + mlx4_close_hca(dev);
    + if (mlx4_is_slave(dev))
    + mlx4_multi_func_cleanup(dev);
    + mlx4_cmd_cleanup(dev);
    +
    + if (dev->flags & MLX4_FLAG_MSI_X)
    + pci_disable_msix(pdev);
    + if (dev->flags & MLX4_FLAG_SRIOV) {
    + mlx4_warn(dev, "Disabling SR-IOV\n");
    + pci_disable_sriov(pdev);
    }
    +
    + if (!mlx4_is_slave(dev))
    + mlx4_free_ownership(dev);
    +
    + kfree(dev->caps.qp0_tunnel);
    + kfree(dev->caps.qp0_proxy);
    + kfree(dev->caps.qp1_tunnel);
    + kfree(dev->caps.qp1_proxy);
    +
    + pci_release_regions(pdev);
    + pci_disable_device(pdev);
    + memset(priv, 0, sizeof(*priv));
    + priv->pci_dev_data = pci_dev_data;
    + priv->removed = 1;
    +}
    +
    +static void mlx4_remove_one(struct pci_dev *pdev)
    +{
    + struct mlx4_dev *dev = pci_get_drvdata(pdev);
    + struct mlx4_priv *priv = mlx4_priv(dev);
    +
    + __mlx4_remove_one(pdev);
    + kfree(priv);
    + pci_set_drvdata(pdev, NULL);
    }

    int mlx4_restart_one(struct pci_dev *pdev)
    @@ -2462,7 +2480,7 @@ int mlx4_restart_one(struct pci_dev *pdev)
    int pci_dev_data;

    pci_dev_data = priv->pci_dev_data;
    - mlx4_remove_one(pdev);
    + __mlx4_remove_one(pdev);
    return __mlx4_init_one(pdev, pci_dev_data);
    }

    @@ -2517,7 +2535,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table);
    static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
    pci_channel_state_t state)
    {
    - mlx4_remove_one(pdev);
    + __mlx4_remove_one(pdev);

    return state == pci_channel_io_perm_failure ?
    PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
    @@ -2525,11 +2543,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,

    static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
    {
    - const struct pci_device_id *id;
    - int ret;
    + struct mlx4_dev *dev = pci_get_drvdata(pdev);
    + struct mlx4_priv *priv = mlx4_priv(dev);
    + int ret;

    - id = pci_match_id(mlx4_pci_table, pdev);
    - ret = __mlx4_init_one(pdev, id->driver_data);
    + ret = __mlx4_init_one(pdev, priv->pci_dev_data);

    return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
    }
    diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
    index 348bb8c7d9a7..796ed1a79284 100644
    --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
    +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
    @@ -774,6 +774,7 @@ struct mlx4_priv {
    spinlock_t ctx_lock;

    int pci_dev_data;
    + int removed;

    struct list_head pgdir_list;
    struct mutex pgdir_mutex;
    --
    2.3.4


    \
     
     \ /
      Last update: 2015-04-07 15:01    [W:4.107 / U:0.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site