Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit befdf897 authored by Wei Yang's avatar Wei Yang Committed by David S. Miller
Browse files

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: 97a5221f "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: default avatarWei Yang <weiyang@linux.vnet.ibm.com>
Acked-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b04c4619
Loading
Loading
Loading
Loading
+95 −77
Original line number Original line Diff line number Diff line
@@ -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 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
	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 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)


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);
		pci_set_drvdata(pdev, NULL);
	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)
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;
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -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;