Joel Stanley | 8f1d88e | 2016-08-29 16:44:12 +0930 | [diff] [blame^] | 1 | From 2a81a42abe8629c8ab1012e2376918665b9cab47 Mon Sep 17 00:00:00 2001 |
Joel Stanley | 2b0f7b4 | 2016-07-19 23:26:28 +0930 | [diff] [blame] | 2 | From: Carol L Soto <clsoto@linux.vnet.ibm.com> |
| 3 | Date: Tue, 12 Jul 2016 17:04:07 -0500 |
Joel Stanley | eeef14f | 2016-08-16 23:09:53 +0930 | [diff] [blame] | 4 | Subject: [PATCH 5/9] net/mlx5: Add pci shutdown callback |
Joel Stanley | 2b0f7b4 | 2016-07-19 23:26:28 +0930 | [diff] [blame] | 5 | |
| 6 | Backport of commit 5fc7197d3a256 ("net/mlx5: Add pci shutdown callback") |
| 7 | so we can use for the OpenPower kernel. |
| 8 | |
| 9 | This patch introduces kexec support for mlx5. |
| 10 | When switching kernels, kexec() calls shutdown, which unloads |
| 11 | the driver and cleans its resources. |
| 12 | |
| 13 | In addition, remove unregister netdev from shutdown flow. This will |
| 14 | allow a clean shutdown, even if some netdev clients did not release their |
| 15 | reference from this netdev. Releasing The HW resources only is enough as |
| 16 | the kernel is shutting down |
| 17 | |
| 18 | Signed-off-by: Majd Dibbiny <majd@mellanox.com> |
| 19 | Signed-off-by: Tariq Toukan <tariqt@mellanox.com> |
| 20 | Signed-off-by: Haggai Abramovsky <hagaya@mellanox.com> |
| 21 | Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> |
| 22 | Signed-off-by: David S. Miller <davem@davemloft.net> |
| 23 | Signed-off-by: Carol L Soto <clsoto@linux.vnet.ibm.com> |
| 24 | (cherry picked from commit 5fc7197d3a256d9c5de3134870304b24892a4908) |
| 25 | Signed-off-by: Joel Stanley <joel@jms.id.au> |
| 26 | --- |
| 27 | drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 15 +++++++++++++-- |
| 28 | drivers/net/ethernet/mellanox/mlx5/core/main.c | 23 +++++++++++++++++++---- |
| 29 | include/linux/mlx5/driver.h | 7 ++++--- |
| 30 | 3 files changed, 36 insertions(+), 9 deletions(-) |
| 31 | |
| 32 | diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| 33 | index cbd17e25beeb..887a54c8e98b 100644 |
| 34 | --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| 35 | +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| 36 | @@ -2241,7 +2241,16 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv) |
| 37 | schedule_work(&priv->set_rx_mode_work); |
| 38 | mlx5e_disable_async_events(priv); |
| 39 | flush_scheduled_work(); |
| 40 | - unregister_netdev(netdev); |
| 41 | + if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) { |
| 42 | + netif_device_detach(netdev); |
| 43 | + mutex_lock(&priv->state_lock); |
| 44 | + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) |
| 45 | + mlx5e_close_locked(netdev); |
| 46 | + mutex_unlock(&priv->state_lock); |
| 47 | + } else { |
| 48 | + unregister_netdev(netdev); |
| 49 | + } |
| 50 | + |
| 51 | mlx5e_destroy_flow_tables(priv); |
| 52 | mlx5e_destroy_tirs(priv); |
| 53 | mlx5e_destroy_rqt(priv, MLX5E_SINGLE_RQ_RQT); |
| 54 | @@ -2252,7 +2261,9 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv) |
| 55 | mlx5_dealloc_transport_domain(priv->mdev, priv->tdn); |
| 56 | mlx5_core_dealloc_pd(priv->mdev, priv->pdn); |
| 57 | mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar); |
| 58 | - free_netdev(netdev); |
| 59 | + |
| 60 | + if (!test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) |
| 61 | + free_netdev(netdev); |
| 62 | } |
| 63 | |
| 64 | static void *mlx5e_get_netdev(void *vpriv) |
| 65 | diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c |
| 66 | index 6cf6d93d8831..8a371bdb823e 100644 |
| 67 | --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c |
| 68 | +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c |
| 69 | @@ -914,7 +914,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) |
| 70 | int err; |
| 71 | |
| 72 | mutex_lock(&dev->intf_state_mutex); |
| 73 | - if (dev->interface_state == MLX5_INTERFACE_STATE_UP) { |
| 74 | + if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { |
| 75 | dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n", |
| 76 | __func__); |
| 77 | goto out; |
| 78 | @@ -1063,7 +1063,8 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) |
| 79 | if (err) |
| 80 | pr_info("failed request module on %s\n", MLX5_IB_MOD); |
| 81 | |
| 82 | - dev->interface_state = MLX5_INTERFACE_STATE_UP; |
| 83 | + clear_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state); |
| 84 | + set_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state); |
| 85 | out: |
| 86 | mutex_unlock(&dev->intf_state_mutex); |
| 87 | |
| 88 | @@ -1125,7 +1126,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) |
| 89 | int err = 0; |
| 90 | |
| 91 | mutex_lock(&dev->intf_state_mutex); |
| 92 | - if (dev->interface_state == MLX5_INTERFACE_STATE_DOWN) { |
| 93 | + if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) { |
| 94 | dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n", |
| 95 | __func__); |
| 96 | goto out; |
| 97 | @@ -1155,7 +1156,8 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) |
| 98 | mlx5_cmd_cleanup(dev); |
| 99 | |
| 100 | out: |
| 101 | - dev->interface_state = MLX5_INTERFACE_STATE_DOWN; |
| 102 | + clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state); |
| 103 | + set_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state); |
| 104 | mutex_unlock(&dev->intf_state_mutex); |
| 105 | return err; |
| 106 | } |
| 107 | @@ -1365,6 +1367,18 @@ static const struct pci_error_handlers mlx5_err_handler = { |
| 108 | .resume = mlx5_pci_resume |
| 109 | }; |
| 110 | |
| 111 | +static void shutdown(struct pci_dev *pdev) |
| 112 | +{ |
| 113 | + struct mlx5_core_dev *dev = pci_get_drvdata(pdev); |
| 114 | + struct mlx5_priv *priv = &dev->priv; |
| 115 | + |
| 116 | + dev_info(&pdev->dev, "Shutdown was called\n"); |
| 117 | + /* Notify mlx5 clients that the kernel is being shut down */ |
| 118 | + set_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &dev->intf_state); |
| 119 | + mlx5_unload_one(dev, priv); |
| 120 | + mlx5_pci_disable_device(dev); |
| 121 | +} |
| 122 | + |
| 123 | static const struct pci_device_id mlx5_core_pci_table[] = { |
| 124 | { PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */ |
| 125 | { PCI_VDEVICE(MELLANOX, 0x1012) }, /* Connect-IB VF */ |
| 126 | @@ -1382,6 +1396,7 @@ static struct pci_driver mlx5_core_driver = { |
| 127 | .id_table = mlx5_core_pci_table, |
| 128 | .probe = init_one, |
| 129 | .remove = remove_one, |
| 130 | + .shutdown = shutdown, |
| 131 | .err_handler = &mlx5_err_handler |
| 132 | }; |
| 133 | |
| 134 | diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h |
| 135 | index 412aa988c6ad..dc26d9942120 100644 |
| 136 | --- a/include/linux/mlx5/driver.h |
| 137 | +++ b/include/linux/mlx5/driver.h |
| 138 | @@ -493,8 +493,9 @@ enum mlx5_device_state { |
| 139 | }; |
| 140 | |
| 141 | enum mlx5_interface_state { |
| 142 | - MLX5_INTERFACE_STATE_DOWN, |
| 143 | - MLX5_INTERFACE_STATE_UP, |
| 144 | + MLX5_INTERFACE_STATE_DOWN = BIT(0), |
| 145 | + MLX5_INTERFACE_STATE_UP = BIT(1), |
| 146 | + MLX5_INTERFACE_STATE_SHUTDOWN = BIT(2), |
| 147 | }; |
| 148 | |
| 149 | enum mlx5_pci_status { |
| 150 | @@ -518,7 +519,7 @@ struct mlx5_core_dev { |
| 151 | enum mlx5_device_state state; |
| 152 | /* sync interface state */ |
| 153 | struct mutex intf_state_mutex; |
| 154 | - enum mlx5_interface_state interface_state; |
| 155 | + unsigned long intf_state; |
| 156 | void (*event) (struct mlx5_core_dev *dev, |
| 157 | enum mlx5_dev_event event, |
| 158 | unsigned long param); |
| 159 | -- |
Joel Stanley | 8f1d88e | 2016-08-29 16:44:12 +0930 | [diff] [blame^] | 160 | 2.9.3 |
Joel Stanley | 2b0f7b4 | 2016-07-19 23:26:28 +0930 | [diff] [blame] | 161 | |