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->elem.index; 87 srq->rq.max_wr = init->attr.max_wr; 88 srq->rq.max_sge = init->attr.max_sge; 89 90 srq_wqe_size = rcv_wqe_size(srq->rq.max_sge); 91 92 spin_lock_init(&srq->rq.producer_lock); 93 spin_lock_init(&srq->rq.consumer_lock); 94 95 type = QUEUE_TYPE_FROM_CLIENT; 96 q = rxe_queue_init(rxe, &srq->rq.max_wr, 97 srq_wqe_size, type); 98 if (!q) { 99 pr_warn("unable to allocate queue for srq\n"); 100 return -ENOMEM; 101 } 102 103 srq->rq.queue = q; 104 105 err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, q->buf, 106 q->buf_size, &q->ip); 107 if (err) { 108 vfree(q->buf); 109 kfree(q); 110 return err; 111 } 112 113 if (uresp) { 114 if (copy_to_user(&uresp->srq_num, &srq->srq_num, 115 sizeof(uresp->srq_num))) { 116 rxe_queue_cleanup(q); 117 return -EFAULT; 118 } 119 } 120 121 return 0; 122 } 123 124 int rxe_srq_from_attr(struct rxe_dev *rxe, struct rxe_srq *srq, 125 struct ib_srq_attr *attr, enum ib_srq_attr_mask mask, 126 struct rxe_modify_srq_cmd *ucmd, struct ib_udata *udata) 127 { 128 int err; 129 struct rxe_queue *q = srq->rq.queue; 130 struct mminfo __user *mi = NULL; 131 132 if (mask & IB_SRQ_MAX_WR) { 133 /* 134 * This is completely screwed up, the response is supposed to 135 * be in the outbuf not like this. 136 */ 137 mi = u64_to_user_ptr(ucmd->mmap_info_addr); 138 139 err = rxe_queue_resize(q, &attr->max_wr, 140 rcv_wqe_size(srq->rq.max_sge), udata, mi, 141 &srq->rq.producer_lock, 142 &srq->rq.consumer_lock); 143 if (err) 144 goto err2; 145 } 146 147 if (mask & IB_SRQ_LIMIT) 148 srq->limit = attr->srq_limit; 149 150 return 0; 151 152 err2: 153 rxe_queue_cleanup(q); 154 srq->rq.queue = NULL; 155 return err; 156 } 157