Skip to content

Commit 54654e1

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: "Not too much going on here, though there are about four fixes related to stuff merged during the last merge window. We also see the return of a syzkaller instance with access to RDMA devices, and a few bugs detected by that squished. - Fix three crashers and a memory memory leak for HFI1 - Several bugs found by syzkaller - A bug fix for the recent QP counters feature on older mlx5 HW - Locking inversion in cxgb4 - Unnecessary WARN_ON in siw - A umad crasher regression during unload, from a bug fix for something else - Bugs introduced in the merge window: - Missed list_del in uverbs file rework, core and mlx5 devx - Unexpected integer math truncation in the mlx5 VAR patches - Compilation bug fix for the VAR patches on 32 bit" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: IB/mlx5: Use div64_u64 for num_var_hw_entries calculation RDMA/core: Fix protection fault in get_pkey_idx_qp_list RDMA/rxe: Fix soft lockup problem due to using tasklets in softirq RDMA/mlx5: Prevent overflow in mmap offset calculations IB/umad: Fix kernel crash while unloading ib_umad RDMA/mlx5: Fix async events cleanup flows RDMA/core: Add missing list deletion on freeing event queue RDMA/siw: Remove unwanted WARN_ON in siw_cm_llp_data_ready() RDMA/iw_cxgb4: initiate CLOSE when entering TERM IB/mlx5: Return failure when rts2rts_qp_counters_set_id is not supported RDMA/core: Fix invalid memory access in spec_filter_size IB/rdmavt: Reset all QPs when the device is shut down IB/hfi1: Close window for pq and request coliding IB/hfi1: Acquire lock to release TID entries when user file is closed RDMA/hfi1: Fix memory leak in _dev_comp_vect_mappings_create
2 parents b719ae0 + 685eff5 commit 54654e1

File tree

17 files changed

+172
-125
lines changed

17 files changed

+172
-125
lines changed

drivers/infiniband/core/security.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -339,22 +339,16 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp,
339339
if (!new_pps)
340340
return NULL;
341341

