Merge rdma branch 'for-rc' into 'for-next'

These did not seem worth sending as a dedicated rc PR during the last week
of the cycle.

* ko-rdma/for-rc:
  RDMA/ipoib: Drain RCU callbacks during module teardown
  RDMA/mlx5: Drain RCU callbacks during module teardown
  RDMA/core: Wait for RCU callbacks before unloading ib_core
  RDMA/irdma: Prevent overflows in memory contiguity checks
  RDMA/siw: publish QP after initialization
  RDMA/hns: Fix potential integer overflow in mhop hem cleanup
  RDMA/core: Fix memory leak in __ib_create_cq() on invalid cqe
  RDMA/mana_ib: initialize err for empty send WR lists
  RDMA/erdma: initialize ret for empty receive WR lists
  RDMA/irdma: Prevent user-triggered null deref on QP create
  RDMA/irdma: Prevent rereg_mr for non-mem regions
  RDMA/cma: Fix hardware address comparison length in netevent callback
  RDMa/mlx5: Avoid frame overflow warning
  IB/mad: Drop unmatched RMPP responses before reassembly

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Jason Gunthorpe 2026-08-18 11:05:13 -03:00
commit fab939caf8
12 changed files with 80 additions and 36 deletions

View File

@ -5272,7 +5272,7 @@ static int cma_netevent_callback(struct notifier_block *self,
list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) {
if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr,
neigh->ha, ETH_ALEN))
neigh->ha, neigh->dev->addr_len))
continue;
cma_id_get(current_id);
if (!queue_work(cma_wq, &current_id->id.net_work))

View File

@ -3332,6 +3332,7 @@ static void __exit ib_core_cleanup(void)
/* Make sure that any pending umem accounting work is done. */
destroy_workqueue(ib_wq);
destroy_workqueue(ib_unreg_wq);
rcu_barrier();
WARN_ON(!xa_empty(&clients));
WARN_ON(!xa_empty(&devices));
}

View File

@ -2031,6 +2031,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr)
change_mad_state(mad_send_wr, IB_MAD_STATE_EARLY_RESP);
}
static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent,
struct ib_mad_recv_wc *mad_recv_wc)
{
const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
struct ib_rmpp_mad *rmpp_mad;
if (!ib_mad_kernel_rmpp_agent(&agent->agent) ||
!ib_response_mad(mad_hdr) ||
!ib_is_mad_class_rmpp(mad_hdr->mgmt_class))
return false;
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE) &&
rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA;
}
static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_recv_wc *mad_recv_wc)
{
@ -2050,6 +2068,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
}
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) {
spin_lock_irqsave(&mad_agent_priv->lock, flags);
mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
if (!mad_send_wr) {
ib_free_recv_mad(mad_recv_wc);
deref_mad_agent(mad_agent_priv);
return;
}
}
if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
mad_recv_wc);

View File

@ -2214,13 +2214,13 @@ struct ib_cq *__ib_create_cq(struct ib_device *device,
struct ib_cq *cq;
int ret;
if (WARN_ON_ONCE(!cq_attr->cqe))
return ERR_PTR(-EINVAL);
cq = rdma_zalloc_drv_obj(device, ib_cq);
if (!cq)
return ERR_PTR(-ENOMEM);
if (WARN_ON_ONCE(!cq_attr->cqe))
return ERR_PTR(-EINVAL);
cq->device = device;
cq->comp_handler = comp_handler;
cq->event_handler = event_handler;

View File

@ -734,7 +734,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr,
const struct ib_recv_wr *wr = recv_wr;
struct erdma_qp *qp = to_eqp(ibqp);
unsigned long flags;
int ret;
int ret = 0;
spin_lock_irqsave(&qp->lock, flags);

View File

@ -836,7 +836,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev,
mhop.bt_chunk_size;
for (i = 0; i < table->num_hem; ++i) {
obj = i * buf_chunk_size / table->obj_size;
obj = (u64)i * buf_chunk_size / table->obj_size;
if (table->hem[i])
hns_roce_table_mhop_put(hr_dev, table, obj, 0);
}

View File

@ -2902,7 +2902,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size)
u32 pg_idx;
for (pg_idx = 0; pg_idx < npages; pg_idx++) {
if ((*arr + (pg_size * pg_idx)) != arr[pg_idx])
if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx])
return false;
}
@ -2935,7 +2935,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc,
for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) {
arr = leaf->addr;
if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr)
if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr)
return false;
ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size);
if (!ret)
@ -3897,6 +3897,9 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
return ERR_PTR(-EOPNOTSUPP);
if (iwmr->type != IRDMA_MEMREG_TYPE_MEM)
return ERR_PTR(-EINVAL);
ret = ib_umem_check_rereg(iwmr->region, flags, new_access);
if (ret)
return ERR_PTR(ret);

View File

