Commit fcef1046 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma into master

Pull rdma fixes from Jason Gunthorpe:
 "One merge window regression, some corruption bugs in HNS and a few
  more syzkaller fixes:

   - Two long standing syzkaller races

   - Fix incorrect HW configuration in HNS

   - Restore accidentally dropped locking in IB CM

   - Fix ODP prefetch bug added in the big rework several versions ago"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/mlx5: Prevent prefetch from racing with implicit destruction
  RDMA/cm: Protect access to remote_sidr_table
  RDMA/core: Fix race in rdma_alloc_commit_uobject()
  RDMA/hns: Fix wrong PBL offset when VA is not aligned to PAGE_SIZE
  RDMA/hns: Fix wrong assignment of lp_pktn_ini in QPC
  RDMA/mlx5: Use xa_lock_irq when access to SRQ table
parents a38a19ef a862192e
...@@ -3676,10 +3676,12 @@ static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv, ...@@ -3676,10 +3676,12 @@ static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
return ret; return ret;
} }
cm_id_priv->id.state = IB_CM_IDLE; cm_id_priv->id.state = IB_CM_IDLE;
spin_lock_irq(&cm.lock);
if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) { if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table); rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
RB_CLEAR_NODE(&cm_id_priv->sidr_id_node); RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
} }
spin_unlock_irq(&cm.lock);
return 0; return 0;
} }
......
...@@ -649,9 +649,6 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj, ...@@ -649,9 +649,6 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,
{ {
struct ib_uverbs_file *ufile = attrs->ufile; struct ib_uverbs_file *ufile = attrs->ufile;
/* alloc_commit consumes the uobj kref */
uobj->uapi_object->type_class->alloc_commit(uobj);
/* kref is held so long as the uobj is on the uobj list. */ /* kref is held so long as the uobj is on the uobj list. */
uverbs_uobject_get(uobj); uverbs_uobject_get(uobj);
spin_lock_irq(&ufile->uobjects_lock); spin_lock_irq(&ufile->uobjects_lock);
...@@ -661,6 +658,9 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj, ...@@ -661,6 +658,9 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,
/* matches atomic_set(-1) in alloc_uobj */ /* matches atomic_set(-1) in alloc_uobj */
atomic_set(&uobj->usecnt, 0); atomic_set(&uobj->usecnt, 0);
/* alloc_commit consumes the uobj kref */
uobj->uapi_object->type_class->alloc_commit(uobj);
/* Matches the down_read in rdma_alloc_begin_uobject */ /* Matches the down_read in rdma_alloc_begin_uobject */
up_read(&ufile->hw_destroy_rwsem); up_read(&ufile->hw_destroy_rwsem);
} }
......
...@@ -3954,6 +3954,15 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev, ...@@ -3954,6 +3954,15 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev,
return 0; return 0;
} }
static inline enum ib_mtu get_mtu(struct ib_qp *ibqp,
const struct ib_qp_attr *attr)
{
if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
return IB_MTU_4096;
return attr->path_mtu;
}
static int modify_qp_init_to_rtr(struct ib_qp *ibqp, static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
const struct ib_qp_attr *attr, int attr_mask, const struct ib_qp_attr *attr, int attr_mask,
struct hns_roce_v2_qp_context *context, struct hns_roce_v2_qp_context *context,
...@@ -3965,6 +3974,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, ...@@ -3965,6 +3974,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
struct ib_device *ibdev = &hr_dev->ib_dev; struct ib_device *ibdev = &hr_dev->ib_dev;
dma_addr_t trrl_ba; dma_addr_t trrl_ba;
dma_addr_t irrl_ba; dma_addr_t irrl_ba;
enum ib_mtu mtu;
u8 port_num; u8 port_num;
u64 *mtts; u64 *mtts;
u8 *dmac; u8 *dmac;
...@@ -4062,22 +4072,22 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, ...@@ -4062,22 +4072,22 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M, roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M,
V2_QPC_BYTE_52_DMAC_S, 0); V2_QPC_BYTE_52_DMAC_S, 0);
/* mtu*(2^LP_PKTN_INI) should not bigger than 1 message length 64kb */ mtu = get_mtu(ibqp, attr);
roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
V2_QPC_BYTE_56_LP_PKTN_INI_S,
ilog2(hr_dev->caps.max_sq_inline / IB_MTU_4096));
roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
V2_QPC_BYTE_56_LP_PKTN_INI_S, 0);
if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD) if (attr_mask & IB_QP_PATH_MTU) {
roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
V2_QPC_BYTE_24_MTU_S, IB_MTU_4096);
else if (attr_mask & IB_QP_PATH_MTU)
roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
V2_QPC_BYTE_24_MTU_S, attr->path_mtu); V2_QPC_BYTE_24_MTU_S, mtu);
roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
V2_QPC_BYTE_24_MTU_S, 0); V2_QPC_BYTE_24_MTU_S, 0);
}
#define MAX_LP_MSG_LEN 65536
/* MTU*(2^LP_PKTN_INI) shouldn't be bigger than 64kb */
roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
V2_QPC_BYTE_56_LP_PKTN_INI_S,
ilog2(MAX_LP_MSG_LEN / ib_mtu_enum_to_int(mtu)));
roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
V2_QPC_BYTE_56_LP_PKTN_INI_S, 0);
roce_set_bit(qpc_mask->byte_108_rx_reqepsn, roce_set_bit(qpc_mask->byte_108_rx_reqepsn,
V2_QPC_BYTE_108_RX_REQ_PSN_ERR_S, 0); V2_QPC_BYTE_108_RX_REQ_PSN_ERR_S, 0);
......
...@@ -120,7 +120,7 @@ static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr, ...@@ -120,7 +120,7 @@ static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr,
mr->pbl_hop_num = is_fast ? 1 : hr_dev->caps.pbl_hop_num; mr->pbl_hop_num = is_fast ? 1 : hr_dev->caps.pbl_hop_num;
buf_attr.page_shift = is_fast ? PAGE_SHIFT : buf_attr.page_shift = is_fast ? PAGE_SHIFT :
hr_dev->caps.pbl_buf_pg_sz + HNS_HW_PAGE_SHIFT; hr_dev->caps.pbl_buf_pg_sz + PAGE_SHIFT;
buf_attr.region[0].size = length; buf_attr.region[0].size = length;
buf_attr.region[0].hopnum = mr->pbl_hop_num; buf_attr.region[0].hopnum = mr->pbl_hop_num;
buf_attr.region_count = 1; buf_attr.region_count = 1;
......
...@@ -601,6 +601,23 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr) ...@@ -601,6 +601,23 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
*/ */
synchronize_srcu(&dev->odp_srcu); synchronize_srcu(&dev->odp_srcu);
/*
* All work on the prefetch list must be completed, xa_erase() prevented
* new work from being created.
*/
wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));
/*
* At this point it is forbidden for any other thread to enter
* pagefault_mr() on this imr. It is already forbidden to call
* pagefault_mr() on an implicit child. Due to this additions to
* implicit_children are prevented.
*/
/*
* Block destroy_unused_implicit_child_mr() from incrementing
* num_deferred_work.
*/
xa_lock(&imr->implicit_children); xa_lock(&imr->implicit_children);
xa_for_each (&imr->implicit_children, idx, mtt) { xa_for_each (&imr->implicit_children, idx, mtt) {
__xa_erase(&imr->implicit_children, idx); __xa_erase(&imr->implicit_children, idx);
...@@ -609,9 +626,8 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr) ...@@ -609,9 +626,8 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
xa_unlock(&imr->implicit_children); xa_unlock(&imr->implicit_children);
/* /*
* num_deferred_work can only be incremented inside the odp_srcu, or * Wait for any concurrent destroy_unused_implicit_child_mr() to
* under xa_lock while the child is in the xarray. Thus at this point * complete.
* it is only decreasing, and all work holding it is now on the wq.
*/ */
wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work)); wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));
......
...@@ -83,11 +83,11 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn) ...@@ -83,11 +83,11 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn)
struct mlx5_srq_table *table = &dev->srq_table; struct mlx5_srq_table *table = &dev->srq_table;
struct mlx5_core_srq *srq; struct mlx5_core_srq *srq;
xa_lock(&table->array); xa_lock_irq(&table->array);
srq = xa_load(&table->array, srqn); srq = xa_load(&table->array, srqn);
if (srq) if (srq)
refcount_inc(&srq->common.refcount); refcount_inc(&srq->common.refcount);
xa_unlock(&table->array); xa_unlock_irq(&table->array);
return srq; return srq;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment