1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved. 4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved. 5 */ 6 7 #include <linux/vmalloc.h> 8 #include "rxe.h" 9 #include "rxe_loc.h" 10 #include "rxe_queue.h" 11 12 int rxe_srq_chk_attr(struct rxe_dev *rxe, struct rxe_srq *srq, 13 struct ib_srq_attr *attr, enum ib_srq_attr_mask mask) 14 { 15 if (srq && srq->error) { 16 pr_warn("srq in error state\n"); 17 goto err1; 18 } 19 20 if (mask & IB_SRQ_MAX_WR) { 21 if (attr->max_wr > rxe->attr.max_srq_wr) { 22 pr_warn("max_wr(%d) > max_srq_wr(%d)\n", 23 attr->max_wr, rxe->attr.max_srq_wr); 24 goto err1; 25 } 26 27 if (attr->max_wr <= 0) { 28 pr_warn("max_wr(%d) <= 0\n", attr->max_wr); 29 goto err1; 30 } 31 32 if (srq && srq->limit && (attr->max_wr < srq->limit)) { 33 pr_warn("max_wr (%d) < srq->limit (%d)\n", 34 attr->max_wr, srq->limit); 35 goto err1; 36 } 37 38 if (attr->max_wr < RXE_MIN_SRQ_WR) 39 attr->max_wr = RXE_MIN_SRQ_WR; 40 } 41 42 if (mask & IB_SRQ_LIMIT) { 43 if (attr->srq_limit > rxe->attr.max_srq_wr) { 44 pr_warn("srq_limit(%d) > max_srq_wr(%d)\n", 45 attr->srq_limit, rxe->attr.max_srq_wr); 46 goto err1; 47 } 48 49 if (srq && (attr->srq_limit > srq->rq.queue->buf->index_mask)) { 50 pr_warn("srq_limit (%d) > cur limit(%d)\n", 51 attr->srq_limit, 52 srq->rq.queue->buf->index_mask); 53 goto err1; 54 } 55 } 56 57 if (mask == IB_SRQ_INIT_MASK) { 58 if (attr->max_sge > rxe->attr.max_srq_sge) { 59 pr_warn("max_sge(%d) > max_srq_sge(%d)\n", 60 attr->max_sge, rxe->attr.max_srq_sge); 61 goto err1; 62 } 63 64 if (attr->max_sge < RXE_MIN_SRQ_SGE) 65 attr->max_sge = RXE_MIN_SRQ_SGE; 66 } 67 68 return 0; 69 70 err1: 71 return -EINVAL; 72 } 73 74 int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq, 75 struct ib_srq_init_attr *init, struct ib_udata *udata, 76 struct rxe_create_srq_resp __user *uresp) 77 { 78 int err; 79 int srq_wqe_size; 80 struct rxe_queue *q; 81 enum queue_type type; 82 83 srq->ibsrq.event_handler = init->event_handler; 84 srq->ibsrq.srq_context = init->srq_context; 85 srq->limit = init->attr.srq_limit; 86 srq->srq_num = srq->pelem.index; 87 srq->rq.max_wr = init->attr.max_wr; 88 srq->rq.max_sge = init->attr.max_sge; 89 srq->rq.is_user = srq->is_user; 90 91 srq_wqe_size = rcv_wqe_size(srq->rq.max_sge); 92 93 spin_lock_init(&srq->rq.producer_lock); 94 spin_lock_init(&srq->rq.consumer_lock); 95 96 type = uresp ? QUEUE_TYPE_FROM_USER : QUEUE_TYPE_KERNEL; 97 q = rxe_queue_init(rxe, &srq->rq.max_wr, 98 srq_wqe_size, type); 99 if (!q) { 100 pr_warn("unable to allocate queue for srq\n"); 101 return -ENOMEM; 102 } 103 104 srq->rq.queue = q; 105 106 err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, q->buf, 107 q->buf_size, &q->ip); 108 if (err) { 109 vfree(q->buf); 110 kfree(q); 111 return err; 112 } 113 114 if (uresp) { 115 if (copy_to_user(&uresp->srq_num, &srq->srq_num, 116 sizeof(uresp->srq_num))) { 117 rxe_queue_cleanup(q); 118 return -EFAULT; 119 } 120 } 121 122 return 0; 123 } 124 125 int rxe_srq_from_attr(struct rxe_dev *rxe, struct rxe_srq *srq, 126 struct ib_srq_attr *attr, enum ib_srq_attr_mask mask, 127 struct rxe_modify_srq_cmd *ucmd, struct ib_udata *udata) 128 { 129 int err; 130 struct rxe_queue *q = srq->rq.queue; 131 struct mminfo __user *mi = NULL; 132 133 if (mask & IB_SRQ_MAX_WR) { 134 /* 135 * This is completely screwed up, the response is supposed to 136 * be in the outbuf not like this. 137 */ 138 mi = u64_to_user_ptr(ucmd->mmap_info_addr); 139 140 err = rxe_queue_resize(q, &attr->max_wr, 141 rcv_wqe_size(srq->rq.max_sge), udata, mi, 142 &srq->rq.producer_lock, 143 &srq->rq.consumer_lock); 144 if (err) 145 goto err2; 146 } 147 148 if (mask & IB_SRQ_LIMIT) 149 srq->limit = attr->srq_limit; 150 151 return 0; 152 153 err2: 154 rxe_queue_cleanup(q); 155 srq->rq.queue = NULL; 156 return err; 157 } 158