342-
if (qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) {
343-
if (!qp_pps) {
344-
new_pps->main.port_num = qp_attr->port_num;
345-
new_pps->main.pkey_index = qp_attr->pkey_index;
346-
} else {
347-
new_pps->main.port_num = (qp_attr_mask & IB_QP_PORT) ?
348-
qp_attr->port_num :
349-
qp_pps->main.port_num;
350-
351-
new_pps->main.pkey_index =
352-
(qp_attr_mask & IB_QP_PKEY_INDEX) ?
353-
qp_attr->pkey_index :
354-
qp_pps->main.pkey_index;
355-
}
342+
if (qp_attr_mask & IB_QP_PORT)
343+
new_pps->main.port_num =
344+
(qp_pps) ? qp_pps->main.port_num : qp_attr->port_num;
345+
if (qp_attr_mask & IB_QP_PKEY_INDEX)
346+
new_pps->main.pkey_index = (qp_pps) ? qp_pps->main.pkey_index :
347+
qp_attr->pkey_index;
348+
if ((qp_attr_mask & IB_QP_PKEY_INDEX) && (qp_attr_mask & IB_QP_PORT))
356349
new_pps->main.state = IB_PORT_PKEY_VALID;
357-
} else if (qp_pps) {
350+
351+
if (!(qp_attr_mask & (IB_QP_PKEY_INDEX || IB_QP_PORT)) && qp_pps) {
358352
new_pps->main.port_num = qp_pps->main.port_num;
359353
new_pps->main.pkey_index = qp_pps->main.pkey_index;
360354
if (qp_pps->main.state != IB_PORT_PKEY_NOT_VALID)

drivers/infiniband/core/user_mad.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,9 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
13121312
struct ib_umad_file *file;
13131313
int id;
13141314

1315+
cdev_device_del(&port->sm_cdev, &port->sm_dev);
1316+
cdev_device_del(&port->cdev, &port->dev);
1317+
13151318
mutex_lock(&port->file_mutex);
13161319

13171320
/* Mark ib_dev NULL and block ioctl or other file ops to progress
@@ -1331,8 +1334,6 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
13311334

13321335
mutex_unlock(&port->file_mutex);
13331336

1334-
cdev_device_del(&port->sm_cdev, &port->sm_dev);
1335-
cdev_device_del(&port->cdev, &port->dev);
13361337
ida_free(&umad_ida, port->dev_num);
13371338

13381339
/* balances device_initialize() */

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,12 +2745,6 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
27452745
return 0;
27462746
}
27472747

2748-
static size_t kern_spec_filter_sz(const struct ib_uverbs_flow_spec_hdr *spec)
2749-
{
2750-
/* Returns user space filter size, includes padding */
2751-
return (spec->size - sizeof(struct ib_uverbs_flow_spec_hdr)) / 2;
2752-
}
2753-
27542748
static ssize_t spec_filter_size(const void *kern_spec_filter, u16 kern_filter_size,
27552749
u16 ib_real_filter_sz)
27562750
{
@@ -2894,11 +2888,16 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
28942888
static int kern_spec_to_ib_spec_filter(struct ib_uverbs_flow_spec *kern_spec,
28952889
union ib_flow_spec *ib_spec)
28962890
{
2897-
ssize_t kern_filter_sz;
2891+
size_t kern_filter_sz;
28982892
void *kern_spec_mask;
28992893
void *kern_spec_val;
29002894

2901-
kern_filter_sz = kern_spec_filter_sz(&kern_spec->hdr);
2895+
if (check_sub_overflow((size_t)kern_spec->hdr.size,
2896+
sizeof(struct ib_uverbs_flow_spec_hdr),
2897+
&kern_filter_sz))
2898+
return -EINVAL;
2899+
2900+
kern_filter_sz /= 2;
29022901

29032902
kern_spec_val = (void *)kern_spec +
29042903
sizeof(struct ib_uverbs_flow_spec_hdr);

drivers/infiniband/core/uverbs_std_types.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue)
220220
list_for_each_entry_safe(entry, tmp, &event_queue->event_list, list) {
221221
if (entry->counter)
222222
list_del(&entry->obj_list);
223+
list_del(&entry->list);
223224
kfree(entry);
224225
}
225226
spin_unlock_irq(&event_queue->lock);

drivers/infiniband/hw/cxgb4/cm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,6 +3036,10 @@ static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
30363036
C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
30373037
}
30383038

3039+
/* As per draft-hilland-iwarp-verbs-v1.0, sec 6.2.3,
3040+
* when entering the TERM state the RNIC MUST initiate a CLOSE.
3041+
*/
3042+
c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
30393043
c4iw_put_ep(&ep->com);
30403044
} else
30413045
pr_warn("TERM received tid %u no ep/qp\n", tid);

drivers/infiniband/hw/cxgb4/qp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,10 +1948,10 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
19481948
qhp->attr.layer_etype = attrs->layer_etype;
19491949
qhp->attr.ecode = attrs->ecode;
19501950
ep = qhp->ep;
1951-
c4iw_get_ep(&ep->com);
1952-
disconnect = 1;
19531951
if (!internal) {
1952+
c4iw_get_ep(&ep->com);
19541953
terminate = 1;
1954+
disconnect = 1;
19551955
} else {
19561956
terminate = qhp->attr.send_term;
19571957
ret = rdma_fini(rhp, qhp, ep);

drivers/infiniband/hw/hfi1/affinity.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ static int _dev_comp_vect_mappings_create(struct hfi1_devdata *dd,
479479
rvt_get_ibdev_name(&(dd)->verbs_dev.rdi), i, cpu);
480480
}
481481

482+
free_cpumask_var(available_cpus);
483+
free_cpumask_var(non_intr_cpus);
482484
return 0;
483485

484486
fail:

drivers/infiniband/hw/hfi1/file_ops.c

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -200,23 +200,24 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
200200

201201
fd = kzalloc(sizeof(*fd), GFP_KERNEL);
202202

203-
if (fd) {
204-
fd->rec_cpu_num = -1; /* no cpu affinity by default */
205-
fd->mm = current->mm;
206-
mmgrab(fd->mm);
207-
fd->dd = dd;
208-
kobject_get(&fd->dd->kobj);
209-
fp->private_data = fd;
210-
} else {
211-
fp->private_data = NULL;
212-
213-
if (atomic_dec_and_test(&dd->user_refcount))
214-
complete(&dd->user_comp);
215-
216-
return -ENOMEM;
217-
}
218-
203+
if (!fd || init_srcu_struct(&fd->pq_srcu))
204+
goto nomem;
205+
spin_lock_init(&fd->pq_rcu_lock);
206+
spin_lock_init(&fd->tid_lock);
207+
spin_lock_init(&fd->invalid_lock);
208+
fd->rec_cpu_num = -1; /* no cpu affinity by default */
209+
fd->mm = current->mm;
210+
mmgrab(fd->mm);
211+
fd->dd = dd;
212+
kobject_get(&fd->dd->kobj);
213+
fp->private_data = fd;
219214
return 0;
215+
nomem:
216+
kfree(fd);
217+
fp->private_data = NULL;
218+
if (atomic_dec_and_test(&dd->user_refcount))
219+
complete(&dd->user_comp);
220+
return -ENOMEM;
220221
}
221222

