Skip to content

Commit 5eeb633

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes from Jason Gunthorpe: "Still not much going on, the usual set of oops and driver fixes this time: - Fix two uapi breakage regressions in mlx5 drivers - Various oops fixes in hfi1, mlx4, umem, uverbs, and ipoib - A protocol bug fix for hfi1 preventing it from implementing the verbs API properly, and a compatability fix for EXEC STACK user programs - Fix missed refcounting in the 'advise_mr' patches merged this cycle. - Fix wrong use of the uABI in the hns SRQ patches merged this cycle" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: IB/uverbs: Fix OOPs in uverbs_user_mmap_disassociate IB/ipoib: Fix for use-after-free in ipoib_cm_tx_start IB/uverbs: Fix ioctl query port to consider device disassociation RDMA/mlx5: Fix flow creation on representors IB/uverbs: Fix OOPs upon device disassociation RDMA/umem: Add missing initialization of owning_mm RDMA/hns: Update the kernel header file of hns IB/mlx5: Fix how advise_mr() launches async work RDMA/device: Expose ib_device_try_get(() IB/hfi1: Add limit test for RC/UC send via loopback IB/hfi1: Remove overly conservative VM_EXEC flag check IB/{hfi1, qib}: Fix WC.byte_len calculation for UD_SEND_WITH_IMM IB/mlx4: Fix using wrong function to destroy sqp AHs under SRIOV RDMA/mlx5: Fix check for supported user flags when creating a QP
2 parents 9ace868 + 7b21b69 commit 5eeb633

File tree

18 files changed

+97
-42
lines changed

18 files changed

+97
-42
lines changed

drivers/infiniband/core/core_priv.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
267267
#endif
268268

269269
struct ib_device *ib_device_get_by_index(u32 ifindex);
270-
void ib_device_put(struct ib_device *device);
271270
/* RDMA device netlink */
272271
void nldev_init(void);
273272
void nldev_exit(void);

drivers/infiniband/core/device.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index)
156156
down_read(&lists_rwsem);
157157
device = __ib_device_get_by_index(index);
158158
if (device) {
159-
/* Do not return a device if unregistration has started. */
160-
if (!refcount_inc_not_zero(&device->refcount))
159+
if (!ib_device_try_get(device))
161160
device = NULL;
162161
}
163162
up_read(&lists_rwsem);
164163
return device;
165164
}
166165

166+
/**
167+
* ib_device_put - Release IB device reference
168+
* @device: device whose reference to be released
169+
*
170+
* ib_device_put() releases reference to the IB device to allow it to be
171+
* unregistered and eventually free.
172+
*/
167173
void ib_device_put(struct ib_device *device)
168174
{
169175
if (refcount_dec_and_test(&device->refcount))
170176
complete(&device->unreg_completion);
171177
}
178+
EXPORT_SYMBOL(ib_device_put);
172179

173180
static struct ib_device *__ib_device_get_by_name(const char *name)
174181
{
@@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size)
303310
rwlock_init(&device->client_data_lock);
304311
INIT_LIST_HEAD(&device->client_data_list);
305312
INIT_LIST_HEAD(&device->port_list);
306-
refcount_set(&device->refcount, 1);
307313
init_completion(&device->unreg_completion);
308314

309315
return device;
@@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name,
620626
goto cg_cleanup;
621627
}
622628

629+
refcount_set(&device->refcount, 1);
623630
device->reg_state = IB_DEV_REGISTERED;
624631

625632
list_for_each_entry(client, &client_list, list)

drivers/infiniband/core/umem_odp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
352352
umem->writable = 1;
353353
umem->is_odp = 1;
354354
odp_data->per_mm = per_mm;
355+
umem->owning_mm = per_mm->mm;
356+
mmgrab(umem->owning_mm);
355357

