Skip to content

Commit d69a24e

Browse files
Daniel Jurgensjgunthorpe
authored andcommitted
IB/mlx5: Move IB event processing onto a workqueue
Because mlx5_ib_event can be called from atomic context move event handling onto a workqueue. A mutex lock is required to get the IB device for slave ports, so move event processing onto a work queue. When an IB event is received, check if the mlx5_core_dev is a slave port, if so attempt to get the IB device it's affiliated with. If found process the event for that device, otherwise return. Signed-off-by: Daniel Jurgens <[email protected]> Reviewed-by: Parav Pandit <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 32f69e4 commit d69a24e

File tree

1 file changed

+56
-13
lines changed
  • drivers/infiniband/hw/mlx5

1 file changed

+56
-13
lines changed

drivers/infiniband/hw/mlx5/main.c

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,19 @@ static char mlx5_version[] =
7070
DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v"
7171
DRIVER_VERSION "\n";
7272

73+
struct mlx5_ib_event_work {
74+
struct work_struct work;
75+
struct mlx5_core_dev *dev;
76+
void *context;
77+
enum mlx5_dev_event event;
78+
unsigned long param;
79+
};
80+
7381
enum {
7482
MLX5_ATOMIC_SIZE_QP_8BYTES = 1 << 3,
7583
};
7684

85+
static struct workqueue_struct *mlx5_ib_event_wq;
7786
static LIST_HEAD(mlx5_ib_unaffiliated_port_list);
7887
static LIST_HEAD(mlx5_ib_dev_list);
7988
/*
@@ -3132,15 +3141,24 @@ static void delay_drop_handler(struct work_struct *work)
31323141
mutex_unlock(&delay_drop->lock);
31333142
}
31343143

3135-
static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
3136-
enum mlx5_dev_event event, unsigned long param)
3144+
static void mlx5_ib_handle_event(struct work_struct *_work)
31373145
{
3138-
struct mlx5_ib_dev *ibdev = (struct mlx5_ib_dev *)context;
3146+
struct mlx5_ib_event_work *work =
3147+
container_of(_work, struct mlx5_ib_event_work, work);
3148+
struct mlx5_ib_dev *ibdev;
31393149
struct ib_event ibev;
31403150
bool fatal = false;
31413151
u8 port = 0;
31423152

3143-
switch (event) {
3153+
if (mlx5_core_is_mp_slave(work->dev)) {
3154+
ibdev = mlx5_ib_get_ibdev_from_mpi(work->context);
3155+
if (!ibdev)
3156+
goto out;
3157+
} else {
3158+
ibdev = work->context;
3159+
}
3160+
3161+
switch (work->event) {
31443162
case MLX5_DEV_EVENT_SYS_ERROR:
31453163
ibev.event = IB_EVENT_DEVICE_FATAL;
31463164
mlx5_ib_handle_internal_error(ibdev);
@@ -3150,39 +3168,39 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
31503168
case MLX5_DEV_EVENT_PORT_UP:
31513169
case MLX5_DEV_EVENT_PORT_DOWN:
31523170
case MLX5_DEV_EVENT_PORT_INITIALIZED:
3153-
port = (u8)param;
3171+
port = (u8)work->param;
31543172

31553173
/* In RoCE, port up/down events are handled in
31563174
* mlx5_netdev_event().
31573175
*/
31583176
if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==
31593177
IB_LINK_LAYER_ETHERNET)
3160-
return;
3178+
goto out;
31613179

3162-
ibev.event = (event == MLX5_DEV_EVENT_PORT_UP) ?
3180+
ibev.event = (work->event == MLX5_DEV_EVENT_PORT_UP) ?
31633181
IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
31643182
break;
31653183

31663184
case MLX5_DEV_EVENT_LID_CHANGE:
31673185
ibev.event = IB_EVENT_LID_CHANGE;
3168-
port = (u8)param;
3186+
port = (u8)work->param;
31693187
break;
31703188

31713189
case MLX5_DEV_EVENT_PKEY_CHANGE:
31723190
ibev.event = IB_EVENT_PKEY_CHANGE;
3173-
port = (u8)param;
3191+
port = (u8)work->param;
31743192

31753193
schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work);
31763194
break;
31773195

31783196
case MLX5_DEV_EVENT_GUID_CHANGE:
31793197
ibev.event = IB_EVENT_GID_CHANGE;
3180-
port = (u8)param;
3198+
port = (u8)work->param;
31813199
break;
31823200

31833201
case MLX5_DEV_EVENT_CLIENT_REREG:
31843202
ibev.event = IB_EVENT_CLIENT_REREGISTER;
3185-
port = (u8)param;
3203+
port = (u8)work->param;
31863204
break;
31873205
case MLX5_DEV_EVENT_DELAY_DROP_TIMEOUT:
31883206
schedule_work(&ibdev->delay_drop.delay_drop_work);
@@ -3204,9 +3222,29 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
32043222

32053223
if (fatal)
32063224
ibdev->ib_active = false;
3207-
32083225
out:
3209-
return;
3226+
kfree(work);
3227+
}
3228+
3229+
static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
3230+
enum mlx5_dev_event event, unsigned long param)
3231+
{
3232+
struct mlx5_ib_event_work *work;
3233+
3234+
work = kmalloc(sizeof(*work), GFP_ATOMIC);
3235+
if (work) {
3236+
INIT_WORK(&work->work, mlx5_ib_handle_event);
3237+
work->dev = dev;
3238+
work->param = param;
3239+
work->context = context;
3240+
work->event = event;
3241+
3242+
queue_work(mlx5_ib_event_wq, &work->work);
3243+
return;
3244+
}
3245+
3246+
dev_warn(&dev->pdev->dev, "%s: mlx5_dev_event: %d, with param: %lu dropped, couldn't allocate memory.\n",
3247+
__func__, event, param);
32103248
}
32113249

32123250
static int set_has_smi_cap(struct mlx5_ib_dev *dev)
@@ -4917,6 +4955,10 @@ static int __init mlx5_ib_init(void)
49174955
{
49184956
int err;
49194957

4958+
mlx5_ib_event_wq = alloc_ordered_workqueue("mlx5_ib_event_wq", 0);
4959+
if (!mlx5_ib_event_wq)
4960+
return -ENOMEM;
4961+
49204962
mlx5_ib_odp_init();
49214963

49224964
err = mlx5_register_interface(&mlx5_ib_interface);
@@ -4927,6 +4969,7 @@ static int __init mlx5_ib_init(void)
49274969
static void __exit mlx5_ib_cleanup(void)
49284970
{
49294971
mlx5_unregister_interface(&mlx5_ib_interface);
4972+
destroy_workqueue(mlx5_ib_event_wq);
49304973
}
49314974

49324975
module_init(mlx5_ib_init);

0 commit comments

Comments
 (0)