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