356358
mutex_init(&odp_data->umem_mutex);
357359
init_completion(&odp_data->notifier_completion);
@@ -384,6 +386,7 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
384386
out_page_list:
385387
vfree(odp_data->page_list);
386388
out_odp_data:
389+
mmdrop(umem->owning_mm);
387390
kfree(odp_data);
388391
return ERR_PTR(ret);
389392
}

drivers/infiniband/core/uverbs_main.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ void ib_uverbs_release_file(struct kref *ref)
204204
if (atomic_dec_and_test(&file->device->refcount))
205205
ib_uverbs_comp_dev(file->device);
206206

207+
if (file->async_file)
208+
kref_put(&file->async_file->ref,
209+
ib_uverbs_release_async_event_file);
207210
put_device(&file->device->dev);
208211
kfree(file);
209212
}
@@ -964,11 +967,19 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
964967

965968
/* Get an arbitrary mm pointer that hasn't been cleaned yet */
966969
mutex_lock(&ufile->umap_lock);
967-
if (!list_empty(&ufile->umaps)) {
968-
mm = list_first_entry(&ufile->umaps,
969-
struct rdma_umap_priv, list)
970-
->vma->vm_mm;
971-
mmget(mm);
970+
while (!list_empty(&ufile->umaps)) {
971+
int ret;
972+
973+
priv = list_first_entry(&ufile->umaps,
974+
struct rdma_umap_priv, list);
975+
mm = priv->vma->vm_mm;
976+
ret = mmget_not_zero(mm);
977+
if (!ret) {
978+
list_del_init(&priv->list);
979+
mm = NULL;
980+
continue;
981+
}
982+
break;
972983
}
973984
mutex_unlock(&ufile->umap_lock);
974985
if (!mm)
@@ -1096,10 +1107,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
10961107
list_del_init(&file->list);
10971108
mutex_unlock(&file->device->lists_mutex);
10981109

1099-
if (file->async_file)
1100-
kref_put(&file->async_file->ref,
1101-
ib_uverbs_release_async_event_file);
1102-
11031110
kref_put(&file->ref, ib_uverbs_release_file);
11041111

11051112
return 0;

drivers/infiniband/core/uverbs_std_types_device.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,18 @@ void copy_port_attr_to_resp(struct ib_port_attr *attr,
168168
static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)(
169169
struct uverbs_attr_bundle *attrs)
170170
{
171-
struct ib_device *ib_dev = attrs->ufile->device->ib_dev;
171+
struct ib_device *ib_dev;
172172
struct ib_port_attr attr = {};
173173
struct ib_uverbs_query_port_resp_ex resp = {};
174+
struct ib_ucontext *ucontext;
174175
int ret;
175176
u8 port_num;
176177

178+
ucontext = ib_uverbs_get_ucontext(attrs);
179+
if (IS_ERR(ucontext))
180+
return PTR_ERR(ucontext);
181+
ib_dev = ucontext->device;
182+
177183
/* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
178184
if (!ib_dev->ops.query_port)
179185
return -EOPNOTSUPP;

drivers/infiniband/hw/hfi1/file_ops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
488488
vmf = 1;
489489
break;
490490
case STATUS:
491-
if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
491+
if (flags & VM_WRITE) {
492492
ret = -EPERM;
493493
goto done;
494494
}

drivers/infiniband/hw/hfi1/ud.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
987987
opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
988988
wc.ex.imm_data = packet->ohdr->u.ud.imm_data;
989989
wc.wc_flags = IB_WC_WITH_IMM;
990-
tlen -= sizeof(u32);
991990
} else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
992991
wc.ex.imm_data = 0;
993992
wc.wc_flags = 0;

drivers/infiniband/hw/hns/hns_roce_srq.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
210210
struct ib_udata *udata)
211211
{
212212
struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
213+
struct hns_roce_ib_create_srq_resp resp = {};
213214
struct hns_roce_srq *srq;
214215
int srq_desc_size;
215216
int srq_buf_size;
@@ -378,16 +379,21 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
378379

379380
srq->event = hns_roce_ib_srq_event;
380381
srq->ibsrq.ext.xrc.srq_num = srq->srqn;
382+
resp.srqn = srq->srqn;
381383

382384
if (udata) {
383-
if (ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) {
385+
if (ib_copy_to_udata(udata, &resp,
386+
min(udata->outlen, sizeof(resp)))) {
384387
ret = -EFAULT;
385-
goto err_wrid;
388+
goto err_srqc_alloc;
386389
}
387390
}
388391

389392
return &srq->ibsrq;
390393

394+
err_srqc_alloc:
395+
hns_roce_srq_free(hr_dev, srq);
396+
391397
err_wrid:
392398
kvfree(srq->wrid);
393399

drivers/infiniband/hw/mlx4/mad.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
14111411

14121412
sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
14131413
if (sqp->tx_ring[wire_tx_ix].ah)
1414-
rdma_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
1414+
mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
14151415
sqp->tx_ring[wire_tx_ix].ah = ah;
14161416
ib_dma_sync_single_for_cpu(&dev->ib_dev,
14171417
sqp->tx_ring[wire_tx_ix].buf.map,
@@ -1902,7 +1902,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
19021902
if (wc.status == IB_WC_SUCCESS) {
19031903
switch (wc.opcode) {
19041904
case IB_WC_SEND:
1905-
rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
1905+
mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
19061906
(MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
19071907
sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
19081908
= NULL;
@@ -1931,7 +1931,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
19311931
" status = %d, wrid = 0x%llx\n",
19321932
ctx->slave, wc.status, wc.wr_id);
19331933
if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
1934-
rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
1934+
mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
19351935
(MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
19361936
sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
19371937
= NULL;

drivers/infiniband/hw/mlx5/flow.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,8 +630,7 @@ const struct uapi_definition mlx5_ib_flow_defs[] = {
630630
UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
631631
UAPI_DEF_CHAIN_OBJ_TREE(
632632
UVERBS_OBJECT_FLOW,
633-
&mlx5_ib_fs,
634-
UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
633+
&mlx5_ib_fs),
635634
UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
636635
&mlx5_ib_flow_actions),
637636
{},

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;

drivers/infiniband/hw/mlx5/qp.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,14 +1912,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
19121912
}
19131913

19141914
if (!check_flags_mask(ucmd.flags,
1915+
MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
1916+
MLX5_QP_FLAG_BFREG_INDEX |
1917+
MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE |
1918+
MLX5_QP_FLAG_SCATTER_CQE |
19151919
MLX5_QP_FLAG_SIGNATURE |
1916-
MLX5_QP_FLAG_SCATTER_CQE |
1917-
MLX5_QP_FLAG_TUNNEL_OFFLOADS |
1918-
MLX5_QP_FLAG_BFREG_INDEX |
1919-
MLX5_QP_FLAG_TYPE_DCT |
1920-
MLX5_QP_FLAG_TYPE_DCI |
1921-
MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
1922-
MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE))
1920+
MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC |
1921+
MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC |
1922+
MLX5_QP_FLAG_TUNNEL_OFFLOADS |
1923+
MLX5_QP_FLAG_TYPE_DCI |
1924+
MLX5_QP_FLAG_TYPE_DCT))
19231925
return -EINVAL;
19241926

19251927
err = get_qp_user_index(to_mucontext(pd->uobject->context),

drivers/infiniband/hw/qib/qib_ud.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,6 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr,
512512
opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
513513
wc.ex.imm_data = ohdr->u.ud.imm_data;
514514
wc.wc_flags = IB_WC_WITH_IMM;
515-
tlen -= sizeof(u32);
516515
} else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
517516
wc.ex.imm_data = 0;
518517
wc.wc_flags = 0;

drivers/infiniband/sw/rdmavt/qp.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2910,6 +2910,8 @@ void rvt_ruc_loopback(struct rvt_qp *sqp)
29102910
goto op_err;
29112911
if (!ret)
29122912
goto rnr_nak;
2913+
if (wqe->length > qp->r_len)
2914+
goto inv_err;
29132915
break;
29142916

29152917
case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -3078,7 +3080,10 @@ void rvt_ruc_loopback(struct rvt_qp *sqp)
30783080
goto err;
30793081

30803082
inv_err:
3081-
send_status = IB_WC_REM_INV_REQ_ERR;
3083+
send_status =
3084+
sqp->ibqp.qp_type == IB_QPT_RC ?
3085+
IB_WC_REM_INV_REQ_ERR :
3086+
IB_WC_SUCCESS;
30823087
wc.status = IB_WC_LOC_QP_OP_ERR;
30833088
goto err;
30843089

drivers/infiniband/ulp/ipoib/ipoib.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ struct ipoib_cm_tx {
248248
struct list_head list;
249249
struct net_device *dev;
250250
struct ipoib_neigh *neigh;
251-
struct ipoib_path *path;
252251
struct ipoib_tx_buf *tx_ring;
253252
unsigned int tx_head;
254253
unsigned int tx_tail;

drivers/infiniband/ulp/ipoib/ipoib_cm.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,6 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path
13121312

13131313
neigh->cm = tx;
13141314
tx->neigh = neigh;
1315-
tx->path = path;
13161315
tx->dev = dev;
13171316
list_add(&tx->list, &priv->cm.start_list);
13181317
set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
@@ -1371,7 +1370,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
13711370
neigh->daddr + QPN_AND_OPTIONS_OFFSET);
13721371
goto free_neigh;
13731372
}
1374-
memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec));
1373+
memcpy(&pathrec, &path->pathrec, sizeof(pathrec));
13751374

13761375
spin_unlock_irqrestore(&priv->lock, flags);
13771376
netif_tx_unlock_bh(dev);

include/rdma/ib_verbs.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,9 +2579,10 @@ struct ib_device {
25792579

25802580
const struct uapi_definition *driver_def;
25812581
enum rdma_driver_id driver_id;
2582+
25822583
/*
2583-
* Provides synchronization between device unregistration and netlink
2584-
* commands on a device. To be used only by core.
2584+
* Positive refcount indicates that the device is currently
2585+
* registered and cannot be unregistered.
25852586
*/
25862587
refcount_t refcount;
25872588
struct completion unreg_completion;
@@ -3926,6 +3927,25 @@ static inline bool ib_access_writable(int access_flags)
39263927
int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
39273928
struct ib_mr_status *mr_status);
39283929

3930+
/**
3931+
* ib_device_try_get: Hold a registration lock
3932+
* device: The device to lock
3933+
*
3934+
* A device under an active registration lock cannot become unregistered. It
3935+
* is only possible to obtain a registration lock on a device that is fully
3936+
* registered, otherwise this function returns false.
3937+
*
3938+
* The registration lock is only necessary for actions which require the
3939+
* device to still be registered. Uses that only require the device pointer to
3940+
* be valid should use get_device(&ibdev->dev) to hold the memory.
3941+
*
3942+
*/
3943+
static inline bool ib_device_try_get(struct ib_device *dev)
3944+
{
3945+
return refcount_inc_not_zero(&dev->refcount);
3946+
}
3947+
3948+
void ib_device_put(struct ib_device *device);
39293949
struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port,
39303950
u16 pkey, const union ib_gid *gid,
39313951
const struct sockaddr *addr);

include/uapi/rdma/hns-abi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ struct hns_roce_ib_create_srq {
5252
__aligned_u64 que_addr;
5353
};
5454

55+
struct hns_roce_ib_create_srq_resp {
56+
__u32 srqn;
57+
__u32 reserved;
58+
};
59+
5560
struct hns_roce_ib_create_qp {
5661
__aligned_u64 buf_addr;
5762
__aligned_u64 db_addr;

0 commit comments

Comments
 (0)