aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2017-01-30 08:11:45 -0500
committerDavid S. Miller <davem@davemloft.net>2017-01-30 15:45:27 -0500
commitd585df1c5ccf995fcee910705ad7a9cdd11d4152 (patch)
treeba9f169698d23cc8623eb70aeadcfea197dbc37e
parent6415aa5039bd40022e0377afb8ce53f8637080e7 (diff)
net/mlx4_core: Avoid command timeouts during VF driver device shutdown
Some Hypervisors detach VFs from VMs by instantly causing an FLR event to be generated for a VF. In the mlx4 case, this will cause that VF's comm channel to be disabled before the VM has an opportunity to invoke the VF device's "shutdown" method. The result is that the VF driver on the VM will experience a command timeout during the shutdown process when the Hypervisor does not deliver a command-completion event to the VM. To avoid FW command timeouts on the VM when the driver's shutdown method is invoked, we detect the absence of the VF's comm channel at the very start of the shutdown process. If the comm-channel has already been disabled, we cause all FW commands during the device shutdown process to immediately return success (and thus avoid all command timeouts). Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/catas.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/intf.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h1
3 files changed, 14 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c
index c7e939945259..53daa6ca5d83 100644
--- a/drivers/net/ethernet/mellanox/mlx4/catas.c
+++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
@@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev)
158 return -ETIMEDOUT; 158 return -ETIMEDOUT;
159} 159}
160 160
161static int mlx4_comm_internal_err(u32 slave_read) 161int mlx4_comm_internal_err(u32 slave_read)
162{ 162{
163 return (u32)COMM_CHAN_EVENT_INTERNAL_ERR == 163 return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
164 (slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0; 164 (slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c
index 0e8b7c44931f..8258d08acd8c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/intf.c
+++ b/drivers/net/ethernet/mellanox/mlx4/intf.c
@@ -222,6 +222,18 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
222 return; 222 return;
223 223
224 mlx4_stop_catas_poll(dev); 224 mlx4_stop_catas_poll(dev);
225 if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
226 mlx4_is_slave(dev)) {
227 /* In mlx4_remove_one on a VF */
228 u32 slave_read =
229 swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
230
231 if (mlx4_comm_internal_err(slave_read)) {
232 mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
233 __func__);
234 mlx4_enter_error_state(dev->persist);
235 }
236 }
225 mutex_lock(&intf_mutex); 237 mutex_lock(&intf_mutex);
226 238
227 list_for_each_entry(intf, &intf_list, list) 239 list_for_each_entry(intf, &intf_list, list)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 88ee7d8a5923..086920b615af 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -1220,6 +1220,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type);
1220void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); 1220void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
1221 1221
1222void mlx4_enter_error_state(struct mlx4_dev_persistent *persist); 1222void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
1223int mlx4_comm_internal_err(u32 slave_read);
1223 1224
1224int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, 1225int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
1225 enum mlx4_port_type *type); 1226 enum mlx4_port_type *type);