|
@@ -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 */
|
|
|
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);
|
|
@@ -2374,10 +2369,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
|
|
|
} else {
|
|
|
atomic_inc(&pf_loading);
|
|
|
err = pci_enable_sriov(pdev, total_vfs);
|
|
|
- atomic_dec(&pf_loading);
|
|
|
if (err) {
|
|
|
mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",
|
|
|
err);
|
|
|
+ atomic_dec(&pf_loading);
|
|
|
err = 0;
|
|
|
} else {
|
|
|
mlx4_warn(dev, "Running in master mode\n");
|
|
@@ -2535,8 +2530,10 @@ 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;
|
|
|
+
|
|
|
+ if (mlx4_is_master(dev) && dev->num_vfs)
|
|
|
+ atomic_dec(&pf_loading);
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -2588,6 +2585,9 @@ err_rel_own:
|
|
|
if (!mlx4_is_slave(dev))
|
|
|
mlx4_free_ownership(dev);
|
|
|
|
|
|
+ if (mlx4_is_master(dev) && dev->num_vfs)
|
|
|
+ atomic_dec(&pf_loading);
|
|
|
+
|
|
|
kfree(priv->dev.dev_vfs);
|
|
|
|
|
|
err_free_dev:
|
|
@@ -2604,85 +2604,110 @@ 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);
|
|
|
|
|
|
- kfree(dev->caps.qp0_tunnel);
|
|
|
- kfree(dev->caps.qp0_proxy);
|
|
|
- kfree(dev->caps.qp1_tunnel);
|
|
|
- kfree(dev->caps.qp1_proxy);
|
|
|
- kfree(dev->dev_vfs);
|
|
|
+ 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(priv);
|
|
|
- pci_release_regions(pdev);
|
|
|
- pci_disable_device(pdev);
|
|
|
- pci_set_drvdata(pdev, NULL);
|
|
|
+ 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);
|
|
|
+ dev->num_vfs = 0;
|
|
|
}
|
|
|
+
|
|
|
+ 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);
|
|
|
+ kfree(dev->dev_vfs);
|
|
|
+
|
|
|
+ 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)
|
|
@@ -2692,7 +2717,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);
|
|
|
}
|
|
|
|
|
@@ -2747,7 +2772,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;
|
|
@@ -2755,11 +2780,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;
|
|
|
}
|