diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-20 18:22:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-20 18:22:30 -0400 |
commit | 1abd8a8f39cd9a2925149000056494523c85643a (patch) | |
tree | a205728bebc9ad149599a60781130540c3e568da | |
parent | d8894a08d91e230c5af9eed3de80114c5aaa3ccf (diff) | |
parent | 375dc53d032fc11e98036b5f228ad13f7c5933f5 (diff) |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes from Jason Gunthorpe:
"Here are eight fairly small fixes collected over the last two weeks.
Regression and crashing bug fixes:
- mlx4/5: Fixes for issues found from various checkers
- A resource tracking and uverbs regression in the core code
- qedr: NULL pointer regression found during testing
- rxe: Various small bugs"
* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
IB/rxe: Fix missing completion for mem_reg work requests
RDMA/core: Save kernel caller name when creating CQ using ib_create_cq()
IB/uverbs: Fix ordering of ucontext check in ib_uverbs_write
IB/mlx4: Fix an error handling path in 'mlx4_ib_rereg_user_mr()'
RDMA/qedr: Fix NULL pointer dereference when running over iWARP without RDMA-CM
IB/mlx5: Fix return value check in flow_counters_set_data()
IB/mlx5: Fix memory leak in mlx5_ib_create_flow
IB/rxe: avoid double kfree skb
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 14 | ||||
-rw-r--r-- | drivers/infiniband/core/verbs.c | 14 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mr.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 36 | ||||
-rw-r--r-- | drivers/infiniband/hw/qedr/verbs.c | 3 | ||||
-rw-r--r-- | drivers/infiniband/sw/rxe/rxe_req.c | 5 | ||||
-rw-r--r-- | include/rdma/ib_verbs.h | 13 |
7 files changed, 59 insertions, 33 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 3ae2339dd27a..2094d136513d 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -736,10 +736,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, | |||
736 | if (ret) | 736 | if (ret) |
737 | return ret; | 737 | return ret; |
738 | 738 | ||
739 | if (!file->ucontext && | ||
740 | (command != IB_USER_VERBS_CMD_GET_CONTEXT || extended)) | ||
741 | return -EINVAL; | ||
742 | |||
743 | if (extended) { | 739 | if (extended) { |
744 | if (count < (sizeof(hdr) + sizeof(ex_hdr))) | 740 | if (count < (sizeof(hdr) + sizeof(ex_hdr))) |
745 | return -EINVAL; | 741 | return -EINVAL; |
@@ -759,6 +755,16 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, | |||
759 | goto out; | 755 | goto out; |
760 | } | 756 | } |
761 | 757 | ||
758 | /* | ||
759 | * Must be after the ib_dev check, as once the RCU clears ib_dev == | ||
760 | * NULL means ucontext == NULL | ||
761 | */ | ||
762 | if (!file->ucontext && | ||
763 | (command != IB_USER_VERBS_CMD_GET_CONTEXT || extended)) { | ||
764 | ret = -EINVAL; | ||
765 | goto out; | ||
766 | } | ||
767 | |||
762 | if (!verify_command_mask(ib_dev, command, extended)) { | 768 | if (!verify_command_mask(ib_dev, command, extended)) { |
763 | ret = -EOPNOTSUPP; | 769 | ret = -EOPNOTSUPP; |
764 | goto out; | 770 | goto out; |
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 0b56828c1319..9d6beb948535 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
@@ -1562,11 +1562,12 @@ EXPORT_SYMBOL(ib_destroy_qp); | |||
1562 | 1562 | ||
1563 | /* Completion queues */ | 1563 | /* Completion queues */ |
1564 | 1564 | ||
1565 | struct ib_cq *ib_create_cq(struct ib_device *device, | 1565 | struct ib_cq *__ib_create_cq(struct ib_device *device, |
1566 | ib_comp_handler comp_handler, | 1566 | ib_comp_handler comp_handler, |
1567 | void (*event_handler)(struct ib_event *, void *), | 1567 | void (*event_handler)(struct ib_event *, void *), |
1568 | void *cq_context, | 1568 | void *cq_context, |
1569 | const struct ib_cq_init_attr *cq_attr) | 1569 | const struct ib_cq_init_attr *cq_attr, |
1570 | const char *caller) | ||
1570 | { | 1571 | { |
1571 | struct ib_cq *cq; | 1572 | struct ib_cq *cq; |
1572 | 1573 | ||
@@ -1580,12 +1581,13 @@ struct ib_cq *ib_create_cq(struct ib_device *device, | |||
1580 | cq->cq_context = cq_context; | 1581 | cq->cq_context = cq_context; |
1581 | atomic_set(&cq->usecnt, 0); | 1582 | atomic_set(&cq->usecnt, 0); |
1582 | cq->res.type = RDMA_RESTRACK_CQ; | 1583 | cq->res.type = RDMA_RESTRACK_CQ; |
1584 | cq->res.kern_name = caller; | ||
1583 | rdma_restrack_add(&cq->res); | 1585 | rdma_restrack_add(&cq->res); |
1584 | } | 1586 | } |
1585 | 1587 | ||
1586 | return cq; | 1588 | return cq; |
1587 | } | 1589 | } |
1588 | EXPORT_SYMBOL(ib_create_cq); | 1590 | EXPORT_SYMBOL(__ib_create_cq); |
1589 | 1591 | ||
1590 | int rdma_set_cq_moderation(struct ib_cq *cq, u16 cq_count, u16 cq_period) | 1592 | int rdma_set_cq_moderation(struct ib_cq *cq, u16 cq_count, u16 cq_period) |
1591 | { | 1593 | { |
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index ed1f253faf97..c7c85c22e4e3 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
@@ -486,8 +486,11 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, | |||
486 | } | 486 | } |
487 | 487 | ||
488 | if (flags & IB_MR_REREG_ACCESS) { | 488 | if (flags & IB_MR_REREG_ACCESS) { |
489 | if (ib_access_writable(mr_access_flags) && !mmr->umem->writable) | 489 | if (ib_access_writable(mr_access_flags) && |
490 | return -EPERM; | 490 | !mmr->umem->writable) { |
491 | err = -EPERM; | ||
492 | goto release_mpt_entry; | ||
493 | } | ||
491 | 494 | ||
492 | err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry, | 495 | err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry, |
493 | convert_access(mr_access_flags)); | 496 | convert_access(mr_access_flags)); |
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index e52dd21519b4..e3e330f59c2c 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
@@ -3199,8 +3199,8 @@ static int flow_counters_set_data(struct ib_counters *ibcounters, | |||
3199 | if (!mcounters->hw_cntrs_hndl) { | 3199 | if (!mcounters->hw_cntrs_hndl) { |
3200 | mcounters->hw_cntrs_hndl = mlx5_fc_create( | 3200 | mcounters->hw_cntrs_hndl = mlx5_fc_create( |
3201 | to_mdev(ibcounters->device)->mdev, false); | 3201 | to_mdev(ibcounters->device)->mdev, false); |
3202 | if (!mcounters->hw_cntrs_hndl) { | 3202 | if (IS_ERR(mcounters->hw_cntrs_hndl)) { |
3203 | ret = -ENOMEM; | 3203 | ret = PTR_ERR(mcounters->hw_cntrs_hndl); |
3204 | goto free; | 3204 | goto free; |
3205 | } | 3205 | } |
3206 | hw_hndl = true; | 3206 | hw_hndl = true; |
@@ -3546,29 +3546,35 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, | |||
3546 | return ERR_PTR(-ENOMEM); | 3546 | return ERR_PTR(-ENOMEM); |
3547 | 3547 | ||
3548 | err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz); | 3548 | err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz); |
3549 | if (err) { | 3549 | if (err) |
3550 | kfree(ucmd); | 3550 | goto free_ucmd; |
3551 | return ERR_PTR(err); | ||
3552 | } | ||
3553 | } | 3551 | } |
3554 | 3552 | ||
3555 | if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) | 3553 | if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) { |
3556 | return ERR_PTR(-ENOMEM); | 3554 | err = -ENOMEM; |
3555 | goto free_ucmd; | ||
3556 | } | ||
3557 | 3557 | ||
3558 | if (domain != IB_FLOW_DOMAIN_USER || | 3558 | if (domain != IB_FLOW_DOMAIN_USER || |
3559 | flow_attr->port > dev->num_ports || | 3559 | flow_attr->port > dev->num_ports || |
3560 | (flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP | | 3560 | (flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP | |
3561 | IB_FLOW_ATTR_FLAGS_EGRESS))) | 3561 | IB_FLOW_ATTR_FLAGS_EGRESS))) { |
3562 | return ERR_PTR(-EINVAL); | 3562 | err = -EINVAL; |
3563 | goto free_ucmd; | ||
3564 | } | ||
3563 | 3565 | ||
3564 | if (is_egress && | 3566 | if (is_egress && |
3565 | (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || | 3567 | (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || |
3566 | flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) | 3568 | flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) { |
3567 | return ERR_PTR(-EINVAL); | 3569 | err = -EINVAL; |
3570 | goto free_ucmd; | ||
3571 | } | ||
3568 | 3572 | ||
3569 | dst = kzalloc(sizeof(*dst), GFP_KERNEL); | 3573 | dst = kzalloc(sizeof(*dst), GFP_KERNEL); |
3570 | if (!dst) | 3574 | if (!dst) { |
3571 | return ERR_PTR(-ENOMEM); | 3575 | err = -ENOMEM; |
3576 | goto free_ucmd; | ||
3577 | } | ||
3572 | 3578 | ||
3573 | mutex_lock(&dev->flow_db->lock); | 3579 | mutex_lock(&dev->flow_db->lock); |
3574 | 3580 | ||
@@ -3637,8 +3643,8 @@ destroy_ft: | |||
3637 | unlock: | 3643 | unlock: |
3638 | mutex_unlock(&dev->flow_db->lock); | 3644 | mutex_unlock(&dev->flow_db->lock); |
3639 | kfree(dst); | 3645 | kfree(dst); |
3646 | free_ucmd: | ||
3640 | kfree(ucmd); | 3647 | kfree(ucmd); |
3641 | kfree(handler); | ||
3642 | return ERR_PTR(err); | 3648 | return ERR_PTR(err); |
3643 | } | 3649 | } |
3644 | 3650 | ||
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index f7ac8fc9b531..f07b8df96f43 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c | |||
@@ -1957,6 +1957,9 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
1957 | } | 1957 | } |
1958 | 1958 | ||
1959 | if (attr_mask & (IB_QP_AV | IB_QP_PATH_MTU)) { | 1959 | if (attr_mask & (IB_QP_AV | IB_QP_PATH_MTU)) { |
1960 | if (rdma_protocol_iwarp(&dev->ibdev, 1)) | ||
1961 | return -EINVAL; | ||
1962 | |||
1960 | if (attr_mask & IB_QP_PATH_MTU) { | 1963 | if (attr_mask & IB_QP_PATH_MTU) { |
1961 | if (attr->path_mtu < IB_MTU_256 || | 1964 | if (attr->path_mtu < IB_MTU_256 || |
1962 | attr->path_mtu > IB_MTU_4096) { | 1965 | attr->path_mtu > IB_MTU_4096) { |
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index f30eeba3f772..8be27238a86e 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c | |||
@@ -645,6 +645,9 @@ next_wqe: | |||
645 | } else { | 645 | } else { |
646 | goto exit; | 646 | goto exit; |
647 | } | 647 | } |
648 | if ((wqe->wr.send_flags & IB_SEND_SIGNALED) || | ||
649 | qp->sq_sig_type == IB_SIGNAL_ALL_WR) | ||
650 | rxe_run_task(&qp->comp.task, 1); | ||
648 | qp->req.wqe_index = next_index(qp->sq.queue, | 651 | qp->req.wqe_index = next_index(qp->sq.queue, |
649 | qp->req.wqe_index); | 652 | qp->req.wqe_index); |
650 | goto next_wqe; | 653 | goto next_wqe; |
@@ -709,6 +712,7 @@ next_wqe: | |||
709 | 712 | ||
710 | if (fill_packet(qp, wqe, &pkt, skb, payload)) { | 713 | if (fill_packet(qp, wqe, &pkt, skb, payload)) { |
711 | pr_debug("qp#%d Error during fill packet\n", qp_num(qp)); | 714 | pr_debug("qp#%d Error during fill packet\n", qp_num(qp)); |
715 | kfree_skb(skb); | ||
712 | goto err; | 716 | goto err; |
713 | } | 717 | } |
714 | 718 | ||
@@ -740,7 +744,6 @@ next_wqe: | |||
740 | goto next_wqe; | 744 | goto next_wqe; |
741 | 745 | ||
742 | err: | 746 | err: |
743 | kfree_skb(skb); | ||
744 | wqe->status = IB_WC_LOC_PROT_ERR; | 747 | wqe->status = IB_WC_LOC_PROT_ERR; |
745 | wqe->state = wqe_state_error; | 748 | wqe->state = wqe_state_error; |
746 | __rxe_do_task(&qp->comp.task); | 749 | __rxe_do_task(&qp->comp.task); |
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 4c6241bc2039..6c003995347a 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h | |||
@@ -3391,11 +3391,14 @@ int ib_process_cq_direct(struct ib_cq *cq, int budget); | |||
3391 | * | 3391 | * |
3392 | * Users can examine the cq structure to determine the actual CQ size. | 3392 | * Users can examine the cq structure to determine the actual CQ size. |
3393 | */ | 3393 | */ |
3394 | struct ib_cq *ib_create_cq(struct ib_device *device, | 3394 | struct ib_cq *__ib_create_cq(struct ib_device *device, |
3395 | ib_comp_handler comp_handler, | 3395 | ib_comp_handler comp_handler, |
3396 | void (*event_handler)(struct ib_event *, void *), | 3396 | void (*event_handler)(struct ib_event *, void *), |
3397 | void *cq_context, | 3397 | void *cq_context, |
3398 | const struct ib_cq_init_attr *cq_attr); | 3398 | const struct ib_cq_init_attr *cq_attr, |
3399 | const char *caller); | ||
3400 | #define ib_create_cq(device, cmp_hndlr, evt_hndlr, cq_ctxt, cq_attr) \ | ||
3401 | __ib_create_cq((device), (cmp_hndlr), (evt_hndlr), (cq_ctxt), (cq_attr), KBUILD_MODNAME) | ||
3399 | 3402 | ||
3400 | /** | 3403 | /** |
3401 | * ib_resize_cq - Modifies the capacity of the CQ. | 3404 | * ib_resize_cq - Modifies the capacity of the CQ. |