Skip to content

Commit fd65f1b

Browse files
monis410dledford
authored andcommitted
IB/mlx5: Change logic for dispatching IB events for port state
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 <monis@mellanox.com> Reviewed-by: Noa Osherovich <noaos@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
1 parent 2c43c5a commit fd65f1b

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

drivers/infiniband/hw/mlx5/main.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ mlx5_ib_port_link_layer(struct ib_device *device, u8 port_num)
9898
return mlx5_port_type_cap_to_rdma_ll(port_type_cap);
9999
}
100100

101+
static int get_port_state(struct ib_device *ibdev,
102+
u8 port_num,
103+
enum ib_port_state *state)
104+
{
105+
struct ib_port_attr attr;
106+
int ret;
107+
108+
memset(&attr, 0, sizeof(attr));
109+
ret = mlx5_ib_query_port(ibdev, port_num, &attr);
110+
if (!ret)
111+
*state = attr.state;
112+
return ret;
113+
}
114+
101115
static int mlx5_netdev_event(struct notifier_block *this,
102116
unsigned long event, void *ptr)
103117
{
@@ -115,6 +129,7 @@ static int mlx5_netdev_event(struct notifier_block *this,
115129
write_unlock(&ibdev->roce.netdev_lock);
116130
break;
117131

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

148+
if (get_port_state(&ibdev->ib_dev, 1, &port_state))
149+
return NOTIFY_DONE;
150+
151+
if (ibdev->roce.last_port_state == port_state)
152+
return NOTIFY_DONE;
153+
154+
ibdev->roce.last_port_state = port_state;
132155
ibev.device = &ibdev->ib_dev;
133-
ibev.event = (event == NETDEV_UP) ?
134-
IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
156+
if (port_state == IB_PORT_DOWN)
157+
ibev.event = IB_EVENT_PORT_ERR;
158+
else if (port_state == IB_PORT_ACTIVE)
159+
ibev.event = IB_EVENT_PORT_ACTIVE;
160+
else
161+
return NOTIFY_DONE;
162+
135163
ibev.element.port_num = 1;
136164
ib_dispatch_event(&ibev);
137165
}
@@ -3793,6 +3821,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
37933821
err = mlx5_enable_eth(dev);
37943822
if (err)
37953823
goto err_free_port;
3824+
dev->roce.last_port_state = IB_PORT_DOWN;
37963825
}
37973826

37983827
err = create_dev_resources(&dev->devr);

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ struct mlx5_roce {
616616
struct net_device *netdev;
617617
struct notifier_block nb;
618618
atomic_t next_port;
619+
enum ib_port_state last_port_state;
619620
};
620621

621622
struct mlx5_ib_dev {

0 commit comments

Comments
 (0)