aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMajd Dibbiny <majd@mellanox.com>2016-04-21 17:33:07 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-24 14:51:39 -0400
commit5fc7197d3a256d9c5de3134870304b24892a4908 (patch)
tree21c40ba8cda98f95f20a47f60d9c5d73b0180408
parent78228cbdeb0aa5c96e2a721e7e0d6953b416b5a3 (diff)
net/mlx5: Add pci shutdown callback
This patch introduces kexec support for mlx5. When switching kernels, kexec() calls shutdown, which unloads the driver and cleans its resources. In addition, remove unregister netdev from shutdown flow. This will allow a clean shutdown, even if some netdev clients did not release their reference from this netdev. Releasing The HW resources only is enough as the kernel is shutting down Signed-off-by: Majd Dibbiny <majd@mellanox.com> Signed-off-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: Haggai Abramovsky <hagaya@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c23
-rw-r--r--include/linux/mlx5/driver.h7
3 files changed, 36 insertions, 9 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 85773f8573e5..67d548b70e14 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2633,7 +2633,16 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
2633 schedule_work(&priv->set_rx_mode_work); 2633 schedule_work(&priv->set_rx_mode_work);
2634 mlx5e_disable_async_events(priv); 2634 mlx5e_disable_async_events(priv);
2635 flush_scheduled_work(); 2635 flush_scheduled_work();
2636 unregister_netdev(netdev); 2636 if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) {
2637 netif_device_detach(netdev);
2638 mutex_lock(&priv->state_lock);
2639 if (test_bit(MLX5E_STATE_OPENED, &priv->state))
2640 mlx5e_close_locked(netdev);
2641 mutex_unlock(&priv->state_lock);
2642 } else {
2643 unregister_netdev(netdev);
2644 }
2645
2637 mlx5e_tc_cleanup(priv); 2646 mlx5e_tc_cleanup(priv);
2638 mlx5e_vxlan_cleanup(priv); 2647 mlx5e_vxlan_cleanup(priv);
2639 mlx5e_destroy_flow_tables(priv); 2648 mlx5e_destroy_flow_tables(priv);
@@ -2646,7 +2655,9 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
2646 mlx5_core_dealloc_transport_domain(priv->mdev, priv->tdn); 2655 mlx5_core_dealloc_transport_domain(priv->mdev, priv->tdn);
2647 mlx5_core_dealloc_pd(priv->mdev, priv->pdn); 2656 mlx5_core_dealloc_pd(priv->mdev, priv->pdn);
2648 mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar); 2657 mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar);
2649 free_netdev(netdev); 2658
2659 if (!test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state))
2660 free_netdev(netdev);
2650} 2661}
2651 2662
2652static void *mlx5e_get_netdev(void *vpriv) 2663static void *mlx5e_get_netdev(void *vpriv)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index ddd352ae3dbd..6892746fd10d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -966,7 +966,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
966 int err; 966 int err;
967 967
968 mutex_lock(&dev->intf_state_mutex); 968 mutex_lock(&dev->intf_state_mutex);
969 if (dev->interface_state == MLX5_INTERFACE_STATE_UP) { 969 if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
970 dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n", 970 dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n",
971 __func__); 971 __func__);
972 goto out; 972 goto out;
@@ -1133,7 +1133,8 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
1133 if (err) 1133 if (err)
1134 pr_info("failed request module on %s\n", MLX5_IB_MOD); 1134 pr_info("failed request module on %s\n", MLX5_IB_MOD);
1135 1135
1136 dev->interface_state = MLX5_INTERFACE_STATE_UP; 1136 clear_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state);
1137 set_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
1137out: 1138out:
1138 mutex_unlock(&dev->intf_state_mutex); 1139 mutex_unlock(&dev->intf_state_mutex);
1139 1140
@@ -1207,7 +1208,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
1207 } 1208 }
1208 1209
1209 mutex_lock(&dev->intf_state_mutex); 1210 mutex_lock(&dev->intf_state_mutex);
1210 if (dev->interface_state == MLX5_INTERFACE_STATE_DOWN) { 1211 if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
1211 dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n", 1212 dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
1212 __func__); 1213 __func__);
1213 goto out; 1214 goto out;
@@ -1241,7 +1242,8 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
1241 mlx5_cmd_cleanup(dev); 1242 mlx5_cmd_cleanup(dev);
1242 1243
1243out: 1244out:
1244 dev->interface_state = MLX5_INTERFACE_STATE_DOWN; 1245 clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
1246 set_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state);
1245 mutex_unlock(&dev->intf_state_mutex); 1247 mutex_unlock(&dev->intf_state_mutex);
1246 return err; 1248 return err;
1247} 1249}
@@ -1452,6 +1454,18 @@ static const struct pci_error_handlers mlx5_err_handler = {
1452 .resume = mlx5_pci_resume 1454 .resume = mlx5_pci_resume
1453}; 1455};
1454 1456
1457static void shutdown(struct pci_dev *pdev)
1458{
1459 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1460 struct mlx5_priv *priv = &dev->priv;
1461
1462 dev_info(&pdev->dev, "Shutdown was called\n");
1463 /* Notify mlx5 clients that the kernel is being shut down */
1464 set_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &dev->intf_state);
1465 mlx5_unload_one(dev, priv);
1466 mlx5_pci_disable_device(dev);
1467}
1468
1455static const struct pci_device_id mlx5_core_pci_table[] = { 1469static const struct pci_device_id mlx5_core_pci_table[] = {
1456 { PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */ 1470 { PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */
1457 { PCI_VDEVICE(MELLANOX, 0x1012), MLX5_PCI_DEV_IS_VF}, /* Connect-IB VF */ 1471 { PCI_VDEVICE(MELLANOX, 0x1012), MLX5_PCI_DEV_IS_VF}, /* Connect-IB VF */
@@ -1471,6 +1485,7 @@ static struct pci_driver mlx5_core_driver = {
1471 .id_table = mlx5_core_pci_table, 1485 .id_table = mlx5_core_pci_table,
1472 .probe = init_one, 1486 .probe = init_one,
1473 .remove = remove_one, 1487 .remove = remove_one,
1488 .shutdown = shutdown,
1474 .err_handler = &mlx5_err_handler, 1489 .err_handler = &mlx5_err_handler,
1475 .sriov_configure = mlx5_core_sriov_configure, 1490 .sriov_configure = mlx5_core_sriov_configure,
1476}; 1491};
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index dcd5ac8d3b14..369c837d40f5 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -519,8 +519,9 @@ enum mlx5_device_state {
519}; 519};
520 520
521enum mlx5_interface_state { 521enum mlx5_interface_state {
522 MLX5_INTERFACE_STATE_DOWN, 522 MLX5_INTERFACE_STATE_DOWN = BIT(0),
523 MLX5_INTERFACE_STATE_UP, 523 MLX5_INTERFACE_STATE_UP = BIT(1),
524 MLX5_INTERFACE_STATE_SHUTDOWN = BIT(2),
524}; 525};
525 526
526enum mlx5_pci_status { 527enum mlx5_pci_status {
@@ -544,7 +545,7 @@ struct mlx5_core_dev {
544 enum mlx5_device_state state; 545 enum mlx5_device_state state;
545 /* sync interface state */ 546 /* sync interface state */
546 struct mutex intf_state_mutex; 547 struct mutex intf_state_mutex;
547 enum mlx5_interface_state interface_state; 548 unsigned long intf_state;
548 void (*event) (struct mlx5_core_dev *dev, 549 void (*event) (struct mlx5_core_dev *dev,
549 enum mlx5_dev_event event, 550 enum mlx5_dev_event event,
550 unsigned long param); 551 unsigned long param);