Skip to content

Commit 951d01b

Browse files
committed
IB/mlx5: Fix how advise_mr() launches async work
Work must hold a kref on the ib_device otherwise the dev pointer can become free before the work runs. This can happen because the work is being pushed onto the system work queue which is not flushed during driver unregister. Remove the bogus use of 'reg_state': - While in uverbs the reg_state is guaranteed to always be REGISTERED - Testing reg_state with no locking is bogus. Use ib_device_try_get() to get back into a region that prevents unregistration. For now continue with a flow that is similar to the existing code. Fixes: 813e90b ("IB/mlx5: Add advise_mr() support") Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> Reviewed-by: Moni Shoua <monis@mellanox.com>
1 parent d79af72 commit 951d01b

File tree

1 file changed

+5
-5
lines changed
  • drivers/infiniband/hw/mlx5

1 file changed

+5
-5
lines changed

drivers/infiniband/hw/mlx5/odp.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
15951595
struct prefetch_mr_work *w =
15961596
container_of(work, struct prefetch_mr_work, work);
15971597

1598-
if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED)
1598+
if (ib_device_try_get(&w->dev->ib_dev)) {
15991599
mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
16001600
w->num_sge);
1601-
1601+
ib_device_put(&w->dev->ib_dev);
1602+
}
1603+
put_device(&w->dev->ib_dev.dev);
16021604
kfree(w);
16031605
}
16041606

@@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
16171619
return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
16181620
num_sge);
16191621

1620-
if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
1621-
return -ENODEV;
1622-
16231622
work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
16241623
if (!work)
16251624
return -ENOMEM;
16261625

16271626
memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
16281627

1628+
get_device(&dev->ib_dev.dev);
16291629
work->dev = dev;
16301630
work->pf_flags = pf_flags;
16311631
work->num_sge = num_sge;

0 commit comments

Comments
 (0)