net/mlx4_core: Preserve pci_dev_data after __mlx4_remove_one()
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>
This commit is contained in:
parent
b04c461902
commit
befdf8978a
@ -2301,13 +2301,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 */
|
/* Allow large DMA segments, up to the firmware limit of 1 GB */
|
||||||
dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
|
dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
dev = pci_get_drvdata(pdev);
|
||||||
if (!priv) {
|
priv = mlx4_priv(dev);
|
||||||
err = -ENOMEM;
|
|
||||||
goto err_release_regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = &priv->dev;
|
|
||||||
dev->pdev = pdev;
|
dev->pdev = pdev;
|
||||||
INIT_LIST_HEAD(&priv->ctx_list);
|
INIT_LIST_HEAD(&priv->ctx_list);
|
||||||
spin_lock_init(&priv->ctx_lock);
|
spin_lock_init(&priv->ctx_lock);
|
||||||
@ -2535,8 +2530,7 @@ slave_start:
|
|||||||
mlx4_sense_init(dev);
|
mlx4_sense_init(dev);
|
||||||
mlx4_start_sense(dev);
|
mlx4_start_sense(dev);
|
||||||
|
|
||||||
priv->pci_dev_data = pci_dev_data;
|
priv->removed = 0;
|
||||||
pci_set_drvdata(pdev, dev);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -2604,24 +2598,38 @@ err_disable_pdev:
|
|||||||
|
|
||||||
static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
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);
|
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);
|
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_dev *dev = pci_get_drvdata(pdev);
|
||||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
|
int pci_dev_data;
|
||||||
int p;
|
int p;
|
||||||
|
|
||||||
if (dev) {
|
if (priv->removed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pci_dev_data = priv->pci_dev_data;
|
||||||
|
|
||||||
/* in SRIOV it is not allowed to unload the pf's
|
/* in SRIOV it is not allowed to unload the pf's
|
||||||
* driver while there are alive vf's */
|
* driver while there are alive vf's */
|
||||||
if (mlx4_is_master(dev)) {
|
if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev))
|
||||||
if (mlx4_how_many_lives_vf(dev))
|
|
||||||
printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
|
printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
|
||||||
}
|
|
||||||
mlx4_stop_sense(dev);
|
mlx4_stop_sense(dev);
|
||||||
mlx4_unregister_device(dev);
|
mlx4_unregister_device(dev);
|
||||||
|
|
||||||
@ -2678,11 +2686,21 @@ static void mlx4_remove_one(struct pci_dev *pdev)
|
|||||||
kfree(dev->caps.qp1_proxy);
|
kfree(dev->caps.qp1_proxy);
|
||||||
kfree(dev->dev_vfs);
|
kfree(dev->dev_vfs);
|
||||||
|
|
||||||
kfree(priv);
|
|
||||||
pci_release_regions(pdev);
|
pci_release_regions(pdev);
|
||||||
pci_disable_device(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);
|
pci_set_drvdata(pdev, NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx4_restart_one(struct pci_dev *pdev)
|
int mlx4_restart_one(struct pci_dev *pdev)
|
||||||
@ -2692,7 +2710,7 @@ int mlx4_restart_one(struct pci_dev *pdev)
|
|||||||
int pci_dev_data;
|
int pci_dev_data;
|
||||||
|
|
||||||
pci_dev_data = priv->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);
|
return __mlx4_init_one(pdev, pci_dev_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2747,7 +2765,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table);
|
|||||||
static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
|
static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
|
||||||
pci_channel_state_t state)
|
pci_channel_state_t state)
|
||||||
{
|
{
|
||||||
mlx4_remove_one(pdev);
|
__mlx4_remove_one(pdev);
|
||||||
|
|
||||||
return state == pci_channel_io_perm_failure ?
|
return state == pci_channel_io_perm_failure ?
|
||||||
PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
|
PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
|
||||||
@ -2755,11 +2773,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)
|
static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
const struct pci_device_id *id;
|
struct mlx4_dev *dev = pci_get_drvdata(pdev);
|
||||||
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
id = pci_match_id(mlx4_pci_table, pdev);
|
ret = __mlx4_init_one(pdev, priv->pci_dev_data);
|
||||||
ret = __mlx4_init_one(pdev, id->driver_data);
|
|
||||||
|
|
||||||
return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
|
return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
|
||||||
}
|
}
|
||||||
|
@ -800,6 +800,7 @@ struct mlx4_priv {
|
|||||||
spinlock_t ctx_lock;
|
spinlock_t ctx_lock;
|
||||||
|
|
||||||
int pci_dev_data;
|
int pci_dev_data;
|
||||||
|
int removed;
|
||||||
|
|
||||||
struct list_head pgdir_list;
|
struct list_head pgdir_list;
|
||||||
struct mutex pgdir_mutex;
|
struct mutex pgdir_mutex;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user