18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright(c) 2016 Intel Corporation. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 58c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 158c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 168c2ecf20Sopenharmony_ci * General Public License for more details. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * BSD LICENSE 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 218c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 228c2ecf20Sopenharmony_ci * are met: 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above copyright 258c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 268c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above copyright 278c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 288c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 298c2ecf20Sopenharmony_ci * distribution. 308c2ecf20Sopenharmony_ci * - Neither the name of Intel Corporation nor the names of its 318c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 328c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 358c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 368c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 378c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 388c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 398c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 408c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 418c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 428c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 438c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 448c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include <linux/err.h> 498c2ecf20Sopenharmony_ci#include <linux/slab.h> 508c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 518c2ecf20Sopenharmony_ci#include <rdma/uverbs_ioctl.h> 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#include "srq.h" 548c2ecf20Sopenharmony_ci#include "vt.h" 558c2ecf20Sopenharmony_ci#include "qp.h" 568c2ecf20Sopenharmony_ci/** 578c2ecf20Sopenharmony_ci * rvt_driver_srq_init - init srq resources on a per driver basis 588c2ecf20Sopenharmony_ci * @rdi: rvt dev structure 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * Do any initialization needed when a driver registers with rdmavt. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_civoid rvt_driver_srq_init(struct rvt_dev_info *rdi) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci spin_lock_init(&rdi->n_srqs_lock); 658c2ecf20Sopenharmony_ci rdi->n_srqs_allocated = 0; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/** 698c2ecf20Sopenharmony_ci * rvt_create_srq - create a shared receive queue 708c2ecf20Sopenharmony_ci * @ibpd: the protection domain of the SRQ to create 718c2ecf20Sopenharmony_ci * @srq_init_attr: the attributes of the SRQ 728c2ecf20Sopenharmony_ci * @udata: data from libibverbs when creating a user SRQ 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * Return: 0 on success 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ciint rvt_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *srq_init_attr, 778c2ecf20Sopenharmony_ci struct ib_udata *udata) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device); 808c2ecf20Sopenharmony_ci struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); 818c2ecf20Sopenharmony_ci u32 sz; 828c2ecf20Sopenharmony_ci int ret; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (srq_init_attr->srq_type != IB_SRQT_BASIC) 858c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (srq_init_attr->attr.max_sge == 0 || 888c2ecf20Sopenharmony_ci srq_init_attr->attr.max_sge > dev->dparms.props.max_srq_sge || 898c2ecf20Sopenharmony_ci srq_init_attr->attr.max_wr == 0 || 908c2ecf20Sopenharmony_ci srq_init_attr->attr.max_wr > dev->dparms.props.max_srq_wr) 918c2ecf20Sopenharmony_ci return -EINVAL; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* 948c2ecf20Sopenharmony_ci * Need to use vmalloc() if we want to support large #s of entries. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci srq->rq.size = srq_init_attr->attr.max_wr + 1; 978c2ecf20Sopenharmony_ci srq->rq.max_sge = srq_init_attr->attr.max_sge; 988c2ecf20Sopenharmony_ci sz = sizeof(struct ib_sge) * srq->rq.max_sge + 998c2ecf20Sopenharmony_ci sizeof(struct rvt_rwqe); 1008c2ecf20Sopenharmony_ci if (rvt_alloc_rq(&srq->rq, srq->rq.size * sz, 1018c2ecf20Sopenharmony_ci dev->dparms.node, udata)) { 1028c2ecf20Sopenharmony_ci ret = -ENOMEM; 1038c2ecf20Sopenharmony_ci goto bail_srq; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* 1078c2ecf20Sopenharmony_ci * Return the address of the RWQ as the offset to mmap. 1088c2ecf20Sopenharmony_ci * See rvt_mmap() for details. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci if (udata && udata->outlen >= sizeof(__u64)) { 1118c2ecf20Sopenharmony_ci u32 s = sizeof(struct rvt_rwq) + srq->rq.size * sz; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci srq->ip = rvt_create_mmap_info(dev, s, udata, srq->rq.wq); 1148c2ecf20Sopenharmony_ci if (IS_ERR(srq->ip)) { 1158c2ecf20Sopenharmony_ci ret = PTR_ERR(srq->ip); 1168c2ecf20Sopenharmony_ci goto bail_wq; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ret = ib_copy_to_udata(udata, &srq->ip->offset, 1208c2ecf20Sopenharmony_ci sizeof(srq->ip->offset)); 1218c2ecf20Sopenharmony_ci if (ret) 1228c2ecf20Sopenharmony_ci goto bail_ip; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* 1268c2ecf20Sopenharmony_ci * ib_create_srq() will initialize srq->ibsrq. 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ci spin_lock_init(&srq->rq.lock); 1298c2ecf20Sopenharmony_ci srq->limit = srq_init_attr->attr.srq_limit; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci spin_lock(&dev->n_srqs_lock); 1328c2ecf20Sopenharmony_ci if (dev->n_srqs_allocated == dev->dparms.props.max_srq) { 1338c2ecf20Sopenharmony_ci spin_unlock(&dev->n_srqs_lock); 1348c2ecf20Sopenharmony_ci ret = -ENOMEM; 1358c2ecf20Sopenharmony_ci goto bail_ip; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci dev->n_srqs_allocated++; 1398c2ecf20Sopenharmony_ci spin_unlock(&dev->n_srqs_lock); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (srq->ip) { 1428c2ecf20Sopenharmony_ci spin_lock_irq(&dev->pending_lock); 1438c2ecf20Sopenharmony_ci list_add(&srq->ip->pending_mmaps, &dev->pending_mmaps); 1448c2ecf20Sopenharmony_ci spin_unlock_irq(&dev->pending_lock); 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci return 0; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cibail_ip: 1508c2ecf20Sopenharmony_ci kfree(srq->ip); 1518c2ecf20Sopenharmony_cibail_wq: 1528c2ecf20Sopenharmony_ci rvt_free_rq(&srq->rq); 1538c2ecf20Sopenharmony_cibail_srq: 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/** 1588c2ecf20Sopenharmony_ci * rvt_modify_srq - modify a shared receive queue 1598c2ecf20Sopenharmony_ci * @ibsrq: the SRQ to modify 1608c2ecf20Sopenharmony_ci * @attr: the new attributes of the SRQ 1618c2ecf20Sopenharmony_ci * @attr_mask: indicates which attributes to modify 1628c2ecf20Sopenharmony_ci * @udata: user data for libibverbs.so 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci * Return: 0 on success 1658c2ecf20Sopenharmony_ci */ 1668c2ecf20Sopenharmony_ciint rvt_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, 1678c2ecf20Sopenharmony_ci enum ib_srq_attr_mask attr_mask, 1688c2ecf20Sopenharmony_ci struct ib_udata *udata) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); 1718c2ecf20Sopenharmony_ci struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device); 1728c2ecf20Sopenharmony_ci struct rvt_rq tmp_rq = {}; 1738c2ecf20Sopenharmony_ci int ret = 0; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (attr_mask & IB_SRQ_MAX_WR) { 1768c2ecf20Sopenharmony_ci struct rvt_krwq *okwq = NULL; 1778c2ecf20Sopenharmony_ci struct rvt_rwq *owq = NULL; 1788c2ecf20Sopenharmony_ci struct rvt_rwqe *p; 1798c2ecf20Sopenharmony_ci u32 sz, size, n, head, tail; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* Check that the requested sizes are below the limits. */ 1828c2ecf20Sopenharmony_ci if ((attr->max_wr > dev->dparms.props.max_srq_wr) || 1838c2ecf20Sopenharmony_ci ((attr_mask & IB_SRQ_LIMIT) ? 1848c2ecf20Sopenharmony_ci attr->srq_limit : srq->limit) > attr->max_wr) 1858c2ecf20Sopenharmony_ci return -EINVAL; 1868c2ecf20Sopenharmony_ci sz = sizeof(struct rvt_rwqe) + 1878c2ecf20Sopenharmony_ci srq->rq.max_sge * sizeof(struct ib_sge); 1888c2ecf20Sopenharmony_ci size = attr->max_wr + 1; 1898c2ecf20Sopenharmony_ci if (rvt_alloc_rq(&tmp_rq, size * sz, dev->dparms.node, 1908c2ecf20Sopenharmony_ci udata)) 1918c2ecf20Sopenharmony_ci return -ENOMEM; 1928c2ecf20Sopenharmony_ci /* Check that we can write the offset to mmap. */ 1938c2ecf20Sopenharmony_ci if (udata && udata->inlen >= sizeof(__u64)) { 1948c2ecf20Sopenharmony_ci __u64 offset_addr; 1958c2ecf20Sopenharmony_ci __u64 offset = 0; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci ret = ib_copy_from_udata(&offset_addr, udata, 1988c2ecf20Sopenharmony_ci sizeof(offset_addr)); 1998c2ecf20Sopenharmony_ci if (ret) 2008c2ecf20Sopenharmony_ci goto bail_free; 2018c2ecf20Sopenharmony_ci udata->outbuf = (void __user *) 2028c2ecf20Sopenharmony_ci (unsigned long)offset_addr; 2038c2ecf20Sopenharmony_ci ret = ib_copy_to_udata(udata, &offset, 2048c2ecf20Sopenharmony_ci sizeof(offset)); 2058c2ecf20Sopenharmony_ci if (ret) 2068c2ecf20Sopenharmony_ci goto bail_free; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci spin_lock_irq(&srq->rq.kwq->c_lock); 2108c2ecf20Sopenharmony_ci /* 2118c2ecf20Sopenharmony_ci * validate head and tail pointer values and compute 2128c2ecf20Sopenharmony_ci * the number of remaining WQEs. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_ci if (udata) { 2158c2ecf20Sopenharmony_ci owq = srq->rq.wq; 2168c2ecf20Sopenharmony_ci head = RDMA_READ_UAPI_ATOMIC(owq->head); 2178c2ecf20Sopenharmony_ci tail = RDMA_READ_UAPI_ATOMIC(owq->tail); 2188c2ecf20Sopenharmony_ci } else { 2198c2ecf20Sopenharmony_ci okwq = srq->rq.kwq; 2208c2ecf20Sopenharmony_ci head = okwq->head; 2218c2ecf20Sopenharmony_ci tail = okwq->tail; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci if (head >= srq->rq.size || tail >= srq->rq.size) { 2248c2ecf20Sopenharmony_ci ret = -EINVAL; 2258c2ecf20Sopenharmony_ci goto bail_unlock; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci n = head; 2288c2ecf20Sopenharmony_ci if (n < tail) 2298c2ecf20Sopenharmony_ci n += srq->rq.size - tail; 2308c2ecf20Sopenharmony_ci else 2318c2ecf20Sopenharmony_ci n -= tail; 2328c2ecf20Sopenharmony_ci if (size <= n) { 2338c2ecf20Sopenharmony_ci ret = -EINVAL; 2348c2ecf20Sopenharmony_ci goto bail_unlock; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci n = 0; 2378c2ecf20Sopenharmony_ci p = tmp_rq.kwq->curr_wq; 2388c2ecf20Sopenharmony_ci while (tail != head) { 2398c2ecf20Sopenharmony_ci struct rvt_rwqe *wqe; 2408c2ecf20Sopenharmony_ci int i; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci wqe = rvt_get_rwqe_ptr(&srq->rq, tail); 2438c2ecf20Sopenharmony_ci p->wr_id = wqe->wr_id; 2448c2ecf20Sopenharmony_ci p->num_sge = wqe->num_sge; 2458c2ecf20Sopenharmony_ci for (i = 0; i < wqe->num_sge; i++) 2468c2ecf20Sopenharmony_ci p->sg_list[i] = wqe->sg_list[i]; 2478c2ecf20Sopenharmony_ci n++; 2488c2ecf20Sopenharmony_ci p = (struct rvt_rwqe *)((char *)p + sz); 2498c2ecf20Sopenharmony_ci if (++tail >= srq->rq.size) 2508c2ecf20Sopenharmony_ci tail = 0; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci srq->rq.kwq = tmp_rq.kwq; 2538c2ecf20Sopenharmony_ci if (udata) { 2548c2ecf20Sopenharmony_ci srq->rq.wq = tmp_rq.wq; 2558c2ecf20Sopenharmony_ci RDMA_WRITE_UAPI_ATOMIC(tmp_rq.wq->head, n); 2568c2ecf20Sopenharmony_ci RDMA_WRITE_UAPI_ATOMIC(tmp_rq.wq->tail, 0); 2578c2ecf20Sopenharmony_ci } else { 2588c2ecf20Sopenharmony_ci tmp_rq.kwq->head = n; 2598c2ecf20Sopenharmony_ci tmp_rq.kwq->tail = 0; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci srq->rq.size = size; 2628c2ecf20Sopenharmony_ci if (attr_mask & IB_SRQ_LIMIT) 2638c2ecf20Sopenharmony_ci srq->limit = attr->srq_limit; 2648c2ecf20Sopenharmony_ci spin_unlock_irq(&srq->rq.kwq->c_lock); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci vfree(owq); 2678c2ecf20Sopenharmony_ci kvfree(okwq); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (srq->ip) { 2708c2ecf20Sopenharmony_ci struct rvt_mmap_info *ip = srq->ip; 2718c2ecf20Sopenharmony_ci struct rvt_dev_info *dev = ib_to_rvt(srq->ibsrq.device); 2728c2ecf20Sopenharmony_ci u32 s = sizeof(struct rvt_rwq) + size * sz; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci rvt_update_mmap_info(dev, ip, s, tmp_rq.wq); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* 2778c2ecf20Sopenharmony_ci * Return the offset to mmap. 2788c2ecf20Sopenharmony_ci * See rvt_mmap() for details. 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_ci if (udata && udata->inlen >= sizeof(__u64)) { 2818c2ecf20Sopenharmony_ci ret = ib_copy_to_udata(udata, &ip->offset, 2828c2ecf20Sopenharmony_ci sizeof(ip->offset)); 2838c2ecf20Sopenharmony_ci if (ret) 2848c2ecf20Sopenharmony_ci return ret; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* 2888c2ecf20Sopenharmony_ci * Put user mapping info onto the pending list 2898c2ecf20Sopenharmony_ci * unless it already is on the list. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ci spin_lock_irq(&dev->pending_lock); 2928c2ecf20Sopenharmony_ci if (list_empty(&ip->pending_mmaps)) 2938c2ecf20Sopenharmony_ci list_add(&ip->pending_mmaps, 2948c2ecf20Sopenharmony_ci &dev->pending_mmaps); 2958c2ecf20Sopenharmony_ci spin_unlock_irq(&dev->pending_lock); 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci } else if (attr_mask & IB_SRQ_LIMIT) { 2988c2ecf20Sopenharmony_ci spin_lock_irq(&srq->rq.kwq->c_lock); 2998c2ecf20Sopenharmony_ci if (attr->srq_limit >= srq->rq.size) 3008c2ecf20Sopenharmony_ci ret = -EINVAL; 3018c2ecf20Sopenharmony_ci else 3028c2ecf20Sopenharmony_ci srq->limit = attr->srq_limit; 3038c2ecf20Sopenharmony_ci spin_unlock_irq(&srq->rq.kwq->c_lock); 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci return ret; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cibail_unlock: 3088c2ecf20Sopenharmony_ci spin_unlock_irq(&srq->rq.kwq->c_lock); 3098c2ecf20Sopenharmony_cibail_free: 3108c2ecf20Sopenharmony_ci rvt_free_rq(&tmp_rq); 3118c2ecf20Sopenharmony_ci return ret; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/** rvt_query_srq - query srq data 3158c2ecf20Sopenharmony_ci * @ibsrq: srq to query 3168c2ecf20Sopenharmony_ci * @attr: return info in attr 3178c2ecf20Sopenharmony_ci * 3188c2ecf20Sopenharmony_ci * Return: always 0 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ciint rvt_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci attr->max_wr = srq->rq.size - 1; 3258c2ecf20Sopenharmony_ci attr->max_sge = srq->rq.max_sge; 3268c2ecf20Sopenharmony_ci attr->srq_limit = srq->limit; 3278c2ecf20Sopenharmony_ci return 0; 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci/** 3318c2ecf20Sopenharmony_ci * rvt_destroy_srq - destory an srq 3328c2ecf20Sopenharmony_ci * @ibsrq: srq object to destroy 3338c2ecf20Sopenharmony_ci * 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ciint rvt_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); 3388c2ecf20Sopenharmony_ci struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci spin_lock(&dev->n_srqs_lock); 3418c2ecf20Sopenharmony_ci dev->n_srqs_allocated--; 3428c2ecf20Sopenharmony_ci spin_unlock(&dev->n_srqs_lock); 3438c2ecf20Sopenharmony_ci if (srq->ip) 3448c2ecf20Sopenharmony_ci kref_put(&srq->ip->ref, rvt_release_mmap_info); 3458c2ecf20Sopenharmony_ci kvfree(srq->rq.kwq); 3468c2ecf20Sopenharmony_ci return 0; 3478c2ecf20Sopenharmony_ci} 348