Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /*
0003  * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
0004  * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
0005  */
0006 
0007 #include <linux/vmalloc.h>
0008 #include "rxe.h"
0009 #include "rxe_queue.h"
0010 
0011 int rxe_srq_chk_init(struct rxe_dev *rxe, struct ib_srq_init_attr *init)
0012 {
0013     struct ib_srq_attr *attr = &init->attr;
0014 
0015     if (attr->max_wr > rxe->attr.max_srq_wr) {
0016         pr_warn("max_wr(%d) > max_srq_wr(%d)\n",
0017             attr->max_wr, rxe->attr.max_srq_wr);
0018         goto err1;
0019     }
0020 
0021     if (attr->max_wr <= 0) {
0022         pr_warn("max_wr(%d) <= 0\n", attr->max_wr);
0023         goto err1;
0024     }
0025 
0026     if (attr->max_wr < RXE_MIN_SRQ_WR)
0027         attr->max_wr = RXE_MIN_SRQ_WR;
0028 
0029     if (attr->max_sge > rxe->attr.max_srq_sge) {
0030         pr_warn("max_sge(%d) > max_srq_sge(%d)\n",
0031             attr->max_sge, rxe->attr.max_srq_sge);
0032         goto err1;
0033     }
0034 
0035     if (attr->max_sge < RXE_MIN_SRQ_SGE)
0036         attr->max_sge = RXE_MIN_SRQ_SGE;
0037 
0038     return 0;
0039 
0040 err1:
0041     return -EINVAL;
0042 }
0043 
0044 int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq,
0045               struct ib_srq_init_attr *init, struct ib_udata *udata,
0046               struct rxe_create_srq_resp __user *uresp)
0047 {
0048     int err;
0049     int srq_wqe_size;
0050     struct rxe_queue *q;
0051     enum queue_type type;
0052 
0053     srq->ibsrq.event_handler    = init->event_handler;
0054     srq->ibsrq.srq_context      = init->srq_context;
0055     srq->limit      = init->attr.srq_limit;
0056     srq->srq_num        = srq->elem.index;
0057     srq->rq.max_wr      = init->attr.max_wr;
0058     srq->rq.max_sge     = init->attr.max_sge;
0059 
0060     srq_wqe_size        = rcv_wqe_size(srq->rq.max_sge);
0061 
0062     spin_lock_init(&srq->rq.producer_lock);
0063     spin_lock_init(&srq->rq.consumer_lock);
0064 
0065     type = QUEUE_TYPE_FROM_CLIENT;
0066     q = rxe_queue_init(rxe, &srq->rq.max_wr, srq_wqe_size, type);
0067     if (!q) {
0068         pr_warn("unable to allocate queue for srq\n");
0069         return -ENOMEM;
0070     }
0071 
0072     srq->rq.queue = q;
0073 
0074     err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, q->buf,
0075                q->buf_size, &q->ip);
0076     if (err) {
0077         vfree(q->buf);
0078         kfree(q);
0079         return err;
0080     }
0081 
0082     if (uresp) {
0083         if (copy_to_user(&uresp->srq_num, &srq->srq_num,
0084                  sizeof(uresp->srq_num))) {
0085             rxe_queue_cleanup(q);
0086             return -EFAULT;
0087         }
0088     }
0089 
0090     return 0;
0091 }
0092 
0093 int rxe_srq_chk_attr(struct rxe_dev *rxe, struct rxe_srq *srq,
0094              struct ib_srq_attr *attr, enum ib_srq_attr_mask mask)
0095 {
0096     if (srq->error) {
0097         pr_warn("srq in error state\n");
0098         goto err1;
0099     }
0100 
0101     if (mask & IB_SRQ_MAX_WR) {
0102         if (attr->max_wr > rxe->attr.max_srq_wr) {
0103             pr_warn("max_wr(%d) > max_srq_wr(%d)\n",
0104                 attr->max_wr, rxe->attr.max_srq_wr);
0105             goto err1;
0106         }
0107 
0108         if (attr->max_wr <= 0) {
0109             pr_warn("max_wr(%d) <= 0\n", attr->max_wr);
0110             goto err1;
0111         }
0112 
0113         if (srq->limit && (attr->max_wr < srq->limit)) {
0114             pr_warn("max_wr (%d) < srq->limit (%d)\n",
0115                 attr->max_wr, srq->limit);
0116             goto err1;
0117         }
0118 
0119         if (attr->max_wr < RXE_MIN_SRQ_WR)
0120             attr->max_wr = RXE_MIN_SRQ_WR;
0121     }
0122 
0123     if (mask & IB_SRQ_LIMIT) {
0124         if (attr->srq_limit > rxe->attr.max_srq_wr) {
0125             pr_warn("srq_limit(%d) > max_srq_wr(%d)\n",
0126                 attr->srq_limit, rxe->attr.max_srq_wr);
0127             goto err1;
0128         }
0129 
0130         if (attr->srq_limit > srq->rq.queue->buf->index_mask) {
0131             pr_warn("srq_limit (%d) > cur limit(%d)\n",
0132                 attr->srq_limit,
0133                 srq->rq.queue->buf->index_mask);
0134             goto err1;
0135         }
0136     }
0137 
0138     return 0;
0139 
0140 err1:
0141     return -EINVAL;
0142 }
0143 
0144 int rxe_srq_from_attr(struct rxe_dev *rxe, struct rxe_srq *srq,
0145               struct ib_srq_attr *attr, enum ib_srq_attr_mask mask,
0146               struct rxe_modify_srq_cmd *ucmd, struct ib_udata *udata)
0147 {
0148     int err;
0149     struct rxe_queue *q = srq->rq.queue;
0150     struct mminfo __user *mi = NULL;
0151 
0152     if (mask & IB_SRQ_MAX_WR) {
0153         /*
0154          * This is completely screwed up, the response is supposed to
0155          * be in the outbuf not like this.
0156          */
0157         mi = u64_to_user_ptr(ucmd->mmap_info_addr);
0158 
0159         err = rxe_queue_resize(q, &attr->max_wr,
0160                        rcv_wqe_size(srq->rq.max_sge), udata, mi,
0161                        &srq->rq.producer_lock,
0162                        &srq->rq.consumer_lock);
0163         if (err)
0164             goto err2;
0165     }
0166 
0167     if (mask & IB_SRQ_LIMIT)
0168         srq->limit = attr->srq_limit;
0169 
0170     return 0;
0171 
0172 err2:
0173     rxe_queue_cleanup(q);
0174     srq->rq.queue = NULL;
0175     return err;
0176 }
0177 
0178 void rxe_srq_cleanup(struct rxe_pool_elem *elem)
0179 {
0180     struct rxe_srq *srq = container_of(elem, typeof(*srq), elem);
0181 
0182     if (srq->pd)
0183         rxe_put(srq->pd);
0184 
0185     if (srq->rq.queue)
0186         rxe_queue_cleanup(srq->rq.queue);
0187 }