IB/mlx5: Port events in RoCE now rely on netdev events

Since ib_query_port() in RoCE returns the state of its netdev as the port
state, it makes sense to propagate the port up/down events to ib_core
when the netdev port state changes, instead of relying on traditional
core events.

This also keeps both the event and ib_query_port() synchronized.

Signed-off-by: Aviv Heller <avivh@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Aviv Heller 2016-09-18 20:48:00 +03:00 committed by Doug Ledford
parent 350d0e4c7e
commit 5ec8c83e3a
1 changed files with 51 additions and 15 deletions

View File

@ -107,13 +107,32 @@ static int mlx5_netdev_event(struct notifier_block *this,
struct mlx5_ib_dev *ibdev = container_of(this, struct mlx5_ib_dev, struct mlx5_ib_dev *ibdev = container_of(this, struct mlx5_ib_dev,
roce.nb); roce.nb);
if ((event != NETDEV_UNREGISTER) && (event != NETDEV_REGISTER)) switch (event) {
return NOTIFY_DONE; case NETDEV_REGISTER:
case NETDEV_UNREGISTER:
write_lock(&ibdev->roce.netdev_lock);
if (ndev->dev.parent == &ibdev->mdev->pdev->dev)
ibdev->roce.netdev = (event == NETDEV_UNREGISTER) ?
NULL : ndev;
write_unlock(&ibdev->roce.netdev_lock);
break;
write_lock(&ibdev->roce.netdev_lock); case NETDEV_UP:
if (ndev->dev.parent == &ibdev->mdev->pdev->dev) case NETDEV_DOWN:
ibdev->roce.netdev = (event == NETDEV_UNREGISTER) ? NULL : ndev; if (ndev == ibdev->roce.netdev && ibdev->ib_active) {
write_unlock(&ibdev->roce.netdev_lock); struct ib_event ibev = {0};
ibev.device = &ibdev->ib_dev;
ibev.event = (event == NETDEV_UP) ?
IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
ibev.element.port_num = 1;
ib_dispatch_event(&ibev);
}
break;
default:
break;
}
return NOTIFY_DONE; return NOTIFY_DONE;
} }
@ -2267,14 +2286,19 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
break; break;
case MLX5_DEV_EVENT_PORT_UP: case MLX5_DEV_EVENT_PORT_UP:
ibev.event = IB_EVENT_PORT_ACTIVE;
port = (u8)param;
break;
case MLX5_DEV_EVENT_PORT_DOWN: case MLX5_DEV_EVENT_PORT_DOWN:
case MLX5_DEV_EVENT_PORT_INITIALIZED: case MLX5_DEV_EVENT_PORT_INITIALIZED:
ibev.event = IB_EVENT_PORT_ERR;
port = (u8)param; port = (u8)param;
/* In RoCE, port up/down events are handled in
* mlx5_netdev_event().
*/
if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==
IB_LINK_LAYER_ETHERNET)
return;
ibev.event = (event == MLX5_DEV_EVENT_PORT_UP) ?
IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
break; break;
case MLX5_DEV_EVENT_LID_CHANGE: case MLX5_DEV_EVENT_LID_CHANGE:
@ -2679,14 +2703,24 @@ static void get_dev_fw_str(struct ib_device *ibdev, char *str,
fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev)); fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
} }
static void mlx5_remove_roce_notifier(struct mlx5_ib_dev *dev)
{
if (dev->roce.nb.notifier_call) {
unregister_netdevice_notifier(&dev->roce.nb);
dev->roce.nb.notifier_call = NULL;
}
}
static int mlx5_enable_roce(struct mlx5_ib_dev *dev) static int mlx5_enable_roce(struct mlx5_ib_dev *dev)
{ {
int err; int err;
dev->roce.nb.notifier_call = mlx5_netdev_event; dev->roce.nb.notifier_call = mlx5_netdev_event;
err = register_netdevice_notifier(&dev->roce.nb); err = register_netdevice_notifier(&dev->roce.nb);
if (err) if (err) {
dev->roce.nb.notifier_call = NULL;
return err; return err;
}
err = mlx5_nic_vport_enable_roce(dev->mdev); err = mlx5_nic_vport_enable_roce(dev->mdev);
if (err) if (err)
@ -2695,14 +2729,13 @@ static int mlx5_enable_roce(struct mlx5_ib_dev *dev)
return 0; return 0;
err_unregister_netdevice_notifier: err_unregister_netdevice_notifier:
unregister_netdevice_notifier(&dev->roce.nb); mlx5_remove_roce_notifier(dev);
return err; return err;
} }
static void mlx5_disable_roce(struct mlx5_ib_dev *dev) static void mlx5_disable_roce(struct mlx5_ib_dev *dev)
{ {
mlx5_nic_vport_disable_roce(dev->mdev); mlx5_nic_vport_disable_roce(dev->mdev);
unregister_netdevice_notifier(&dev->roce.nb);
} }
static void mlx5_ib_dealloc_q_counters(struct mlx5_ib_dev *dev) static void mlx5_ib_dealloc_q_counters(struct mlx5_ib_dev *dev)
@ -3051,8 +3084,10 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
destroy_dev_resources(&dev->devr); destroy_dev_resources(&dev->devr);
err_disable_roce: err_disable_roce:
if (ll == IB_LINK_LAYER_ETHERNET) if (ll == IB_LINK_LAYER_ETHERNET) {
mlx5_disable_roce(dev); mlx5_disable_roce(dev);
mlx5_remove_roce_notifier(dev);
}
err_free_port: err_free_port:
kfree(dev->port); kfree(dev->port);
@ -3068,6 +3103,7 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
struct mlx5_ib_dev *dev = context; struct mlx5_ib_dev *dev = context;
enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev, 1); enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev, 1);
mlx5_remove_roce_notifier(dev);
ib_unregister_device(&dev->ib_dev); ib_unregister_device(&dev->ib_dev);
mlx5_ib_dealloc_q_counters(dev); mlx5_ib_dealloc_q_counters(dev);
destroy_umrc_res(dev); destroy_umrc_res(dev);