222223
static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
@@ -301,21 +302,30 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
301302
static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
302303
{
303304
struct hfi1_filedata *fd = kiocb->ki_filp->private_data;
304-
struct hfi1_user_sdma_pkt_q *pq = fd->pq;
305+
struct hfi1_user_sdma_pkt_q *pq;
305306
struct hfi1_user_sdma_comp_q *cq = fd->cq;
306307
int done = 0, reqs = 0;
307308
unsigned long dim = from->nr_segs;
309+
int idx;
308310

309-
if (!cq || !pq)
311+
idx = srcu_read_lock(&fd->pq_srcu);
312+
pq = srcu_dereference(fd->pq, &fd->pq_srcu);
313+
if (!cq || !pq) {
314+
srcu_read_unlock(&fd->pq_srcu, idx);
310315
return -EIO;
316+
}
311317

312-
if (!iter_is_iovec(from) || !dim)
318+
if (!iter_is_iovec(from) || !dim) {
319+
srcu_read_unlock(&fd->pq_srcu, idx);
313320
return -EINVAL;
321+
}
314322

315323
trace_hfi1_sdma_request(fd->dd, fd->uctxt->ctxt, fd->subctxt, dim);
316324

317-
if (atomic_read(&pq->n_reqs) == pq->n_max_reqs)
325+
if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) {
326+
srcu_read_unlock(&fd->pq_srcu, idx);
318327
return -ENOSPC;
328+
}
319329

320330
while (dim) {
321331
int ret;
@@ -333,6 +343,7 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
333343
reqs++;
334344
}
335345

346+
srcu_read_unlock(&fd->pq_srcu, idx);
336347
return reqs;
337348
}
338349

@@ -707,6 +718,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
707718
if (atomic_dec_and_test(&dd->user_refcount))
708719
complete(&dd->user_comp);
709720

721+
cleanup_srcu_struct(&fdata->pq_srcu);
710722
kfree(fdata);
711723
return 0;
712724
}

drivers/infiniband/hw/hfi1/hfi.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1444,10 +1444,13 @@ struct mmu_rb_handler;
14441444

14451445
/* Private data for file operations */
14461446
struct hfi1_filedata {
1447+
struct srcu_struct pq_srcu;
14471448
struct hfi1_devdata *dd;
14481449
struct hfi1_ctxtdata *uctxt;
14491450
struct hfi1_user_sdma_comp_q *cq;
1450-
struct hfi1_user_sdma_pkt_q *pq;
1451+
/* update side lock for SRCU */
1452+
spinlock_t pq_rcu_lock;
1453+
struct hfi1_user_sdma_pkt_q __rcu *pq;
14511454
u16 subctxt;
14521455
/* for cpu affinity; -1 if none */
14531456
int rec_cpu_num;

drivers/infiniband/hw/hfi1/user_exp_rcv.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ int hfi1_user_exp_rcv_init(struct hfi1_filedata *fd,
8787
{
8888
int ret = 0;
8989

90-
spin_lock_init(&fd->tid_lock);
91-
spin_lock_init(&fd->invalid_lock);
92-
9390
fd->entry_to_rb = kcalloc(uctxt->expected_count,
9491
sizeof(struct rb_node *),
9592
GFP_KERNEL);
@@ -142,10 +139,12 @@ void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd)
142139
{
143140
struct hfi1_ctxtdata *uctxt = fd->uctxt;
144141

142+
mutex_lock(&uctxt->exp_mutex);
145143
if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list))
146144
unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd);
147145
if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list))
148146
unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd);
147+
mutex_unlock(&uctxt->exp_mutex);
149148

150149
kfree(fd->invalid_tids);
151150
fd->invalid_tids = NULL;

0 commit comments

Comments
 (0)