@ -144,7 +144,7 @@ static int mana_ib_post_send_ud(struct mana_ib_qp *qp, const struct ib_ud_wr *wr
int mana_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
const struct ib_send_wr **bad_wr)
{
int err;
int err = 0;
struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp);
for (; wr; wr = wr->next) {

View File

@ -5542,6 +5542,7 @@ static int __init mlx5_ib_init(void)
dd_err:
mlx5r_rep_cleanup();
rep_err:
rcu_barrier();
mlx5_ib_qp_event_cleanup();
qp_event_err:
destroy_workqueue(mlx5_ib_event_wq);
@ -5555,6 +5556,7 @@ static void __exit mlx5_ib_cleanup(void)
auxiliary_driver_unregister(&mlx5r_driver);
auxiliary_driver_unregister(&mlx5r_mp_driver);
mlx5r_rep_cleanup();
rcu_barrier();
mlx5_ib_qp_event_cleanup();
destroy_workqueue(mlx5_ib_event_wq);

View File

@ -840,13 +840,15 @@ static int handle_psv(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
return err;
}
static int handle_reg_mr_integrity(struct mlx5_ib_dev *dev,
struct mlx5_ib_qp *qp,
const struct ib_send_wr *wr,
struct mlx5_wqe_ctrl_seg **ctrl, void **seg,
int *size, void **cur_edge,
unsigned int *idx, int nreq, u8 fence,
u8 next_fence)
static noinline_for_stack int handle_reg_mr_integrity(struct mlx5_ib_dev *dev,
struct mlx5_ib_qp *qp,
const struct ib_send_wr *wr,
struct mlx5_wqe_ctrl_seg **ctrl,
void **seg,
int *size, void **cur_edge,
unsigned int *idx, int nreq,
u8 fence,
u8 next_fence)
{
struct mlx5_ib_mr *mr;
struct mlx5_ib_mr *pi_mr;

View File

@ -316,6 +316,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
struct siw_ucontext *uctx =
rdma_udata_to_drv_context(udata, struct siw_ucontext,
base_ucontext);
struct siw_uresp_create_qp uresp = {};
unsigned long flags;
int num_sqe, num_rqe, rv = 0;
size_t length;
@ -369,11 +370,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
spin_lock_init(&qp->rq_lock);
spin_lock_init(&qp->orq_lock);
rv = siw_qp_add(sdev, qp);
if (rv)
goto err_atomic;
/* All queue indices are derived from modulo operations
* on a free running 'get' (consumer) and 'put' (producer)
* unsigned counter. Having queue sizes at power of two
@ -391,14 +387,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (qp->sendq == NULL) {
rv = -ENOMEM;
goto err_out_xa;
goto err_out;
}
if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) {
if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->attrs.flags |= SIW_SIGNAL_ALL_WR;
else {
rv = -EINVAL;
goto err_out_xa;
goto err_out;
}
}
qp->pd = pd;
@ -424,7 +420,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (qp->recvq == NULL) {
rv = -ENOMEM;
goto err_out_xa;
goto err_out;
}
qp->attrs.rq_size = num_rqe;
}
@ -439,11 +435,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
qp->attrs.state = SIW_QP_STATE_IDLE;
if (udata) {
struct siw_uresp_create_qp uresp = {};
uresp.num_sqe = num_sqe;
uresp.num_rqe = num_rqe;
uresp.qp_id = qp_id(qp);
if (qp->sendq) {
length = num_sqe * sizeof(struct siw_sqe);
@ -452,7 +445,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
length, &uresp.sq_key);
if (!qp->sq_entry) {
rv = -ENOMEM;
goto err_out_xa;
goto err_out;
}
}
@ -464,9 +457,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (!qp->rq_entry) {
uresp.sq_key = SIW_INVAL_UOBJ_KEY;
rv = -ENOMEM;
goto err_out_xa;
goto err_out;
}
}
}
qp->tx_cpu = siw_get_tx_cpu(sdev);
if (qp->tx_cpu < 0) {
rv = -EINVAL;
goto err_out;
}
init_completion(&qp->qp_free);
rv = siw_qp_add(sdev, qp);
if (rv)
goto err_out_tx;
if (udata) {
uresp.qp_id = qp_id(qp);
if (udata->outlen < sizeof(uresp)) {
rv = -EINVAL;
@ -476,22 +483,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (rv)
goto err_out_xa;
}
qp->tx_cpu = siw_get_tx_cpu(sdev);
if (qp->tx_cpu < 0) {
rv = -EINVAL;
goto err_out_xa;
}
INIT_LIST_HEAD(&qp->devq);
spin_lock_irqsave(&sdev->lock, flags);
list_add_tail(&qp->devq, &sdev->qp_list);
spin_unlock_irqrestore(&sdev->lock, flags);
init_completion(&qp->qp_free);
return 0;
err_out_xa:
xa_erase(&sdev->qp_xa, qp_id(qp));
err_out_tx:
siw_put_tx_cpu(qp->tx_cpu);
err_out:
if (uctx) {
rdma_user_mmap_entry_remove(qp->sq_entry);
rdma_user_mmap_entry_remove(qp->rq_entry);

View File

@ -2783,6 +2783,7 @@ static int __init ipoib_init_module(void)
err_sa:
ib_sa_unregister_client(&ipoib_sa_client);
destroy_workqueue(ipoib_workqueue);
rcu_barrier();
err_fs:
ipoib_unregister_debugfs();
@ -2800,6 +2801,7 @@ static void __exit ipoib_cleanup_module(void)
ib_sa_unregister_client(&ipoib_sa_client);
ipoib_unregister_debugfs();
destroy_workqueue(ipoib_workqueue);
rcu_barrier();
}
module_init(ipoib_init_module);