Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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
  • Loading branch information
torvalds committed Feb 16, 2020
2 parents b719ae0 + 685eff5 commit 54654e1
Show file tree
Hide file tree
Showing 17 changed files with 172 additions and 125 deletions.
24 changes: 9 additions & 15 deletions drivers/infiniband/core/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,22 +339,16 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp,
if (!new_pps)
return NULL;

if (qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) {
if (!qp_pps) {
new_pps->main.port_num = qp_attr->port_num;
new_pps->main.pkey_index = qp_attr->pkey_index;
} else {
new_pps->main.port_num = (qp_attr_mask & IB_QP_PORT) ?
qp_attr->port_num :
qp_pps->main.port_num;

new_pps->main.pkey_index =
(qp_attr_mask & IB_QP_PKEY_INDEX) ?
qp_attr->pkey_index :
qp_pps->main.pkey_index;
}
if (qp_attr_mask & IB_QP_PORT)
new_pps->main.port_num =
(qp_pps) ? qp_pps->main.port_num : qp_attr->port_num;
if (qp_attr_mask & IB_QP_PKEY_INDEX)
new_pps->main.pkey_index = (qp_pps) ? qp_pps->main.pkey_index :
qp_attr->pkey_index;
if ((qp_attr_mask & IB_QP_PKEY_INDEX) && (qp_attr_mask & IB_QP_PORT))
new_pps->main.state = IB_PORT_PKEY_VALID;
} else if (qp_pps) {

if (!(qp_attr_mask & (IB_QP_PKEY_INDEX || IB_QP_PORT)) && qp_pps) {
new_pps->main.port_num = qp_pps->main.port_num;
new_pps->main.pkey_index = qp_pps->main.pkey_index;
if (qp_pps->main.state != IB_PORT_PKEY_NOT_VALID)
Expand Down
5 changes: 3 additions & 2 deletions drivers/infiniband/core/user_mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,9 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
struct ib_umad_file *file;
int id;

cdev_device_del(&port->sm_cdev, &port->sm_dev);
cdev_device_del(&port->cdev, &port->dev);

mutex_lock(&port->file_mutex);

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

mutex_unlock(&port->file_mutex);

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

/* balances device_initialize() */
Expand Down
15 changes: 7 additions & 8 deletions drivers/infiniband/core/uverbs_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2745,12 +2745,6 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
return 0;
}

static size_t kern_spec_filter_sz(const struct ib_uverbs_flow_spec_hdr *spec)
{
/* Returns user space filter size, includes padding */
return (spec->size - sizeof(struct ib_uverbs_flow_spec_hdr)) / 2;
}

static ssize_t spec_filter_size(const void *kern_spec_filter, u16 kern_filter_size,
u16 ib_real_filter_sz)
{
Expand Down Expand Up @@ -2894,11 +2888,16 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
static int kern_spec_to_ib_spec_filter(struct ib_uverbs_flow_spec *kern_spec,
union ib_flow_spec *ib_spec)
{
ssize_t kern_filter_sz;
size_t kern_filter_sz;
void *kern_spec_mask;
void *kern_spec_val;

kern_filter_sz = kern_spec_filter_sz(&kern_spec->hdr);
if (check_sub_overflow((size_t)kern_spec->hdr.size,
sizeof(struct ib_uverbs_flow_spec_hdr),
&kern_filter_sz))
return -EINVAL;

kern_filter_sz /= 2;

kern_spec_val = (void *)kern_spec +
sizeof(struct ib_uverbs_flow_spec_hdr);
Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/core/uverbs_std_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue)
list_for_each_entry_safe(entry, tmp, &event_queue->event_list, list) {
if (entry->counter)
list_del(&entry->obj_list);
list_del(&entry->list);
kfree(entry);
}
spin_unlock_irq(&event_queue->lock);
Expand Down
4 changes: 4 additions & 0 deletions drivers/infiniband/hw/cxgb4/cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3036,6 +3036,10 @@ static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
}

/* As per draft-hilland-iwarp-verbs-v1.0, sec 6.2.3,
* when entering the TERM state the RNIC MUST initiate a CLOSE.
*/
c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
c4iw_put_ep(&ep->com);
} else
pr_warn("TERM received tid %u no ep/qp\n", tid);
Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/hw/cxgb4/qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1948,10 +1948,10 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
qhp->attr.layer_etype = attrs->layer_etype;
qhp->attr.ecode = attrs->ecode;
ep = qhp->ep;
c4iw_get_ep(&ep->com);
disconnect = 1;
if (!internal) {
c4iw_get_ep(&ep->com);
terminate = 1;
disconnect = 1;
} else {
terminate = qhp->attr.send_term;
ret = rdma_fini(rhp, qhp, ep);
Expand Down
2 changes: 2 additions & 0 deletions drivers/infiniband/hw/hfi1/affinity.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@ static int _dev_comp_vect_mappings_create(struct hfi1_devdata *dd,
rvt_get_ibdev_name(&(dd)->verbs_dev.rdi), i, cpu);
}

free_cpumask_var(available_cpus);
free_cpumask_var(non_intr_cpus);
return 0;

fail:
Expand Down
52 changes: 32 additions & 20 deletions drivers/infiniband/hw/hfi1/file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,24 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)

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

if (fd) {
fd->rec_cpu_num = -1; /* no cpu affinity by default */
fd->mm = current->mm;
mmgrab(fd->mm);
fd->dd = dd;
kobject_get(&fd->dd->kobj);
fp->private_data = fd;
} else {
fp->private_data = NULL;

if (atomic_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp);

return -ENOMEM;
}

