Skip to content

Commit

Permalink
IB/mlx5: Change logic for dispatching IB events for port state
Browse files Browse the repository at this point in the history
The old logic ignored link state. This led to missing IB events like
when link goes down on the switch while admin state is up or to redundant
events like when admin state goes up while link is down.
To fix that, probe the port state on NETDEV events and compare to last
known state to decide if IB events needs to be dispatched.

FIxes: 5ec8c83 ("IB/mlx5: Port events in RoCE now rely on netdev events")
Signed-off-by: Moni Shoua <[email protected]>
Reviewed-by: Noa Osherovich <[email protected]>
Signed-off-by: Leon Romanovsky <[email protected]>
Signed-off-by: Doug Ledford <[email protected]>
  • Loading branch information
monis410 authored and dledford committed Jul 24, 2017
1 parent 2c43c5a commit fd65f1b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
33 changes: 31 additions & 2 deletions drivers/infiniband/hw/mlx5/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ mlx5_ib_port_link_layer(struct ib_device *device, u8 port_num)
return mlx5_port_type_cap_to_rdma_ll(port_type_cap);
}

static int get_port_state(struct ib_device *ibdev,
u8 port_num,
enum ib_port_state *state)
{
struct ib_port_attr attr;
int ret;

memset(&attr, 0, sizeof(attr));
ret = mlx5_ib_query_port(ibdev, port_num, &attr);
if (!ret)
*state = attr.state;
return ret;
}

static int mlx5_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
Expand All @@ -115,6 +129,7 @@ static int mlx5_netdev_event(struct notifier_block *this,
write_unlock(&ibdev->roce.netdev_lock);
break;

case NETDEV_CHANGE:
case NETDEV_UP:
case NETDEV_DOWN: {
struct net_device *lag_ndev = mlx5_lag_get_roce_netdev(ibdev->mdev);
Expand All @@ -128,10 +143,23 @@ static int mlx5_netdev_event(struct notifier_block *this,
if ((upper == ndev || (!upper && ndev == ibdev->roce.netdev))
&& ibdev->ib_active) {
struct ib_event ibev = { };
enum ib_port_state port_state;

if (get_port_state(&ibdev->ib_dev, 1, &port_state))
return NOTIFY_DONE;

if (ibdev->roce.last_port_state == port_state)
return NOTIFY_DONE;

ibdev->roce.last_port_state = port_state;
ibev.device = &ibdev->ib_dev;
ibev.event = (event == NETDEV_UP) ?
IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
if (port_state == IB_PORT_DOWN)
ibev.event = IB_EVENT_PORT_ERR;
else if (port_state == IB_PORT_ACTIVE)
ibev.event = IB_EVENT_PORT_ACTIVE;
else
return NOTIFY_DONE;

ibev.element.port_num = 1;
ib_dispatch_event(&ibev);
}
Expand Down Expand Up @@ -3793,6 +3821,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
err = mlx5_enable_eth(dev);
if (err)
goto err_free_port;
dev->roce.last_port_state = IB_PORT_DOWN;
}

err = create_dev_resources(&dev->devr);
Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/hw/mlx5/mlx5_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ struct mlx5_roce {
struct net_device *netdev;
struct notifier_block nb;
atomic_t next_port;
enum ib_port_state last_port_state;
};

struct mlx5_ib_dev {
Expand Down

0 comments on commit fd65f1b

Please sign in to comment.