18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2013-2018, Mellanox Technologies inc. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kernel.h> 78c2ecf20Sopenharmony_ci#include <linux/mlx5/driver.h> 88c2ecf20Sopenharmony_ci#include "mlx5_ib.h" 98c2ecf20Sopenharmony_ci#include "srq.h" 108c2ecf20Sopenharmony_ci#include "qp.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic int get_pas_size(struct mlx5_srq_attr *in) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci u32 log_page_size = in->log_page_size + 12; 158c2ecf20Sopenharmony_ci u32 log_srq_size = in->log_size; 168c2ecf20Sopenharmony_ci u32 log_rq_stride = in->wqe_shift; 178c2ecf20Sopenharmony_ci u32 page_offset = in->page_offset; 188c2ecf20Sopenharmony_ci u32 po_quanta = 1 << (log_page_size - 6); 198c2ecf20Sopenharmony_ci u32 rq_sz = 1 << (log_srq_size + 4 + log_rq_stride); 208c2ecf20Sopenharmony_ci u32 page_size = 1 << log_page_size; 218c2ecf20Sopenharmony_ci u32 rq_sz_po = rq_sz + (page_offset * po_quanta); 228c2ecf20Sopenharmony_ci u32 rq_num_pas = DIV_ROUND_UP(rq_sz_po, page_size); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci return rq_num_pas * sizeof(u64); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void set_wq(void *wq, struct mlx5_srq_attr *in) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, wq_signature, !!(in->flags 308c2ecf20Sopenharmony_ci & MLX5_SRQ_FLAG_WQ_SIG)); 318c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, log_wq_pg_sz, in->log_page_size); 328c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, log_wq_stride, in->wqe_shift + 4); 338c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, log_wq_sz, in->log_size); 348c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, page_offset, in->page_offset); 358c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, lwm, in->lwm); 368c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, pd, in->pd); 378c2ecf20Sopenharmony_ci MLX5_SET64(wq, wq, dbr_addr, in->db_record); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic void set_srqc(void *srqc, struct mlx5_srq_attr *in) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, wq_signature, !!(in->flags 438c2ecf20Sopenharmony_ci & MLX5_SRQ_FLAG_WQ_SIG)); 448c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, log_page_size, in->log_page_size); 458c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, log_rq_stride, in->wqe_shift); 468c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, log_srq_size, in->log_size); 478c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, page_offset, in->page_offset); 488c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, lwm, in->lwm); 498c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, pd, in->pd); 508c2ecf20Sopenharmony_ci MLX5_SET64(srqc, srqc, dbr_addr, in->db_record); 518c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, xrcd, in->xrcd); 528c2ecf20Sopenharmony_ci MLX5_SET(srqc, srqc, cqn, in->cqn); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic void get_wq(void *wq, struct mlx5_srq_attr *in) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci if (MLX5_GET(wq, wq, wq_signature)) 588c2ecf20Sopenharmony_ci in->flags &= MLX5_SRQ_FLAG_WQ_SIG; 598c2ecf20Sopenharmony_ci in->log_page_size = MLX5_GET(wq, wq, log_wq_pg_sz); 608c2ecf20Sopenharmony_ci in->wqe_shift = MLX5_GET(wq, wq, log_wq_stride) - 4; 618c2ecf20Sopenharmony_ci in->log_size = MLX5_GET(wq, wq, log_wq_sz); 628c2ecf20Sopenharmony_ci in->page_offset = MLX5_GET(wq, wq, page_offset); 638c2ecf20Sopenharmony_ci in->lwm = MLX5_GET(wq, wq, lwm); 648c2ecf20Sopenharmony_ci in->pd = MLX5_GET(wq, wq, pd); 658c2ecf20Sopenharmony_ci in->db_record = MLX5_GET64(wq, wq, dbr_addr); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic void get_srqc(void *srqc, struct mlx5_srq_attr *in) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci if (MLX5_GET(srqc, srqc, wq_signature)) 718c2ecf20Sopenharmony_ci in->flags &= MLX5_SRQ_FLAG_WQ_SIG; 728c2ecf20Sopenharmony_ci in->log_page_size = MLX5_GET(srqc, srqc, log_page_size); 738c2ecf20Sopenharmony_ci in->wqe_shift = MLX5_GET(srqc, srqc, log_rq_stride); 748c2ecf20Sopenharmony_ci in->log_size = MLX5_GET(srqc, srqc, log_srq_size); 758c2ecf20Sopenharmony_ci in->page_offset = MLX5_GET(srqc, srqc, page_offset); 768c2ecf20Sopenharmony_ci in->lwm = MLX5_GET(srqc, srqc, lwm); 778c2ecf20Sopenharmony_ci in->pd = MLX5_GET(srqc, srqc, pd); 788c2ecf20Sopenharmony_ci in->db_record = MLX5_GET64(srqc, srqc, dbr_addr); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct mlx5_srq_table *table = &dev->srq_table; 848c2ecf20Sopenharmony_ci struct mlx5_core_srq *srq; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci xa_lock_irq(&table->array); 878c2ecf20Sopenharmony_ci srq = xa_load(&table->array, srqn); 888c2ecf20Sopenharmony_ci if (srq) 898c2ecf20Sopenharmony_ci refcount_inc(&srq->common.refcount); 908c2ecf20Sopenharmony_ci xa_unlock_irq(&table->array); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci return srq; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int create_srq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 968c2ecf20Sopenharmony_ci struct mlx5_srq_attr *in) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci u32 create_out[MLX5_ST_SZ_DW(create_srq_out)] = {0}; 998c2ecf20Sopenharmony_ci void *create_in; 1008c2ecf20Sopenharmony_ci void *srqc; 1018c2ecf20Sopenharmony_ci void *pas; 1028c2ecf20Sopenharmony_ci int pas_size; 1038c2ecf20Sopenharmony_ci int inlen; 1048c2ecf20Sopenharmony_ci int err; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci pas_size = get_pas_size(in); 1078c2ecf20Sopenharmony_ci inlen = MLX5_ST_SZ_BYTES(create_srq_in) + pas_size; 1088c2ecf20Sopenharmony_ci create_in = kvzalloc(inlen, GFP_KERNEL); 1098c2ecf20Sopenharmony_ci if (!create_in) 1108c2ecf20Sopenharmony_ci return -ENOMEM; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci MLX5_SET(create_srq_in, create_in, uid, in->uid); 1138c2ecf20Sopenharmony_ci srqc = MLX5_ADDR_OF(create_srq_in, create_in, srq_context_entry); 1148c2ecf20Sopenharmony_ci pas = MLX5_ADDR_OF(create_srq_in, create_in, pas); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci set_srqc(srqc, in); 1178c2ecf20Sopenharmony_ci memcpy(pas, in->pas, pas_size); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci MLX5_SET(create_srq_in, create_in, opcode, 1208c2ecf20Sopenharmony_ci MLX5_CMD_OP_CREATE_SRQ); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci err = mlx5_cmd_exec(dev->mdev, create_in, inlen, create_out, 1238c2ecf20Sopenharmony_ci sizeof(create_out)); 1248c2ecf20Sopenharmony_ci kvfree(create_in); 1258c2ecf20Sopenharmony_ci if (!err) { 1268c2ecf20Sopenharmony_ci srq->srqn = MLX5_GET(create_srq_out, create_out, srqn); 1278c2ecf20Sopenharmony_ci srq->uid = in->uid; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci return err; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic int destroy_srq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(destroy_srq_in)] = {}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci MLX5_SET(destroy_srq_in, in, opcode, MLX5_CMD_OP_DESTROY_SRQ); 1388c2ecf20Sopenharmony_ci MLX5_SET(destroy_srq_in, in, srqn, srq->srqn); 1398c2ecf20Sopenharmony_ci MLX5_SET(destroy_srq_in, in, uid, srq->uid); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, destroy_srq, in); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int arm_srq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 1458c2ecf20Sopenharmony_ci u16 lwm, int is_srq) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(arm_rq_in)] = {}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, opcode, MLX5_CMD_OP_ARM_RQ); 1508c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, op_mod, MLX5_ARM_RQ_IN_OP_MOD_SRQ); 1518c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, srq_number, srq->srqn); 1528c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, lwm, lwm); 1538c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, uid, srq->uid); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, arm_rq, in); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic int query_srq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 1598c2ecf20Sopenharmony_ci struct mlx5_srq_attr *out) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(query_srq_in)] = {}; 1628c2ecf20Sopenharmony_ci u32 *srq_out; 1638c2ecf20Sopenharmony_ci void *srqc; 1648c2ecf20Sopenharmony_ci int err; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci srq_out = kvzalloc(MLX5_ST_SZ_BYTES(query_srq_out), GFP_KERNEL); 1678c2ecf20Sopenharmony_ci if (!srq_out) 1688c2ecf20Sopenharmony_ci return -ENOMEM; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci MLX5_SET(query_srq_in, in, opcode, MLX5_CMD_OP_QUERY_SRQ); 1718c2ecf20Sopenharmony_ci MLX5_SET(query_srq_in, in, srqn, srq->srqn); 1728c2ecf20Sopenharmony_ci err = mlx5_cmd_exec_inout(dev->mdev, query_srq, in, srq_out); 1738c2ecf20Sopenharmony_ci if (err) 1748c2ecf20Sopenharmony_ci goto out; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci srqc = MLX5_ADDR_OF(query_srq_out, srq_out, srq_context_entry); 1778c2ecf20Sopenharmony_ci get_srqc(srqc, out); 1788c2ecf20Sopenharmony_ci if (MLX5_GET(srqc, srqc, state) != MLX5_SRQC_STATE_GOOD) 1798c2ecf20Sopenharmony_ci out->flags |= MLX5_SRQ_FLAG_ERR; 1808c2ecf20Sopenharmony_ciout: 1818c2ecf20Sopenharmony_ci kvfree(srq_out); 1828c2ecf20Sopenharmony_ci return err; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic int create_xrc_srq_cmd(struct mlx5_ib_dev *dev, 1868c2ecf20Sopenharmony_ci struct mlx5_core_srq *srq, 1878c2ecf20Sopenharmony_ci struct mlx5_srq_attr *in) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci u32 create_out[MLX5_ST_SZ_DW(create_xrc_srq_out)]; 1908c2ecf20Sopenharmony_ci void *create_in; 1918c2ecf20Sopenharmony_ci void *xrc_srqc; 1928c2ecf20Sopenharmony_ci void *pas; 1938c2ecf20Sopenharmony_ci int pas_size; 1948c2ecf20Sopenharmony_ci int inlen; 1958c2ecf20Sopenharmony_ci int err; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci pas_size = get_pas_size(in); 1988c2ecf20Sopenharmony_ci inlen = MLX5_ST_SZ_BYTES(create_xrc_srq_in) + pas_size; 1998c2ecf20Sopenharmony_ci create_in = kvzalloc(inlen, GFP_KERNEL); 2008c2ecf20Sopenharmony_ci if (!create_in) 2018c2ecf20Sopenharmony_ci return -ENOMEM; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci MLX5_SET(create_xrc_srq_in, create_in, uid, in->uid); 2048c2ecf20Sopenharmony_ci xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, create_in, 2058c2ecf20Sopenharmony_ci xrc_srq_context_entry); 2068c2ecf20Sopenharmony_ci pas = MLX5_ADDR_OF(create_xrc_srq_in, create_in, pas); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci set_srqc(xrc_srqc, in); 2098c2ecf20Sopenharmony_ci MLX5_SET(xrc_srqc, xrc_srqc, user_index, in->user_index); 2108c2ecf20Sopenharmony_ci memcpy(pas, in->pas, pas_size); 2118c2ecf20Sopenharmony_ci MLX5_SET(create_xrc_srq_in, create_in, opcode, 2128c2ecf20Sopenharmony_ci MLX5_CMD_OP_CREATE_XRC_SRQ); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci memset(create_out, 0, sizeof(create_out)); 2158c2ecf20Sopenharmony_ci err = mlx5_cmd_exec(dev->mdev, create_in, inlen, create_out, 2168c2ecf20Sopenharmony_ci sizeof(create_out)); 2178c2ecf20Sopenharmony_ci if (err) 2188c2ecf20Sopenharmony_ci goto out; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci srq->srqn = MLX5_GET(create_xrc_srq_out, create_out, xrc_srqn); 2218c2ecf20Sopenharmony_ci srq->uid = in->uid; 2228c2ecf20Sopenharmony_ciout: 2238c2ecf20Sopenharmony_ci kvfree(create_in); 2248c2ecf20Sopenharmony_ci return err; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int destroy_xrc_srq_cmd(struct mlx5_ib_dev *dev, 2288c2ecf20Sopenharmony_ci struct mlx5_core_srq *srq) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(destroy_xrc_srq_in)] = {}; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci MLX5_SET(destroy_xrc_srq_in, in, opcode, MLX5_CMD_OP_DESTROY_XRC_SRQ); 2338c2ecf20Sopenharmony_ci MLX5_SET(destroy_xrc_srq_in, in, xrc_srqn, srq->srqn); 2348c2ecf20Sopenharmony_ci MLX5_SET(destroy_xrc_srq_in, in, uid, srq->uid); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, destroy_xrc_srq, in); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic int arm_xrc_srq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 2408c2ecf20Sopenharmony_ci u16 lwm) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(arm_xrc_srq_in)] = {}; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci MLX5_SET(arm_xrc_srq_in, in, opcode, MLX5_CMD_OP_ARM_XRC_SRQ); 2458c2ecf20Sopenharmony_ci MLX5_SET(arm_xrc_srq_in, in, op_mod, 2468c2ecf20Sopenharmony_ci MLX5_ARM_XRC_SRQ_IN_OP_MOD_XRC_SRQ); 2478c2ecf20Sopenharmony_ci MLX5_SET(arm_xrc_srq_in, in, xrc_srqn, srq->srqn); 2488c2ecf20Sopenharmony_ci MLX5_SET(arm_xrc_srq_in, in, lwm, lwm); 2498c2ecf20Sopenharmony_ci MLX5_SET(arm_xrc_srq_in, in, uid, srq->uid); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, arm_xrc_srq, in); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int query_xrc_srq_cmd(struct mlx5_ib_dev *dev, 2558c2ecf20Sopenharmony_ci struct mlx5_core_srq *srq, 2568c2ecf20Sopenharmony_ci struct mlx5_srq_attr *out) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(query_xrc_srq_in)] = {}; 2598c2ecf20Sopenharmony_ci u32 *xrcsrq_out; 2608c2ecf20Sopenharmony_ci void *xrc_srqc; 2618c2ecf20Sopenharmony_ci int err; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci xrcsrq_out = kvzalloc(MLX5_ST_SZ_BYTES(query_xrc_srq_out), GFP_KERNEL); 2648c2ecf20Sopenharmony_ci if (!xrcsrq_out) 2658c2ecf20Sopenharmony_ci return -ENOMEM; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci MLX5_SET(query_xrc_srq_in, in, opcode, MLX5_CMD_OP_QUERY_XRC_SRQ); 2688c2ecf20Sopenharmony_ci MLX5_SET(query_xrc_srq_in, in, xrc_srqn, srq->srqn); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci err = mlx5_cmd_exec_inout(dev->mdev, query_xrc_srq, in, xrcsrq_out); 2718c2ecf20Sopenharmony_ci if (err) 2728c2ecf20Sopenharmony_ci goto out; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci xrc_srqc = MLX5_ADDR_OF(query_xrc_srq_out, xrcsrq_out, 2758c2ecf20Sopenharmony_ci xrc_srq_context_entry); 2768c2ecf20Sopenharmony_ci get_srqc(xrc_srqc, out); 2778c2ecf20Sopenharmony_ci if (MLX5_GET(xrc_srqc, xrc_srqc, state) != MLX5_XRC_SRQC_STATE_GOOD) 2788c2ecf20Sopenharmony_ci out->flags |= MLX5_SRQ_FLAG_ERR; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ciout: 2818c2ecf20Sopenharmony_ci kvfree(xrcsrq_out); 2828c2ecf20Sopenharmony_ci return err; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic int create_rmp_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 2868c2ecf20Sopenharmony_ci struct mlx5_srq_attr *in) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci void *create_out = NULL; 2898c2ecf20Sopenharmony_ci void *create_in = NULL; 2908c2ecf20Sopenharmony_ci void *rmpc; 2918c2ecf20Sopenharmony_ci void *wq; 2928c2ecf20Sopenharmony_ci int pas_size; 2938c2ecf20Sopenharmony_ci int outlen; 2948c2ecf20Sopenharmony_ci int inlen; 2958c2ecf20Sopenharmony_ci int err; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci pas_size = get_pas_size(in); 2988c2ecf20Sopenharmony_ci inlen = MLX5_ST_SZ_BYTES(create_rmp_in) + pas_size; 2998c2ecf20Sopenharmony_ci outlen = MLX5_ST_SZ_BYTES(create_rmp_out); 3008c2ecf20Sopenharmony_ci create_in = kvzalloc(inlen, GFP_KERNEL); 3018c2ecf20Sopenharmony_ci create_out = kvzalloc(outlen, GFP_KERNEL); 3028c2ecf20Sopenharmony_ci if (!create_in || !create_out) { 3038c2ecf20Sopenharmony_ci err = -ENOMEM; 3048c2ecf20Sopenharmony_ci goto out; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci rmpc = MLX5_ADDR_OF(create_rmp_in, create_in, ctx); 3088c2ecf20Sopenharmony_ci wq = MLX5_ADDR_OF(rmpc, rmpc, wq); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_RDY); 3118c2ecf20Sopenharmony_ci MLX5_SET(create_rmp_in, create_in, uid, in->uid); 3128c2ecf20Sopenharmony_ci set_wq(wq, in); 3138c2ecf20Sopenharmony_ci memcpy(MLX5_ADDR_OF(rmpc, rmpc, wq.pas), in->pas, pas_size); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci MLX5_SET(create_rmp_in, create_in, opcode, MLX5_CMD_OP_CREATE_RMP); 3168c2ecf20Sopenharmony_ci err = mlx5_cmd_exec(dev->mdev, create_in, inlen, create_out, outlen); 3178c2ecf20Sopenharmony_ci if (!err) { 3188c2ecf20Sopenharmony_ci srq->srqn = MLX5_GET(create_rmp_out, create_out, rmpn); 3198c2ecf20Sopenharmony_ci srq->uid = in->uid; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ciout: 3238c2ecf20Sopenharmony_ci kvfree(create_in); 3248c2ecf20Sopenharmony_ci kvfree(create_out); 3258c2ecf20Sopenharmony_ci return err; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic int destroy_rmp_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(destroy_rmp_in)] = {}; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci MLX5_SET(destroy_rmp_in, in, opcode, MLX5_CMD_OP_DESTROY_RMP); 3338c2ecf20Sopenharmony_ci MLX5_SET(destroy_rmp_in, in, rmpn, srq->srqn); 3348c2ecf20Sopenharmony_ci MLX5_SET(destroy_rmp_in, in, uid, srq->uid); 3358c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, destroy_rmp, in); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic int arm_rmp_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 3398c2ecf20Sopenharmony_ci u16 lwm) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci void *out = NULL; 3428c2ecf20Sopenharmony_ci void *in = NULL; 3438c2ecf20Sopenharmony_ci void *rmpc; 3448c2ecf20Sopenharmony_ci void *wq; 3458c2ecf20Sopenharmony_ci void *bitmask; 3468c2ecf20Sopenharmony_ci int outlen; 3478c2ecf20Sopenharmony_ci int inlen; 3488c2ecf20Sopenharmony_ci int err; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci inlen = MLX5_ST_SZ_BYTES(modify_rmp_in); 3518c2ecf20Sopenharmony_ci outlen = MLX5_ST_SZ_BYTES(modify_rmp_out); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci in = kvzalloc(inlen, GFP_KERNEL); 3548c2ecf20Sopenharmony_ci out = kvzalloc(outlen, GFP_KERNEL); 3558c2ecf20Sopenharmony_ci if (!in || !out) { 3568c2ecf20Sopenharmony_ci err = -ENOMEM; 3578c2ecf20Sopenharmony_ci goto out; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci rmpc = MLX5_ADDR_OF(modify_rmp_in, in, ctx); 3618c2ecf20Sopenharmony_ci bitmask = MLX5_ADDR_OF(modify_rmp_in, in, bitmask); 3628c2ecf20Sopenharmony_ci wq = MLX5_ADDR_OF(rmpc, rmpc, wq); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci MLX5_SET(modify_rmp_in, in, rmp_state, MLX5_RMPC_STATE_RDY); 3658c2ecf20Sopenharmony_ci MLX5_SET(modify_rmp_in, in, rmpn, srq->srqn); 3668c2ecf20Sopenharmony_ci MLX5_SET(modify_rmp_in, in, uid, srq->uid); 3678c2ecf20Sopenharmony_ci MLX5_SET(wq, wq, lwm, lwm); 3688c2ecf20Sopenharmony_ci MLX5_SET(rmp_bitmask, bitmask, lwm, 1); 3698c2ecf20Sopenharmony_ci MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_RDY); 3708c2ecf20Sopenharmony_ci MLX5_SET(modify_rmp_in, in, opcode, MLX5_CMD_OP_MODIFY_RMP); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci err = mlx5_cmd_exec_inout(dev->mdev, modify_rmp, in, out); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ciout: 3758c2ecf20Sopenharmony_ci kvfree(in); 3768c2ecf20Sopenharmony_ci kvfree(out); 3778c2ecf20Sopenharmony_ci return err; 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic int query_rmp_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 3818c2ecf20Sopenharmony_ci struct mlx5_srq_attr *out) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci u32 *rmp_out = NULL; 3848c2ecf20Sopenharmony_ci u32 *rmp_in = NULL; 3858c2ecf20Sopenharmony_ci void *rmpc; 3868c2ecf20Sopenharmony_ci int outlen; 3878c2ecf20Sopenharmony_ci int inlen; 3888c2ecf20Sopenharmony_ci int err; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci outlen = MLX5_ST_SZ_BYTES(query_rmp_out); 3918c2ecf20Sopenharmony_ci inlen = MLX5_ST_SZ_BYTES(query_rmp_in); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci rmp_out = kvzalloc(outlen, GFP_KERNEL); 3948c2ecf20Sopenharmony_ci rmp_in = kvzalloc(inlen, GFP_KERNEL); 3958c2ecf20Sopenharmony_ci if (!rmp_out || !rmp_in) { 3968c2ecf20Sopenharmony_ci err = -ENOMEM; 3978c2ecf20Sopenharmony_ci goto out; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci MLX5_SET(query_rmp_in, rmp_in, opcode, MLX5_CMD_OP_QUERY_RMP); 4018c2ecf20Sopenharmony_ci MLX5_SET(query_rmp_in, rmp_in, rmpn, srq->srqn); 4028c2ecf20Sopenharmony_ci err = mlx5_cmd_exec_inout(dev->mdev, query_rmp, rmp_in, rmp_out); 4038c2ecf20Sopenharmony_ci if (err) 4048c2ecf20Sopenharmony_ci goto out; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci rmpc = MLX5_ADDR_OF(query_rmp_out, rmp_out, rmp_context); 4078c2ecf20Sopenharmony_ci get_wq(MLX5_ADDR_OF(rmpc, rmpc, wq), out); 4088c2ecf20Sopenharmony_ci if (MLX5_GET(rmpc, rmpc, state) != MLX5_RMPC_STATE_RDY) 4098c2ecf20Sopenharmony_ci out->flags |= MLX5_SRQ_FLAG_ERR; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ciout: 4128c2ecf20Sopenharmony_ci kvfree(rmp_out); 4138c2ecf20Sopenharmony_ci kvfree(rmp_in); 4148c2ecf20Sopenharmony_ci return err; 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cistatic int create_xrq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 4188c2ecf20Sopenharmony_ci struct mlx5_srq_attr *in) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci u32 create_out[MLX5_ST_SZ_DW(create_xrq_out)] = {0}; 4218c2ecf20Sopenharmony_ci void *create_in; 4228c2ecf20Sopenharmony_ci void *xrqc; 4238c2ecf20Sopenharmony_ci void *wq; 4248c2ecf20Sopenharmony_ci int pas_size; 4258c2ecf20Sopenharmony_ci int inlen; 4268c2ecf20Sopenharmony_ci int err; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci pas_size = get_pas_size(in); 4298c2ecf20Sopenharmony_ci inlen = MLX5_ST_SZ_BYTES(create_xrq_in) + pas_size; 4308c2ecf20Sopenharmony_ci create_in = kvzalloc(inlen, GFP_KERNEL); 4318c2ecf20Sopenharmony_ci if (!create_in) 4328c2ecf20Sopenharmony_ci return -ENOMEM; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci xrqc = MLX5_ADDR_OF(create_xrq_in, create_in, xrq_context); 4358c2ecf20Sopenharmony_ci wq = MLX5_ADDR_OF(xrqc, xrqc, wq); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci set_wq(wq, in); 4388c2ecf20Sopenharmony_ci memcpy(MLX5_ADDR_OF(xrqc, xrqc, wq.pas), in->pas, pas_size); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci if (in->type == IB_SRQT_TM) { 4418c2ecf20Sopenharmony_ci MLX5_SET(xrqc, xrqc, topology, MLX5_XRQC_TOPOLOGY_TAG_MATCHING); 4428c2ecf20Sopenharmony_ci if (in->flags & MLX5_SRQ_FLAG_RNDV) 4438c2ecf20Sopenharmony_ci MLX5_SET(xrqc, xrqc, offload, MLX5_XRQC_OFFLOAD_RNDV); 4448c2ecf20Sopenharmony_ci MLX5_SET(xrqc, xrqc, 4458c2ecf20Sopenharmony_ci tag_matching_topology_context.log_matching_list_sz, 4468c2ecf20Sopenharmony_ci in->tm_log_list_size); 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci MLX5_SET(xrqc, xrqc, user_index, in->user_index); 4498c2ecf20Sopenharmony_ci MLX5_SET(xrqc, xrqc, cqn, in->cqn); 4508c2ecf20Sopenharmony_ci MLX5_SET(create_xrq_in, create_in, opcode, MLX5_CMD_OP_CREATE_XRQ); 4518c2ecf20Sopenharmony_ci MLX5_SET(create_xrq_in, create_in, uid, in->uid); 4528c2ecf20Sopenharmony_ci err = mlx5_cmd_exec(dev->mdev, create_in, inlen, create_out, 4538c2ecf20Sopenharmony_ci sizeof(create_out)); 4548c2ecf20Sopenharmony_ci kvfree(create_in); 4558c2ecf20Sopenharmony_ci if (!err) { 4568c2ecf20Sopenharmony_ci srq->srqn = MLX5_GET(create_xrq_out, create_out, xrqn); 4578c2ecf20Sopenharmony_ci srq->uid = in->uid; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci return err; 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic int destroy_xrq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(destroy_xrq_in)] = {}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci MLX5_SET(destroy_xrq_in, in, opcode, MLX5_CMD_OP_DESTROY_XRQ); 4688c2ecf20Sopenharmony_ci MLX5_SET(destroy_xrq_in, in, xrqn, srq->srqn); 4698c2ecf20Sopenharmony_ci MLX5_SET(destroy_xrq_in, in, uid, srq->uid); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, destroy_xrq, in); 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic int arm_xrq_cmd(struct mlx5_ib_dev *dev, 4758c2ecf20Sopenharmony_ci struct mlx5_core_srq *srq, 4768c2ecf20Sopenharmony_ci u16 lwm) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(arm_rq_in)] = {}; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, opcode, MLX5_CMD_OP_ARM_RQ); 4818c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, op_mod, MLX5_ARM_RQ_IN_OP_MOD_XRQ); 4828c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, srq_number, srq->srqn); 4838c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, lwm, lwm); 4848c2ecf20Sopenharmony_ci MLX5_SET(arm_rq_in, in, uid, srq->uid); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci return mlx5_cmd_exec_in(dev->mdev, arm_rq, in); 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic int query_xrq_cmd(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 4908c2ecf20Sopenharmony_ci struct mlx5_srq_attr *out) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci u32 in[MLX5_ST_SZ_DW(query_xrq_in)] = {}; 4938c2ecf20Sopenharmony_ci u32 *xrq_out; 4948c2ecf20Sopenharmony_ci int outlen = MLX5_ST_SZ_BYTES(query_xrq_out); 4958c2ecf20Sopenharmony_ci void *xrqc; 4968c2ecf20Sopenharmony_ci int err; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci xrq_out = kvzalloc(outlen, GFP_KERNEL); 4998c2ecf20Sopenharmony_ci if (!xrq_out) 5008c2ecf20Sopenharmony_ci return -ENOMEM; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci MLX5_SET(query_xrq_in, in, opcode, MLX5_CMD_OP_QUERY_XRQ); 5038c2ecf20Sopenharmony_ci MLX5_SET(query_xrq_in, in, xrqn, srq->srqn); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci err = mlx5_cmd_exec_inout(dev->mdev, query_xrq, in, xrq_out); 5068c2ecf20Sopenharmony_ci if (err) 5078c2ecf20Sopenharmony_ci goto out; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci xrqc = MLX5_ADDR_OF(query_xrq_out, xrq_out, xrq_context); 5108c2ecf20Sopenharmony_ci get_wq(MLX5_ADDR_OF(xrqc, xrqc, wq), out); 5118c2ecf20Sopenharmony_ci if (MLX5_GET(xrqc, xrqc, state) != MLX5_XRQC_STATE_GOOD) 5128c2ecf20Sopenharmony_ci out->flags |= MLX5_SRQ_FLAG_ERR; 5138c2ecf20Sopenharmony_ci out->tm_next_tag = 5148c2ecf20Sopenharmony_ci MLX5_GET(xrqc, xrqc, 5158c2ecf20Sopenharmony_ci tag_matching_topology_context.append_next_index); 5168c2ecf20Sopenharmony_ci out->tm_hw_phase_cnt = 5178c2ecf20Sopenharmony_ci MLX5_GET(xrqc, xrqc, 5188c2ecf20Sopenharmony_ci tag_matching_topology_context.hw_phase_cnt); 5198c2ecf20Sopenharmony_ci out->tm_sw_phase_cnt = 5208c2ecf20Sopenharmony_ci MLX5_GET(xrqc, xrqc, 5218c2ecf20Sopenharmony_ci tag_matching_topology_context.sw_phase_cnt); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ciout: 5248c2ecf20Sopenharmony_ci kvfree(xrq_out); 5258c2ecf20Sopenharmony_ci return err; 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic int create_srq_split(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 5298c2ecf20Sopenharmony_ci struct mlx5_srq_attr *in) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci if (!dev->mdev->issi) 5328c2ecf20Sopenharmony_ci return create_srq_cmd(dev, srq, in); 5338c2ecf20Sopenharmony_ci switch (srq->common.res) { 5348c2ecf20Sopenharmony_ci case MLX5_RES_XSRQ: 5358c2ecf20Sopenharmony_ci return create_xrc_srq_cmd(dev, srq, in); 5368c2ecf20Sopenharmony_ci case MLX5_RES_XRQ: 5378c2ecf20Sopenharmony_ci return create_xrq_cmd(dev, srq, in); 5388c2ecf20Sopenharmony_ci default: 5398c2ecf20Sopenharmony_ci return create_rmp_cmd(dev, srq, in); 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic int destroy_srq_split(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci if (!dev->mdev->issi) 5468c2ecf20Sopenharmony_ci return destroy_srq_cmd(dev, srq); 5478c2ecf20Sopenharmony_ci switch (srq->common.res) { 5488c2ecf20Sopenharmony_ci case MLX5_RES_XSRQ: 5498c2ecf20Sopenharmony_ci return destroy_xrc_srq_cmd(dev, srq); 5508c2ecf20Sopenharmony_ci case MLX5_RES_XRQ: 5518c2ecf20Sopenharmony_ci return destroy_xrq_cmd(dev, srq); 5528c2ecf20Sopenharmony_ci default: 5538c2ecf20Sopenharmony_ci return destroy_rmp_cmd(dev, srq); 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ciint mlx5_cmd_create_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 5588c2ecf20Sopenharmony_ci struct mlx5_srq_attr *in) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci struct mlx5_srq_table *table = &dev->srq_table; 5618c2ecf20Sopenharmony_ci int err; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci switch (in->type) { 5648c2ecf20Sopenharmony_ci case IB_SRQT_XRC: 5658c2ecf20Sopenharmony_ci srq->common.res = MLX5_RES_XSRQ; 5668c2ecf20Sopenharmony_ci break; 5678c2ecf20Sopenharmony_ci case IB_SRQT_TM: 5688c2ecf20Sopenharmony_ci srq->common.res = MLX5_RES_XRQ; 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci default: 5718c2ecf20Sopenharmony_ci srq->common.res = MLX5_RES_SRQ; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci err = create_srq_split(dev, srq, in); 5758c2ecf20Sopenharmony_ci if (err) 5768c2ecf20Sopenharmony_ci return err; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci refcount_set(&srq->common.refcount, 1); 5798c2ecf20Sopenharmony_ci init_completion(&srq->common.free); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci err = xa_err(xa_store_irq(&table->array, srq->srqn, srq, GFP_KERNEL)); 5828c2ecf20Sopenharmony_ci if (err) 5838c2ecf20Sopenharmony_ci goto err_destroy_srq_split; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci return 0; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cierr_destroy_srq_split: 5888c2ecf20Sopenharmony_ci destroy_srq_split(dev, srq); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return err; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ciint mlx5_cmd_destroy_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci struct mlx5_srq_table *table = &dev->srq_table; 5968c2ecf20Sopenharmony_ci struct mlx5_core_srq *tmp; 5978c2ecf20Sopenharmony_ci int err; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* Delete entry, but leave index occupied */ 6008c2ecf20Sopenharmony_ci tmp = xa_cmpxchg_irq(&table->array, srq->srqn, srq, XA_ZERO_ENTRY, 0); 6018c2ecf20Sopenharmony_ci if (WARN_ON(tmp != srq)) 6028c2ecf20Sopenharmony_ci return xa_err(tmp) ?: -EINVAL; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci err = destroy_srq_split(dev, srq); 6058c2ecf20Sopenharmony_ci if (err) { 6068c2ecf20Sopenharmony_ci /* 6078c2ecf20Sopenharmony_ci * We don't need to check returned result for an error, 6088c2ecf20Sopenharmony_ci * because we are storing in pre-allocated space xarray 6098c2ecf20Sopenharmony_ci * entry and it can't fail at this stage. 6108c2ecf20Sopenharmony_ci */ 6118c2ecf20Sopenharmony_ci xa_cmpxchg_irq(&table->array, srq->srqn, XA_ZERO_ENTRY, srq, 0); 6128c2ecf20Sopenharmony_ci return err; 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci xa_erase_irq(&table->array, srq->srqn); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci mlx5_core_res_put(&srq->common); 6178c2ecf20Sopenharmony_ci wait_for_completion(&srq->common.free); 6188c2ecf20Sopenharmony_ci return 0; 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ciint mlx5_cmd_query_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 6228c2ecf20Sopenharmony_ci struct mlx5_srq_attr *out) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci if (!dev->mdev->issi) 6258c2ecf20Sopenharmony_ci return query_srq_cmd(dev, srq, out); 6268c2ecf20Sopenharmony_ci switch (srq->common.res) { 6278c2ecf20Sopenharmony_ci case MLX5_RES_XSRQ: 6288c2ecf20Sopenharmony_ci return query_xrc_srq_cmd(dev, srq, out); 6298c2ecf20Sopenharmony_ci case MLX5_RES_XRQ: 6308c2ecf20Sopenharmony_ci return query_xrq_cmd(dev, srq, out); 6318c2ecf20Sopenharmony_ci default: 6328c2ecf20Sopenharmony_ci return query_rmp_cmd(dev, srq, out); 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ciint mlx5_cmd_arm_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, 6378c2ecf20Sopenharmony_ci u16 lwm, int is_srq) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci if (!dev->mdev->issi) 6408c2ecf20Sopenharmony_ci return arm_srq_cmd(dev, srq, lwm, is_srq); 6418c2ecf20Sopenharmony_ci switch (srq->common.res) { 6428c2ecf20Sopenharmony_ci case MLX5_RES_XSRQ: 6438c2ecf20Sopenharmony_ci return arm_xrc_srq_cmd(dev, srq, lwm); 6448c2ecf20Sopenharmony_ci case MLX5_RES_XRQ: 6458c2ecf20Sopenharmony_ci return arm_xrq_cmd(dev, srq, lwm); 6468c2ecf20Sopenharmony_ci default: 6478c2ecf20Sopenharmony_ci return arm_rmp_cmd(dev, srq, lwm); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci} 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_cistatic int srq_event_notifier(struct notifier_block *nb, 6528c2ecf20Sopenharmony_ci unsigned long type, void *data) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci struct mlx5_srq_table *table; 6558c2ecf20Sopenharmony_ci struct mlx5_core_srq *srq; 6568c2ecf20Sopenharmony_ci struct mlx5_eqe *eqe; 6578c2ecf20Sopenharmony_ci u32 srqn; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci if (type != MLX5_EVENT_TYPE_SRQ_CATAS_ERROR && 6608c2ecf20Sopenharmony_ci type != MLX5_EVENT_TYPE_SRQ_RQ_LIMIT) 6618c2ecf20Sopenharmony_ci return NOTIFY_DONE; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci table = container_of(nb, struct mlx5_srq_table, nb); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci eqe = data; 6668c2ecf20Sopenharmony_ci srqn = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci xa_lock(&table->array); 6698c2ecf20Sopenharmony_ci srq = xa_load(&table->array, srqn); 6708c2ecf20Sopenharmony_ci if (srq) 6718c2ecf20Sopenharmony_ci refcount_inc(&srq->common.refcount); 6728c2ecf20Sopenharmony_ci xa_unlock(&table->array); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci if (!srq) 6758c2ecf20Sopenharmony_ci return NOTIFY_OK; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci srq->event(srq, eqe->type); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci mlx5_core_res_put(&srq->common); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci return NOTIFY_OK; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ciint mlx5_init_srq_table(struct mlx5_ib_dev *dev) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci struct mlx5_srq_table *table = &dev->srq_table; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci memset(table, 0, sizeof(*table)); 6898c2ecf20Sopenharmony_ci xa_init_flags(&table->array, XA_FLAGS_LOCK_IRQ); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci table->nb.notifier_call = srq_event_notifier; 6928c2ecf20Sopenharmony_ci mlx5_notifier_register(dev->mdev, &table->nb); 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_civoid mlx5_cleanup_srq_table(struct mlx5_ib_dev *dev) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct mlx5_srq_table *table = &dev->srq_table; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci mlx5_notifier_unregister(dev->mdev, &table->nb); 7028c2ecf20Sopenharmony_ci} 703