brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · fec87c9 Raw
134 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB2/*3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.5 */6#include <linux/vmalloc.h>7#include "rxe.h"8#include "rxe_loc.h"9#include "rxe_queue.h"10 11int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq,12		    int cqe, int comp_vector)13{14	int count;15 16	if (cqe <= 0) {17		rxe_dbg_dev(rxe, "cqe(%d) <= 0\n", cqe);18		goto err1;19	}20 21	if (cqe > rxe->attr.max_cqe) {22		rxe_dbg_dev(rxe, "cqe(%d) > max_cqe(%d)\n",23				cqe, rxe->attr.max_cqe);24		goto err1;25	}26 27	if (cq) {28		count = queue_count(cq->queue, QUEUE_TYPE_TO_CLIENT);29		if (cqe < count) {30			rxe_dbg_cq(cq, "cqe(%d) < current # elements in queue (%d)\n",31					cqe, count);32			goto err1;33		}34	}35 36	return 0;37 38err1:39	return -EINVAL;40}41 42int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe,43		     int comp_vector, struct ib_udata *udata,44		     struct rxe_create_cq_resp __user *uresp)45{46	int err;47	enum queue_type type;48 49	type = QUEUE_TYPE_TO_CLIENT;50	cq->queue = rxe_queue_init(rxe, &cqe,51			sizeof(struct rxe_cqe), type);52	if (!cq->queue) {53		rxe_dbg_dev(rxe, "unable to create cq\n");54		return -ENOMEM;55	}56 57	err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata,58			   cq->queue->buf, cq->queue->buf_size, &cq->queue->ip);59	if (err) {60		vfree(cq->queue->buf);61		kfree(cq->queue);62		return err;63	}64 65	cq->is_user = uresp;66 67	spin_lock_init(&cq->cq_lock);68	cq->ibcq.cqe = cqe;69	return 0;70}71 72int rxe_cq_resize_queue(struct rxe_cq *cq, int cqe,73			struct rxe_resize_cq_resp __user *uresp,74			struct ib_udata *udata)75{76	int err;77 78	err = rxe_queue_resize(cq->queue, (unsigned int *)&cqe,79			       sizeof(struct rxe_cqe), udata,80			       uresp ? &uresp->mi : NULL, NULL, &cq->cq_lock);81	if (!err)82		cq->ibcq.cqe = cqe;83 84	return err;85}86 87/* caller holds reference to cq */88int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)89{90	struct ib_event ev;91	int full;92	void *addr;93	unsigned long flags;94 95	spin_lock_irqsave(&cq->cq_lock, flags);96 97	full = queue_full(cq->queue, QUEUE_TYPE_TO_CLIENT);98	if (unlikely(full)) {99		rxe_err_cq(cq, "queue full\n");100		spin_unlock_irqrestore(&cq->cq_lock, flags);101		if (cq->ibcq.event_handler) {102			ev.device = cq->ibcq.device;103			ev.element.cq = &cq->ibcq;104			ev.event = IB_EVENT_CQ_ERR;105			cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);106		}107 108		return -EBUSY;109	}110 111	addr = queue_producer_addr(cq->queue, QUEUE_TYPE_TO_CLIENT);112	memcpy(addr, cqe, sizeof(*cqe));113 114	queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT);115 116	if ((cq->notify & IB_CQ_NEXT_COMP) ||117	    (cq->notify & IB_CQ_SOLICITED && solicited)) {118		cq->notify = 0;119		cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);120	}121 122	spin_unlock_irqrestore(&cq->cq_lock, flags);123 124	return 0;125}126 127void rxe_cq_cleanup(struct rxe_pool_elem *elem)128{129	struct rxe_cq *cq = container_of(elem, typeof(*cq), elem);130 131	if (cq->queue)132		rxe_queue_cleanup(cq->queue);133}134