if (!fd || init_srcu_struct(&fd->pq_srcu))
goto nomem;
spin_lock_init(&fd->pq_rcu_lock);
spin_lock_init(&fd->tid_lock);
spin_lock_init(&fd->invalid_lock);
fd->rec_cpu_num = -1; /* no cpu affinity by default */
fd->mm = current->mm;
mmgrab(fd->mm);
fd->dd = dd;
kobject_get(&fd->dd->kobj);
fp->private_data = fd;
return 0;
nomem:
kfree(fd);
fp->private_data = NULL;
if (atomic_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp);
return -ENOMEM;
}

static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
Expand Down Expand Up @@ -301,21 +302,30 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
{
struct hfi1_filedata *fd = kiocb->ki_filp->private_data;
struct hfi1_user_sdma_pkt_q *pq = fd->pq;
struct hfi1_user_sdma_pkt_q *pq;
struct hfi1_user_sdma_comp_q *cq = fd->cq;
int done = 0, reqs = 0;
unsigned long dim = from->nr_segs;
int idx;

if (!cq || !pq)
idx = srcu_read_lock(&fd->pq_srcu);
pq = srcu_dereference(fd->pq, &fd->pq_srcu);
if (!cq || !pq) {
srcu_read_unlock(&fd->pq_srcu, idx);
return -EIO;
}

if (!iter_is_iovec(from) || !dim)
if (!iter_is_iovec(from) || !dim) {
srcu_read_unlock(&fd->pq_srcu, idx);
return -EINVAL;
}

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

if (atomic_read(&pq->n_reqs) == pq->n_max_reqs)
if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) {
srcu_read_unlock(&fd->pq_srcu, idx);
return -ENOSPC;
}

while (dim) {
int ret;
Expand All @@ -333,6 +343,7 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
reqs++;
}

srcu_read_unlock(&fd->pq_srcu, idx);
return reqs;
}

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

cleanup_srcu_struct(&fdata->pq_srcu);
kfree(fdata);
return 0;
}
Expand Down
5 changes: 4 additions & 1 deletion drivers/infiniband/hw/hfi1/hfi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1444,10 +1444,13 @@ struct mmu_rb_handler;

/* Private data for file operations */
struct hfi1_filedata {
struct srcu_struct pq_srcu;
struct hfi1_devdata *dd;
struct hfi1_ctxtdata *uctxt;
struct hfi1_user_sdma_comp_q *cq;
struct hfi1_user_sdma_pkt_q *pq;
/* update side lock for SRCU */
spinlock_t pq_rcu_lock;
struct hfi1_user_sdma_pkt_q __rcu *pq;
u16 subctxt;
/* for cpu affinity; -1 if none */
int rec_cpu_num;
Expand Down
5 changes: 2 additions & 3 deletions drivers/infiniband/hw/hfi1/user_exp_rcv.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ int hfi1_user_exp_rcv_init(struct hfi1_filedata *fd,
{
int ret = 0;

spin_lock_init(&fd->tid_lock);
spin_lock_init(&fd->invalid_lock);

fd->entry_to_rb = kcalloc(uctxt->expected_count,
sizeof(struct rb_node *),
GFP_KERNEL);
Expand Down Expand Up @@ -142,10 +139,12 @@ void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd)
{
struct hfi1_ctxtdata *uctxt = fd->uctxt;

mutex_lock(&uctxt->exp_mutex);
if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list))
unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd);
if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list))
unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd);
mutex_unlock(&uctxt->exp_mutex);

kfree(fd->invalid_tids);
fd->invalid_tids = NULL;
Expand Down
17 changes: 12 additions & 5 deletions drivers/infiniband/hw/hfi1/user_sdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
pq = kzalloc(sizeof(*pq), GFP_KERNEL);
if (!pq)
return -ENOMEM;

pq->dd = dd;
pq->ctxt = uctxt->ctxt;
pq->subctxt = fd->subctxt;
Expand Down Expand Up @@ -236,7 +235,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
goto pq_mmu_fail;
}

fd->pq = pq;
rcu_assign_pointer(fd->pq, pq);
fd->cq = cq;

return 0;
Expand Down Expand Up @@ -264,8 +263,14 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,

trace_hfi1_sdma_user_free_queues(uctxt->dd, uctxt->ctxt, fd->subctxt);

pq = fd->pq;
spin_lock(&fd->pq_rcu_lock);
pq = srcu_dereference_check(fd->pq, &fd->pq_srcu,
lockdep_is_held(&fd->pq_rcu_lock));
if (pq) {
rcu_assign_pointer(fd->pq, NULL);
spin_unlock(&fd->pq_rcu_lock);
synchronize_srcu(&fd->pq_srcu);
/* at this point there can be no more new requests */
if (pq->handler)
hfi1_mmu_rb_unregister(pq->handler);
iowait_sdma_drain(&pq->busy);
Expand All @@ -277,7 +282,8 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
kfree(pq->req_in_use);
kmem_cache_destroy(pq->txreq_cache);
kfree(pq);
fd->pq = NULL;
} else {
spin_unlock(&fd->pq_rcu_lock);
}
if (fd->cq) {
vfree(fd->cq->comps);
Expand Down Expand Up @@ -321,7 +327,8 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
{
int ret = 0, i;
struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_user_sdma_pkt_q *pq = fd->pq;
struct hfi1_user_sdma_pkt_q *pq =
srcu_dereference(fd->pq, &fd->pq_srcu);
struct hfi1_user_sdma_comp_q *cq = fd->cq;
struct hfi1_devdata *dd = pq->dd;
unsigned long idx = 0;
Expand Down
Loading

0 comments on commit 54654e1

Please sign in to comment.