1b86efd96Sagiri /*
2b86efd96Sagiri  * CDDL HEADER START
3b86efd96Sagiri  *
4b86efd96Sagiri  * The contents of this file are subject to the terms of the
5b86efd96Sagiri  * Common Development and Distribution License (the "License").
6b86efd96Sagiri  * You may not use this file except in compliance with the License.
7b86efd96Sagiri  *
8b86efd96Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9b86efd96Sagiri  * or http://www.opensolaris.org/os/licensing.
10b86efd96Sagiri  * See the License for the specific language governing permissions
11b86efd96Sagiri  * and limitations under the License.
12b86efd96Sagiri  *
13b86efd96Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
14b86efd96Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15b86efd96Sagiri  * If applicable, add the following below this CDDL HEADER, with the
16b86efd96Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
17b86efd96Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
18b86efd96Sagiri  *
19b86efd96Sagiri  * CDDL HEADER END
20b86efd96Sagiri  */
21b86efd96Sagiri /*
220c19630bSagiri  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23b86efd96Sagiri  * Use is subject to license terms.
24b86efd96Sagiri  */
25b86efd96Sagiri /*
26b86efd96Sagiri  * Copyright (c) 2005 SilverStorm Technologies, Inc. All rights reserved.
27b86efd96Sagiri  *
28b86efd96Sagiri  * This software is available to you under a choice of one of two
29b86efd96Sagiri  * licenses.  You may choose to be licensed under the terms of the GNU
30b86efd96Sagiri  * General Public License (GPL) Version 2, available from the file
31b86efd96Sagiri  * COPYING in the main directory of this source tree, or the
32b86efd96Sagiri  * OpenIB.org BSD license below:
33b86efd96Sagiri  *
34b86efd96Sagiri  *     Redistribution and use in source and binary forms, with or
35b86efd96Sagiri  *     without modification, are permitted provided that the following
36b86efd96Sagiri  *     conditions are met:
37b86efd96Sagiri  *
38b86efd96Sagiri  *	- Redistributions of source code must retain the above
39b86efd96Sagiri  *	  copyright notice, this list of conditions and the following
40b86efd96Sagiri  *	  disclaimer.
41b86efd96Sagiri  *
42b86efd96Sagiri  *	- Redistributions in binary form must reproduce the above
43b86efd96Sagiri  *	  copyright notice, this list of conditions and the following
44b86efd96Sagiri  *	  disclaimer in the documentation and/or other materials
45b86efd96Sagiri  *	  provided with the distribution.
46b86efd96Sagiri  *
47b86efd96Sagiri  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48b86efd96Sagiri  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49b86efd96Sagiri  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50b86efd96Sagiri  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
51b86efd96Sagiri  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
52b86efd96Sagiri  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53b86efd96Sagiri  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54b86efd96Sagiri  * SOFTWARE.
55b86efd96Sagiri  *
56b86efd96Sagiri  */
57b86efd96Sagiri /*
58b86efd96Sagiri  * Sun elects to include this software in Sun product
59b86efd96Sagiri  * under the OpenIB BSD license.
60b86efd96Sagiri  *
61b86efd96Sagiri  *
62b86efd96Sagiri  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
63b86efd96Sagiri  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64b86efd96Sagiri  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65b86efd96Sagiri  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
66b86efd96Sagiri  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
67b86efd96Sagiri  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
68b86efd96Sagiri  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
69b86efd96Sagiri  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
70b86efd96Sagiri  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
71b86efd96Sagiri  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
72b86efd96Sagiri  * POSSIBILITY OF SUCH DAMAGE.
73b86efd96Sagiri  */
74b86efd96Sagiri 
75b86efd96Sagiri #include <sys/ib/clients/rds/rdsib_cm.h>
76b86efd96Sagiri #include <sys/ib/clients/rds/rdsib_ib.h>
77b86efd96Sagiri #include <sys/ib/clients/rds/rdsib_buf.h>
78b86efd96Sagiri #include <sys/ib/clients/rds/rdsib_ep.h>
79b86efd96Sagiri #include <sys/ib/clients/rds/rds_kstat.h>
80b86efd96Sagiri 
81b86efd96Sagiri /*
82b86efd96Sagiri  * This File contains the buffer management code
83b86efd96Sagiri  */
84b86efd96Sagiri 
85b86efd96Sagiri #define	DUMP_USER_PARAMS()	\
865763ba1eSagiri 	RDS_DPRINTF3(LABEL, "MaxNodes = %d", MaxNodes); \
87b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "UserBufferSize = %d", UserBufferSize); \
88b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "RdsPktSize = %d", RdsPktSize); \
89b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "MaxDataSendBuffers = %d", MaxDataSendBuffers); \
90b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "MaxDataRecvBuffers = %d", MaxDataRecvBuffers); \
91b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "MaxCtrlSendBuffers = %d", MaxCtrlSendBuffers); \
92b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "MaxCtrlRecvBuffers = %d", MaxCtrlRecvBuffers); \
93b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "DataRecvBufferLWM = %d", DataRecvBufferLWM); \
94b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "PendingRxPktsHWM = %d", PendingRxPktsHWM); \
95b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "MinRnrRetry = %d", MinRnrRetry)
96b86efd96Sagiri 
970c19630bSagiri uint_t	rds_nbuffers_to_putback;
980c19630bSagiri 
99b86efd96Sagiri static void
rds_free_mblk(char * arg)100b86efd96Sagiri rds_free_mblk(char *arg)
101b86efd96Sagiri {
102b86efd96Sagiri 	rds_buf_t *bp = (rds_buf_t *)(uintptr_t)arg;
103b86efd96Sagiri 
104b86efd96Sagiri 	/* Free the recv buffer */
105b86efd96Sagiri 	RDS_DPRINTF4("rds_free_mblk", "Enter: BP(%p)", bp);
106b86efd96Sagiri 	ASSERT(bp->buf_state == RDS_RCVBUF_ONSOCKQ);
107b86efd96Sagiri 	rds_free_recv_buf(bp, 1);
108b86efd96Sagiri 	RDS_DECR_RXPKTS_PEND(1);
109b86efd96Sagiri 	RDS_DPRINTF4("rds_free_mblk", "Return: BP(%p)", bp);
110b86efd96Sagiri }
111b86efd96Sagiri 
112b86efd96Sagiri void
rds_free_recv_caches(rds_state_t * statep)113b86efd96Sagiri rds_free_recv_caches(rds_state_t *statep)
114b86efd96Sagiri {
115b86efd96Sagiri 	rds_hca_t	*hcap;
116b86efd96Sagiri 	int		ret;
117b86efd96Sagiri 
118b86efd96Sagiri 	RDS_DPRINTF4("rds_free_recv_caches", "Enter");
119b86efd96Sagiri 
120b86efd96Sagiri 	mutex_enter(&rds_dpool.pool_lock);
121b86efd96Sagiri 	if (rds_dpool.pool_memp == NULL) {
122b86efd96Sagiri 		RDS_DPRINTF2("rds_free_recv_caches", "Caches are empty");
123b86efd96Sagiri 		mutex_exit(&rds_dpool.pool_lock);
124b86efd96Sagiri 		return;
125b86efd96Sagiri 	}
126b86efd96Sagiri 
127b86efd96Sagiri 	/*
128b86efd96Sagiri 	 * All buffers must have been freed as all sessions are closed
129b86efd96Sagiri 	 * and destroyed
130b86efd96Sagiri 	 */
131b86efd96Sagiri 	ASSERT(rds_dpool.pool_nbusy == 0);
132b86efd96Sagiri 	RDS_DPRINTF2("rds_free_recv_caches", "Data Pool has "
133b86efd96Sagiri 	    "pending buffers: %d", rds_dpool.pool_nbusy);
134b86efd96Sagiri 	while (rds_dpool.pool_nbusy != 0) {
135b86efd96Sagiri 		mutex_exit(&rds_dpool.pool_lock);
136b86efd96Sagiri 		delay(drv_usectohz(1000000));
137b86efd96Sagiri 		mutex_enter(&rds_dpool.pool_lock);
138b86efd96Sagiri 	}
139b86efd96Sagiri 
140b86efd96Sagiri 	hcap = statep->rds_hcalistp;
141b86efd96Sagiri 	while (hcap != NULL) {
142b86efd96Sagiri 		if (hcap->hca_mrhdl != NULL) {
143b86efd96Sagiri 			ret = ibt_deregister_mr(hcap->hca_hdl,
144b86efd96Sagiri 			    hcap->hca_mrhdl);
145b86efd96Sagiri 			if (ret == IBT_SUCCESS) {
146b86efd96Sagiri 				hcap->hca_mrhdl = NULL;
147b86efd96Sagiri 				hcap->hca_lkey = 0;
148b86efd96Sagiri 				hcap->hca_rkey = 0;
149b86efd96Sagiri 			} else {
150b86efd96Sagiri 				RDS_DPRINTF2(LABEL, "ibt_deregister_mr "
151b86efd96Sagiri 				    "failed: %d, mrhdl: 0x%p", ret,
152b86efd96Sagiri 				    hcap->hca_mrhdl);
153b86efd96Sagiri 			}
154b86efd96Sagiri 		}
155b86efd96Sagiri 		hcap = hcap->hca_nextp;
156b86efd96Sagiri 	}
157b86efd96Sagiri 
158b86efd96Sagiri 	kmem_free(rds_dpool.pool_bufmemp, (rds_dpool.pool_nbuffers +
159b86efd96Sagiri 	    rds_cpool.pool_nbuffers) * sizeof (rds_buf_t));
160b86efd96Sagiri 	rds_dpool.pool_bufmemp = NULL;
161b86efd96Sagiri 
162b86efd96Sagiri 	kmem_free(rds_dpool.pool_memp, rds_dpool.pool_memsize);
163b86efd96Sagiri 	rds_dpool.pool_memp = NULL;
164b86efd96Sagiri 
165b86efd96Sagiri 	mutex_exit(&rds_dpool.pool_lock);
166b86efd96Sagiri 
167b86efd96Sagiri 	RDS_DPRINTF4("rds_free_recv_caches", "Return");
168b86efd96Sagiri }
169b86efd96Sagiri 
170b86efd96Sagiri int
rds_init_recv_caches(rds_state_t * statep)171b86efd96Sagiri rds_init_recv_caches(rds_state_t *statep)
172b86efd96Sagiri {
173b86efd96Sagiri 	uint8_t		*mp;
174b86efd96Sagiri 	rds_buf_t	*bp;
175b86efd96Sagiri 	rds_hca_t	*hcap;
176b86efd96Sagiri 	uint32_t	nsessions;
177b86efd96Sagiri 	uint_t		ix;
1785763ba1eSagiri 	uint_t		nctrlrx;
179b86efd96Sagiri 	uint8_t		*memp;
180b86efd96Sagiri 	uint_t		memsize, nbuf;
181b86efd96Sagiri 	rds_buf_t	*bufmemp;
182b86efd96Sagiri 	ibt_mr_attr_t	mem_attr;
183b86efd96Sagiri 	ibt_mr_desc_t	mem_desc;
184b86efd96Sagiri 	int		ret;
185b86efd96Sagiri 
186b86efd96Sagiri 	RDS_DPRINTF4("rds_init_recv_caches", "Enter");
187b86efd96Sagiri 
188b86efd96Sagiri 	DUMP_USER_PARAMS();
189b86efd96Sagiri 
190b86efd96Sagiri 	mutex_enter(&rds_dpool.pool_lock);
191b86efd96Sagiri 	if (rds_dpool.pool_memp != NULL) {
192b86efd96Sagiri 		RDS_DPRINTF2("rds_init_recv_caches", "Pools are already "
193b86efd96Sagiri 		    "initialized");
194b86efd96Sagiri 		mutex_exit(&rds_dpool.pool_lock);
195b86efd96Sagiri 		return (0);
196b86efd96Sagiri 	}
197b86efd96Sagiri 
198b86efd96Sagiri 	/*
199b86efd96Sagiri 	 * High water mark for the receive buffers in the system. If the
200b86efd96Sagiri 	 * number of buffers used crosses this mark then all sockets in
201b86efd96Sagiri 	 * would be stalled. The port quota for the sockets is set based
202b86efd96Sagiri 	 * on this limit.
203b86efd96Sagiri 	 */
2045763ba1eSagiri 	rds_rx_pkts_pending_hwm = (PendingRxPktsHWM * NDataRX)/100;
205b86efd96Sagiri 
2060c19630bSagiri 	rds_nbuffers_to_putback = min(MaxCtrlRecvBuffers, MaxDataRecvBuffers);
2070c19630bSagiri 
208b86efd96Sagiri 	/* nsessions can never be less than 1 */
2095763ba1eSagiri 	nsessions = MaxNodes - 1;
2100c19630bSagiri 	nctrlrx = (nsessions + 1) * MaxCtrlRecvBuffers * 2;
211b86efd96Sagiri 
212b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "Number of Possible Sessions: %d", nsessions);
213b86efd96Sagiri 
214b86efd96Sagiri 	/* Add the hdr */
215b86efd96Sagiri 	RdsPktSize = UserBufferSize + RDS_DATA_HDR_SZ;
216b86efd96Sagiri 
2175763ba1eSagiri 	memsize = (NDataRX * RdsPktSize) + (nctrlrx * RDS_CTRLPKT_SIZE);
2185763ba1eSagiri 	nbuf = NDataRX + nctrlrx;
219b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "RDS Buffer Pool Memory: %lld", memsize);
220b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "Total Buffers: %d", nbuf);
221b86efd96Sagiri 
222b86efd96Sagiri 	memp = (uint8_t *)kmem_zalloc(memsize, KM_NOSLEEP);
223b86efd96Sagiri 	if (memp == NULL) {
224b86efd96Sagiri 		RDS_DPRINTF1(LABEL, "RDS Memory allocation failed");
225b86efd96Sagiri 		mutex_exit(&rds_dpool.pool_lock);
226b86efd96Sagiri 		return (-1);
227b86efd96Sagiri 	}
228b86efd96Sagiri 
229b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "RDS Buffer Entries Memory: %lld",
230b86efd96Sagiri 	    nbuf * sizeof (rds_buf_t));
231b86efd96Sagiri 
232b86efd96Sagiri 	/* allocate memory for buffer entries */
233b86efd96Sagiri 	bufmemp = (rds_buf_t *)kmem_zalloc(nbuf * sizeof (rds_buf_t),
234b86efd96Sagiri 	    KM_SLEEP);
235b86efd96Sagiri 
236b86efd96Sagiri 	/* register the memory with all HCAs */
237b86efd96Sagiri 	mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)memp;
238b86efd96Sagiri 	mem_attr.mr_len = memsize;
239b86efd96Sagiri 	mem_attr.mr_as = NULL;
240b86efd96Sagiri 	mem_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
241b86efd96Sagiri 
24200a3eaf3SRamaswamy Tummala 	rw_enter(&statep->rds_hca_lock, RW_WRITER);
24300a3eaf3SRamaswamy Tummala 
244b86efd96Sagiri 	hcap = statep->rds_hcalistp;
245b86efd96Sagiri 	while (hcap != NULL) {
24600a3eaf3SRamaswamy Tummala 		if (hcap->hca_state != RDS_HCA_STATE_OPEN) {
24700a3eaf3SRamaswamy Tummala 			hcap = hcap->hca_nextp;
24800a3eaf3SRamaswamy Tummala 			continue;
24900a3eaf3SRamaswamy Tummala 		}
25000a3eaf3SRamaswamy Tummala 
251b86efd96Sagiri 		ret = ibt_register_mr(hcap->hca_hdl, hcap->hca_pdhdl,
252b86efd96Sagiri 		    &mem_attr, &hcap->hca_mrhdl, &mem_desc);
253b86efd96Sagiri 		if (ret != IBT_SUCCESS) {
254b86efd96Sagiri 			RDS_DPRINTF2(LABEL, "ibt_register_mr failed: %d", ret);
255559d851dSagiri 			hcap = statep->rds_hcalistp;
256559d851dSagiri 			while ((hcap) && (hcap->hca_mrhdl != NULL)) {
257559d851dSagiri 				ret = ibt_deregister_mr(hcap->hca_hdl,
258559d851dSagiri 				    hcap->hca_mrhdl);
259559d851dSagiri 				if (ret == IBT_SUCCESS) {
260559d851dSagiri 					hcap->hca_mrhdl = NULL;
261559d851dSagiri 					hcap->hca_lkey = 0;
262559d851dSagiri 					hcap->hca_rkey = 0;
263559d851dSagiri 				} else {
264559d851dSagiri 					RDS_DPRINTF2(LABEL, "ibt_deregister_mr "
265559d851dSagiri 					    "failed: %d, mrhdl: 0x%p", ret,
266559d851dSagiri 					    hcap->hca_mrhdl);
267559d851dSagiri 				}
268559d851dSagiri 				hcap = hcap->hca_nextp;
269559d851dSagiri 			}
270559d851dSagiri 			kmem_free(bufmemp, nbuf * sizeof (rds_buf_t));
271559d851dSagiri 			kmem_free(memp, memsize);
27200a3eaf3SRamaswamy Tummala 			rw_exit(&statep->rds_hca_lock);
273559d851dSagiri 			mutex_exit(&rds_dpool.pool_lock);
274b86efd96Sagiri 			return (-1);
275b86efd96Sagiri 		}
276b86efd96Sagiri 
27700a3eaf3SRamaswamy Tummala 		hcap->hca_state = RDS_HCA_STATE_MEM_REGISTERED;
278b86efd96Sagiri 		hcap->hca_lkey = mem_desc.md_lkey;
279b86efd96Sagiri 		hcap->hca_rkey = mem_desc.md_rkey;
280b86efd96Sagiri 
281b86efd96Sagiri 		hcap = hcap->hca_nextp;
282b86efd96Sagiri 	}
28300a3eaf3SRamaswamy Tummala 	rw_exit(&statep->rds_hca_lock);
284b86efd96Sagiri 
285b86efd96Sagiri 	/* Initialize data pool */
286b86efd96Sagiri 	rds_dpool.pool_memp = memp;
287b86efd96Sagiri 	rds_dpool.pool_memsize = memsize;
288b86efd96Sagiri 	rds_dpool.pool_bufmemp = bufmemp;
2895763ba1eSagiri 	rds_dpool.pool_nbuffers = NDataRX;
290b86efd96Sagiri 	rds_dpool.pool_nbusy = 0;
2915763ba1eSagiri 	rds_dpool.pool_nfree = NDataRX;
292b86efd96Sagiri 
293b86efd96Sagiri 	/* chain the buffers */
294b86efd96Sagiri 	mp = memp;
295b86efd96Sagiri 	bp = bufmemp;
2965763ba1eSagiri 	for (ix = 0; ix < NDataRX; ix++) {
297b86efd96Sagiri 		bp[ix].buf_nextp = &bp[ix + 1];
298b86efd96Sagiri 		bp[ix].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
299b86efd96Sagiri 		bp[ix].buf_state = RDS_RCVBUF_FREE;
300b86efd96Sagiri 		bp[ix].buf_frtn.free_func = rds_free_mblk;
301b86efd96Sagiri 		bp[ix].buf_frtn.free_arg = (char *)&bp[ix];
302b86efd96Sagiri 		mp = mp + RdsPktSize;
303b86efd96Sagiri 	}
3045763ba1eSagiri 	bp[NDataRX - 1].buf_nextp = NULL;
305b86efd96Sagiri 	rds_dpool.pool_headp = &bp[0];
3065763ba1eSagiri 	rds_dpool.pool_tailp = &bp[NDataRX - 1];
307b86efd96Sagiri 
308b86efd96Sagiri 	/* Initialize ctrl pool */
309b86efd96Sagiri 	rds_cpool.pool_nbuffers = nctrlrx;
310b86efd96Sagiri 	rds_cpool.pool_nbusy = 0;
311b86efd96Sagiri 	rds_cpool.pool_nfree = nctrlrx;
312b86efd96Sagiri 
313b86efd96Sagiri 	/* chain the buffers */
3145763ba1eSagiri 	for (ix = NDataRX; ix < nbuf - 1; ix++) {
315b86efd96Sagiri 		bp[ix].buf_nextp = &bp[ix + 1];
316b86efd96Sagiri 		bp[ix].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
317b86efd96Sagiri 		mp = mp + RDS_CTRLPKT_SIZE;
318b86efd96Sagiri 	}
319b86efd96Sagiri 	bp[nbuf - 1].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
320b86efd96Sagiri 	bp[nbuf - 1].buf_nextp = NULL;
3215763ba1eSagiri 	rds_cpool.pool_headp = &bp[NDataRX];
322b86efd96Sagiri 	rds_cpool.pool_tailp = &bp[nbuf - 1];
323b86efd96Sagiri 
324b86efd96Sagiri 	mutex_exit(&rds_dpool.pool_lock);
325b86efd96Sagiri 
326b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "rdsmemp start: %p end: %p", memp, mp);
327b86efd96Sagiri 	RDS_DPRINTF4("rds_init_recv_caches", "Return");
328b86efd96Sagiri 	return (0);
329b86efd96Sagiri }
330b86efd96Sagiri 
33100a3eaf3SRamaswamy Tummala rds_hca_t *rds_lkup_hca(ib_guid_t hca_guid);
33200a3eaf3SRamaswamy Tummala 
333b86efd96Sagiri void
rds_free_send_pool(rds_ep_t * ep)334b86efd96Sagiri rds_free_send_pool(rds_ep_t *ep)
335b86efd96Sagiri {
336b86efd96Sagiri 	rds_bufpool_t   *pool;
337b86efd96Sagiri 	rds_hca_t	*hcap;
338b86efd96Sagiri 	int		ret;
339b86efd96Sagiri 
340b86efd96Sagiri 	pool = &ep->ep_sndpool;
341b86efd96Sagiri 
342b86efd96Sagiri 	mutex_enter(&pool->pool_lock);
343b86efd96Sagiri 	if (pool->pool_memp == NULL) {
344b86efd96Sagiri 		mutex_exit(&pool->pool_lock);
345b86efd96Sagiri 		RDS_DPRINTF2("rds_free_send_pool",
346b86efd96Sagiri 		    "EP(%p) DOUBLE Free on Send Pool", ep);
347b86efd96Sagiri 		return;
348b86efd96Sagiri 	}
349b86efd96Sagiri 
350b86efd96Sagiri 	/* get the hcap for the HCA hosting this channel */
35100a3eaf3SRamaswamy Tummala 	hcap = rds_lkup_hca(ep->ep_hca_guid);
352b86efd96Sagiri 	if (hcap == NULL) {
353b86efd96Sagiri 		RDS_DPRINTF2("rds_free_send_pool", "HCA (0x%llx) not found",
354b86efd96Sagiri 		    ep->ep_hca_guid);
355b86efd96Sagiri 	} else {
356b86efd96Sagiri 		ret = ibt_deregister_mr(hcap->hca_hdl, ep->ep_snd_mrhdl);
357b86efd96Sagiri 		if (ret != IBT_SUCCESS) {
358b86efd96Sagiri 			RDS_DPRINTF2(LABEL,
359b86efd96Sagiri 			    "ibt_deregister_mr failed: %d, mrhdl: 0x%p",
360b86efd96Sagiri 			    ret, ep->ep_snd_mrhdl);
361b86efd96Sagiri 		}
362b86efd96Sagiri 
363b86efd96Sagiri 		if (ep->ep_ack_addr) {
364b86efd96Sagiri 			ret = ibt_deregister_mr(hcap->hca_hdl, ep->ep_ackhdl);
365b86efd96Sagiri 			if (ret != IBT_SUCCESS) {
366b86efd96Sagiri 				RDS_DPRINTF2(LABEL,
367b86efd96Sagiri 				    "ibt_deregister_mr ackhdl failed: %d, "
368b86efd96Sagiri 				    "mrhdl: 0x%p", ret, ep->ep_ackhdl);
369b86efd96Sagiri 			}
370b86efd96Sagiri 
371b86efd96Sagiri 			kmem_free((void *)ep->ep_ack_addr, sizeof (uintptr_t));
372*accc2981SToomas Soome 			ep->ep_ack_addr = (uintptr_t)NULL;
373b86efd96Sagiri 		}
374b86efd96Sagiri 	}
375b86efd96Sagiri 
376b86efd96Sagiri 	kmem_free(pool->pool_memp, pool->pool_memsize);
377b86efd96Sagiri 	kmem_free(pool->pool_bufmemp,
378b86efd96Sagiri 	    pool->pool_nbuffers * sizeof (rds_buf_t));
379b86efd96Sagiri 	pool->pool_memp = NULL;
380b86efd96Sagiri 	pool->pool_bufmemp = NULL;
381b86efd96Sagiri 	mutex_exit(&pool->pool_lock);
382b86efd96Sagiri }
383b86efd96Sagiri 
384b86efd96Sagiri int
rds_init_send_pool(rds_ep_t * ep,ib_guid_t hca_guid)3858257fab9Sagiri rds_init_send_pool(rds_ep_t *ep, ib_guid_t hca_guid)
386b86efd96Sagiri {
387b86efd96Sagiri 	uint8_t		*mp;
388b86efd96Sagiri 	rds_buf_t	*bp;
389b86efd96Sagiri 	rds_hca_t	*hcap;
390b86efd96Sagiri 	uint_t		ix, rcv_len;
391b86efd96Sagiri 	ibt_mr_attr_t   mem_attr;
392b86efd96Sagiri 	ibt_mr_desc_t   mem_desc;
393b86efd96Sagiri 	uint8_t		*memp;
394b86efd96Sagiri 	rds_buf_t	*bufmemp;
395*accc2981SToomas Soome 	uintptr_t	ack_addr = (uintptr_t)NULL;
396b86efd96Sagiri 	uint_t		memsize;
397b86efd96Sagiri 	uint_t		nbuf;
398b86efd96Sagiri 	rds_bufpool_t   *spool;
399b86efd96Sagiri 	rds_data_hdr_t	*pktp;
400b86efd96Sagiri 	int		ret;
401b86efd96Sagiri 
402b86efd96Sagiri 	RDS_DPRINTF2("rds_init_send_pool", "Enter");
403b86efd96Sagiri 
404b86efd96Sagiri 	spool = &ep->ep_sndpool;
405b86efd96Sagiri 
406b86efd96Sagiri 	ASSERT(spool->pool_memp == NULL);
4078257fab9Sagiri 	ASSERT(ep->ep_hca_guid == 0);
408b86efd96Sagiri 
409b86efd96Sagiri 	/* get the hcap for the HCA hosting this channel */
4108257fab9Sagiri 	hcap = rds_get_hcap(rdsib_statep, hca_guid);
411b86efd96Sagiri 	if (hcap == NULL) {
412b86efd96Sagiri 		RDS_DPRINTF2("rds_init_send_pool", "HCA (0x%llx) not found",
4138257fab9Sagiri 		    hca_guid);
414b86efd96Sagiri 		return (-1);
415b86efd96Sagiri 	}
416b86efd96Sagiri 
417b86efd96Sagiri 	if (ep->ep_type == RDS_EP_TYPE_DATA) {
418b86efd96Sagiri 		spool->pool_nbuffers = MaxDataSendBuffers;
419b86efd96Sagiri 		spool->pool_nbusy = 0;
420b86efd96Sagiri 		spool->pool_nfree = MaxDataSendBuffers;
421b86efd96Sagiri 		memsize = (MaxDataSendBuffers * RdsPktSize) +
422b86efd96Sagiri 		    sizeof (uintptr_t);
423b86efd96Sagiri 		rcv_len = RdsPktSize;
424b86efd96Sagiri 	} else {
425b86efd96Sagiri 		spool->pool_nbuffers = MaxCtrlSendBuffers;
426b86efd96Sagiri 		spool->pool_nbusy = 0;
427b86efd96Sagiri 		spool->pool_nfree = MaxCtrlSendBuffers;
428b86efd96Sagiri 		memsize = MaxCtrlSendBuffers * RDS_CTRLPKT_SIZE;
429b86efd96Sagiri 		rcv_len = RDS_CTRLPKT_SIZE;
430b86efd96Sagiri 	}
431b86efd96Sagiri 	nbuf = spool->pool_nbuffers;
432b86efd96Sagiri 
433b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "RDS Send Pool Memory: %lld", memsize);
434b86efd96Sagiri 
435b86efd96Sagiri 	memp = (uint8_t *)kmem_zalloc(memsize, KM_NOSLEEP);
436b86efd96Sagiri 	if (memp == NULL) {
437b86efd96Sagiri 		RDS_DPRINTF1(LABEL, "RDS Send Memory allocation failed");
438b86efd96Sagiri 		return (-1);
439b86efd96Sagiri 	}
440b86efd96Sagiri 
441b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "RDS Buffer Entries Memory: %lld",
442b86efd96Sagiri 	    nbuf * sizeof (rds_buf_t));
443b86efd96Sagiri 
444b86efd96Sagiri 	/* allocate memory for buffer entries */
445b86efd96Sagiri 	bufmemp = (rds_buf_t *)kmem_zalloc(nbuf * sizeof (rds_buf_t),
446b86efd96Sagiri 	    KM_SLEEP);
447b86efd96Sagiri 
448b86efd96Sagiri 	if (ep->ep_type == RDS_EP_TYPE_DATA) {
449b86efd96Sagiri 		ack_addr = (uintptr_t)kmem_zalloc(sizeof (uintptr_t), KM_SLEEP);
450b86efd96Sagiri 
451b86efd96Sagiri 		/* register the memory with the HCA for this channel */
452b86efd96Sagiri 		mem_attr.mr_vaddr = (ib_vaddr_t)ack_addr;
453b86efd96Sagiri 		mem_attr.mr_len = sizeof (uintptr_t);
454b86efd96Sagiri 		mem_attr.mr_as = NULL;
455b86efd96Sagiri 		mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE |
456b86efd96Sagiri 		    IBT_MR_ENABLE_REMOTE_WRITE;
457b86efd96Sagiri 
458b86efd96Sagiri 		ret = ibt_register_mr(hcap->hca_hdl, hcap->hca_pdhdl,
459b86efd96Sagiri 		    &mem_attr, &ep->ep_ackhdl, &mem_desc);
460b86efd96Sagiri 		if (ret != IBT_SUCCESS) {
461b86efd96Sagiri 			RDS_DPRINTF2("rds_init_send_pool",
462b86efd96Sagiri 			    "EP(%p): ibt_register_mr for ack failed: %d",
463b86efd96Sagiri 			    ep, ret);
464b86efd96Sagiri 			kmem_free(memp, memsize);
465b86efd96Sagiri 			kmem_free(bufmemp, nbuf * sizeof (rds_buf_t));
466b86efd96Sagiri 			kmem_free((void *)ack_addr, sizeof (uintptr_t));
467b86efd96Sagiri 			return (-1);
468b86efd96Sagiri 		}
469b86efd96Sagiri 		ep->ep_ack_rkey = mem_desc.md_rkey;
470b86efd96Sagiri 		ep->ep_ack_addr = ack_addr;
471b86efd96Sagiri 	}
472b86efd96Sagiri 
473b86efd96Sagiri 	/* register the memory with the HCA for this channel */
474b86efd96Sagiri 	mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)memp;
475b86efd96Sagiri 	mem_attr.mr_len = memsize;
476b86efd96Sagiri 	mem_attr.mr_as = NULL;
477b86efd96Sagiri 	mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
478b86efd96Sagiri 
479b86efd96Sagiri 	ret = ibt_register_mr(hcap->hca_hdl, hcap->hca_pdhdl,
480b86efd96Sagiri 	    &mem_attr, &ep->ep_snd_mrhdl, &mem_desc);
481b86efd96Sagiri 	if (ret != IBT_SUCCESS) {
482b86efd96Sagiri 		RDS_DPRINTF2("rds_init_send_pool", "EP(%p): ibt_register_mr "
483b86efd96Sagiri 		    "failed: %d", ep, ret);
484b86efd96Sagiri 		kmem_free(memp, memsize);
485b86efd96Sagiri 		kmem_free(bufmemp, nbuf * sizeof (rds_buf_t));
486*accc2981SToomas Soome 		if (ack_addr != (uintptr_t)NULL)
487b86efd96Sagiri 			kmem_free((void *)ack_addr, sizeof (uintptr_t));
488b86efd96Sagiri 		return (-1);
489b86efd96Sagiri 	}
490b86efd96Sagiri 	ep->ep_snd_lkey = mem_desc.md_lkey;
491b86efd96Sagiri 
492b86efd96Sagiri 
493b86efd96Sagiri 	/* Initialize the pool */
494b86efd96Sagiri 	spool->pool_memp = memp;
495b86efd96Sagiri 	spool->pool_memsize = memsize;
496b86efd96Sagiri 	spool->pool_bufmemp = bufmemp;
497b86efd96Sagiri 	spool->pool_sqpoll_pending = B_FALSE;
498b86efd96Sagiri 
499b86efd96Sagiri 	/* chain the buffers and initialize them */
500b86efd96Sagiri 	mp = memp;
501b86efd96Sagiri 	bp = bufmemp;
502b86efd96Sagiri 
503b86efd96Sagiri 	if (ep->ep_type == RDS_EP_TYPE_DATA) {
504b86efd96Sagiri 		for (ix = 0; ix < nbuf - 1; ix++) {
505b86efd96Sagiri 			bp[ix].buf_nextp = &bp[ix + 1];
506b86efd96Sagiri 			bp[ix].buf_ep = ep;
507b86efd96Sagiri 			bp[ix].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
508b86efd96Sagiri 			bp[ix].buf_ds.ds_key = ep->ep_snd_lkey;
509b86efd96Sagiri 			bp[ix].buf_state = RDS_SNDBUF_FREE;
510b86efd96Sagiri 			pktp = (rds_data_hdr_t *)(uintptr_t)mp;
511b86efd96Sagiri 			pktp->dh_bufid = (uintptr_t)&bp[ix];
512b86efd96Sagiri 			mp = mp + rcv_len;
513b86efd96Sagiri 		}
514b86efd96Sagiri 		bp[nbuf - 1].buf_nextp = NULL;
515b86efd96Sagiri 		bp[nbuf - 1].buf_ep = ep;
516b86efd96Sagiri 		bp[nbuf - 1].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
517b86efd96Sagiri 		bp[nbuf - 1].buf_ds.ds_key = ep->ep_snd_lkey;
518b86efd96Sagiri 		bp[nbuf - 1].buf_state = RDS_SNDBUF_FREE;
519b86efd96Sagiri 		pktp = (rds_data_hdr_t *)(uintptr_t)mp;
520b86efd96Sagiri 		pktp->dh_bufid = (uintptr_t)&bp[nbuf - 1];
521b86efd96Sagiri 
522b86efd96Sagiri 		spool->pool_headp = &bp[0];
523b86efd96Sagiri 		spool->pool_tailp = &bp[nbuf - 1];
524b86efd96Sagiri 
525b86efd96Sagiri 		mp = mp + rcv_len;
526b86efd96Sagiri 		ep->ep_ackds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
527b86efd96Sagiri 		ep->ep_ackds.ds_key = ep->ep_snd_lkey;
528b86efd96Sagiri 		ep->ep_ackds.ds_len = sizeof (uintptr_t);
529b86efd96Sagiri 
530b86efd96Sagiri 		*(uintptr_t *)ep->ep_ack_addr = (uintptr_t)spool->pool_tailp;
531b86efd96Sagiri 	} else {
532b86efd96Sagiri 		/* control send pool */
533b86efd96Sagiri 		for (ix = 0; ix < nbuf - 1; ix++) {
534b86efd96Sagiri 			bp[ix].buf_nextp = &bp[ix + 1];
535b86efd96Sagiri 			bp[ix].buf_ep = ep;
536b86efd96Sagiri 			bp[ix].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
537b86efd96Sagiri 			bp[ix].buf_ds.ds_key = ep->ep_snd_lkey;
538b86efd96Sagiri 			bp[ix].buf_state = RDS_SNDBUF_FREE;
539b86efd96Sagiri 			mp = mp + rcv_len;
540b86efd96Sagiri 		}
541b86efd96Sagiri 		bp[nbuf - 1].buf_nextp = NULL;
542b86efd96Sagiri 		bp[nbuf - 1].buf_ep = ep;
543b86efd96Sagiri 		bp[nbuf - 1].buf_ds.ds_va = (ib_vaddr_t)(uintptr_t)mp;
544b86efd96Sagiri 		bp[nbuf - 1].buf_ds.ds_key = ep->ep_snd_lkey;
545b86efd96Sagiri 		bp[nbuf - 1].buf_state = RDS_SNDBUF_FREE;
546b86efd96Sagiri 		spool->pool_headp = &bp[0];
547b86efd96Sagiri 		spool->pool_tailp = &bp[nbuf - 1];
548b86efd96Sagiri 	}
549b86efd96Sagiri 
550b86efd96Sagiri 	RDS_DPRINTF3(LABEL, "rdsmemp start: %p end: %p", memp, mp);
551b86efd96Sagiri 	RDS_DPRINTF2("rds_init_send_pool", "Return");
552b86efd96Sagiri 
553b86efd96Sagiri 	return (0);
554b86efd96Sagiri }
555b86efd96Sagiri 
556c1f8b08eSagiri int
rds_reinit_send_pool(rds_ep_t * ep,ib_guid_t hca_guid)557c1f8b08eSagiri rds_reinit_send_pool(rds_ep_t *ep, ib_guid_t hca_guid)
558c1f8b08eSagiri {
559c1f8b08eSagiri 	rds_buf_t	*bp;
560c1f8b08eSagiri 	rds_hca_t	*hcap;
561c1f8b08eSagiri 	ibt_mr_attr_t   mem_attr;
562c1f8b08eSagiri 	ibt_mr_desc_t   mem_desc;
563c1f8b08eSagiri 	rds_bufpool_t   *spool;
564c1f8b08eSagiri 	int		ret;
565c1f8b08eSagiri 
566c1f8b08eSagiri 	RDS_DPRINTF2("rds_reinit_send_pool", "Enter: EP(%p)", ep);
567c1f8b08eSagiri 
568c1f8b08eSagiri 	spool = &ep->ep_sndpool;
569c1f8b08eSagiri 	ASSERT(spool->pool_memp != NULL);
570c1f8b08eSagiri 
571c1f8b08eSagiri 	/* deregister the send pool memory from the previous HCA */
572c1f8b08eSagiri 	hcap = rds_get_hcap(rdsib_statep, ep->ep_hca_guid);
573c1f8b08eSagiri 	if (hcap == NULL) {
574c1f8b08eSagiri 		RDS_DPRINTF2("rds_reinit_send_pool", "HCA (0x%llx) not found",
575c1f8b08eSagiri 		    ep->ep_hca_guid);
576c1f8b08eSagiri 	} else {
577c1f8b08eSagiri 		if (ep->ep_snd_mrhdl != NULL) {
578c1f8b08eSagiri 			(void) ibt_deregister_mr(hcap->hca_hdl,
579c1f8b08eSagiri 			    ep->ep_snd_mrhdl);
580c1f8b08eSagiri 			ep->ep_snd_mrhdl = NULL;
581c1f8b08eSagiri 			ep->ep_snd_lkey = 0;
582c1f8b08eSagiri 		}
583c1f8b08eSagiri 
584c1f8b08eSagiri 		if ((ep->ep_type == RDS_EP_TYPE_DATA) &&
585c1f8b08eSagiri 		    (ep->ep_ackhdl != NULL)) {
586c1f8b08eSagiri 			(void) ibt_deregister_mr(hcap->hca_hdl, ep->ep_ackhdl);
587c1f8b08eSagiri 			ep->ep_ackhdl = NULL;
588c1f8b08eSagiri 			ep->ep_ack_rkey = 0;
589c1f8b08eSagiri 		}
590c1f8b08eSagiri 
591*accc2981SToomas Soome 		ep->ep_hca_guid = 0;
592c1f8b08eSagiri 	}
593c1f8b08eSagiri 
594c1f8b08eSagiri 	/* get the hcap for the new HCA */
595c1f8b08eSagiri 	hcap = rds_get_hcap(rdsib_statep, hca_guid);
596c1f8b08eSagiri 	if (hcap == NULL) {
597c1f8b08eSagiri 		RDS_DPRINTF2("rds_reinit_send_pool", "HCA (0x%llx) not found",
598c1f8b08eSagiri 		    hca_guid);
599c1f8b08eSagiri 		return (-1);
600c1f8b08eSagiri 	}
601c1f8b08eSagiri 
602c1f8b08eSagiri 	/* register the send memory */
603c1f8b08eSagiri 	mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)spool->pool_memp;
604c1f8b08eSagiri 	mem_attr.mr_len = spool->pool_memsize;
605c1f8b08eSagiri 	mem_attr.mr_as = NULL;
606c1f8b08eSagiri 	mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
607c1f8b08eSagiri 
608c1f8b08eSagiri 	ret = ibt_register_mr(hcap->hca_hdl, hcap->hca_pdhdl,
609c1f8b08eSagiri 	    &mem_attr, &ep->ep_snd_mrhdl, &mem_desc);
610c1f8b08eSagiri 	if (ret != IBT_SUCCESS) {
611c1f8b08eSagiri 		RDS_DPRINTF2("rds_reinit_send_pool",
612c1f8b08eSagiri 		    "EP(%p): ibt_register_mr failed: %d", ep, ret);
613c1f8b08eSagiri 		return (-1);
614c1f8b08eSagiri 	}
615c1f8b08eSagiri 	ep->ep_snd_lkey = mem_desc.md_lkey;
616c1f8b08eSagiri 
617c1f8b08eSagiri 	/* register the acknowledgement space */
618c1f8b08eSagiri 	if (ep->ep_type == RDS_EP_TYPE_DATA) {
619c1f8b08eSagiri 		mem_attr.mr_vaddr = (ib_vaddr_t)ep->ep_ack_addr;
620c1f8b08eSagiri 		mem_attr.mr_len = sizeof (uintptr_t);
621c1f8b08eSagiri 		mem_attr.mr_as = NULL;
622c1f8b08eSagiri 		mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE |
623c1f8b08eSagiri 		    IBT_MR_ENABLE_REMOTE_WRITE;
624c1f8b08eSagiri 
625c1f8b08eSagiri 		ret = ibt_register_mr(hcap->hca_hdl, hcap->hca_pdhdl,
626c1f8b08eSagiri 		    &mem_attr, &ep->ep_ackhdl, &mem_desc);
627c1f8b08eSagiri 		if (ret != IBT_SUCCESS) {
628c1f8b08eSagiri 			RDS_DPRINTF2("rds_reinit_send_pool",
629c1f8b08eSagiri 			    "EP(%p): ibt_register_mr for ack failed: %d",
630c1f8b08eSagiri 			    ep, ret);
631c1f8b08eSagiri 			(void) ibt_deregister_mr(hcap->hca_hdl,
632c1f8b08eSagiri 			    ep->ep_snd_mrhdl);
633c1f8b08eSagiri 			ep->ep_snd_mrhdl = NULL;
634c1f8b08eSagiri 			ep->ep_snd_lkey = 0;
635c1f8b08eSagiri 			return (-1);
636c1f8b08eSagiri 		}
637c1f8b08eSagiri 		ep->ep_ack_rkey = mem_desc.md_rkey;
638c1f8b08eSagiri 
639c1f8b08eSagiri 		/* update the LKEY in the acknowledgement WR */
640c1f8b08eSagiri 		ep->ep_ackds.ds_key = ep->ep_snd_lkey;
641c1f8b08eSagiri 	}
642c1f8b08eSagiri 
643c1f8b08eSagiri 	/* update the LKEY in each buffer */
644c1f8b08eSagiri 	bp = spool->pool_headp;
645c1f8b08eSagiri 	while (bp) {
646c1f8b08eSagiri 		bp->buf_ds.ds_key = ep->ep_snd_lkey;
647c1f8b08eSagiri 		bp = bp->buf_nextp;
648c1f8b08eSagiri 	}
649c1f8b08eSagiri 
650c1f8b08eSagiri 	ep->ep_hca_guid = hca_guid;
651c1f8b08eSagiri 
652c1f8b08eSagiri 	RDS_DPRINTF2("rds_reinit_send_pool", "Return: EP(%p)", ep);
653c1f8b08eSagiri 
654c1f8b08eSagiri 	return (0);
655c1f8b08eSagiri }
656c1f8b08eSagiri 
657b86efd96Sagiri void
rds_free_recv_pool(rds_ep_t * ep)658b86efd96Sagiri rds_free_recv_pool(rds_ep_t *ep)
659b86efd96Sagiri {
660b86efd96Sagiri 	rds_bufpool_t *pool;
661b86efd96Sagiri 
662b86efd96Sagiri 	if (ep->ep_type == RDS_EP_TYPE_DATA) {
663b86efd96Sagiri 		pool = &rds_dpool;
664b86efd96Sagiri 	} else {
665b86efd96Sagiri 		pool = &rds_cpool;
666b86efd96Sagiri 	}
667b86efd96Sagiri 
668b86efd96Sagiri 	mutex_enter(&ep->ep_rcvpool.pool_lock);
669b86efd96Sagiri 	if (ep->ep_rcvpool.pool_nfree != 0) {
670b86efd96Sagiri 		rds_free_buf(pool, ep->ep_rcvpool.pool_headp,
671b86efd96Sagiri 		    ep->ep_rcvpool.pool_nfree);
672b86efd96Sagiri 		ep->ep_rcvpool.pool_nfree = 0;
673b86efd96Sagiri 		ep->ep_rcvpool.pool_headp = NULL;
674b86efd96Sagiri 		ep->ep_rcvpool.pool_tailp = NULL;
675b86efd96Sagiri 	}
676b86efd96Sagiri 	mutex_exit(&ep->ep_rcvpool.pool_lock);
677b86efd96Sagiri }
678b86efd96Sagiri 
679b86efd96Sagiri int
rds_init_recv_pool(rds_ep_t * ep)680b86efd96Sagiri rds_init_recv_pool(rds_ep_t *ep)
681b86efd96Sagiri {
682b86efd96Sagiri 	rds_bufpool_t	*rpool;
683b86efd96Sagiri 	rds_qp_t	*recvqp;
684b86efd96Sagiri 
685b86efd96Sagiri 	recvqp = &ep->ep_recvqp;
686b86efd96Sagiri 	rpool = &ep->ep_rcvpool;
687b86efd96Sagiri 	if (ep->ep_type == RDS_EP_TYPE_DATA) {
688b86efd96Sagiri 		recvqp->qp_depth = MaxDataRecvBuffers;
689b86efd96Sagiri 		recvqp->qp_level = 0;
690b86efd96Sagiri 		recvqp->qp_lwm = (DataRecvBufferLWM * MaxDataRecvBuffers)/100;
691b86efd96Sagiri 		recvqp->qp_taskqpending = B_FALSE;
692b86efd96Sagiri 
693b86efd96Sagiri 		rpool->pool_nbuffers = MaxDataRecvBuffers;
694b86efd96Sagiri 		rpool->pool_nbusy = 0;
695b86efd96Sagiri 		rpool->pool_nfree = 0;
696b86efd96Sagiri 	} else {
697b86efd96Sagiri 		recvqp->qp_depth = MaxCtrlRecvBuffers;
698b86efd96Sagiri 		recvqp->qp_level = 0;
699b86efd96Sagiri 		recvqp->qp_lwm = (CtrlRecvBufferLWM * MaxCtrlRecvBuffers)/100;
700b86efd96Sagiri 		recvqp->qp_taskqpending = B_FALSE;
701b86efd96Sagiri 
702b86efd96Sagiri 		rpool->pool_nbuffers = MaxCtrlRecvBuffers;
703b86efd96Sagiri 		rpool->pool_nbusy = 0;
704b86efd96Sagiri 		rpool->pool_nfree = 0;
705b86efd96Sagiri 	}
706b86efd96Sagiri 
707b86efd96Sagiri 	return (0);
708b86efd96Sagiri }
709b86efd96Sagiri 
710b86efd96Sagiri /* Free buffers to the global pool, either cpool or dpool */
711b86efd96Sagiri void
rds_free_buf(rds_bufpool_t * pool,rds_buf_t * bp,uint_t nbuf)712b86efd96Sagiri rds_free_buf(rds_bufpool_t *pool, rds_buf_t *bp, uint_t nbuf)
713b86efd96Sagiri {
714b86efd96Sagiri 	uint_t		ix;
715b86efd96Sagiri 
716b86efd96Sagiri 	RDS_DPRINTF4("rds_free_buf", "Enter");
717b86efd96Sagiri 
718b86efd96Sagiri 	ASSERT(nbuf != 0);
719b86efd96Sagiri 
720b86efd96Sagiri 	mutex_enter(&pool->pool_lock);
721b86efd96Sagiri 
722b86efd96Sagiri 	if (pool->pool_nfree != 0) {
723b86efd96Sagiri 		pool->pool_tailp->buf_nextp = bp;
724b86efd96Sagiri 	} else {
725b86efd96Sagiri 		pool->pool_headp = bp;
726b86efd96Sagiri 	}
727b86efd96Sagiri 
728b86efd96Sagiri 	if (nbuf == 1) {
729b86efd96Sagiri 		ASSERT(bp->buf_state == RDS_RCVBUF_FREE);
730b86efd96Sagiri 		bp->buf_ep = NULL;
731b86efd96Sagiri 		bp->buf_nextp = NULL;
732b86efd96Sagiri 		pool->pool_tailp = bp;
733b86efd96Sagiri 	} else {
734b86efd96Sagiri 		for (ix = 1; ix < nbuf; ix++) {
735b86efd96Sagiri 			ASSERT(bp->buf_state == RDS_RCVBUF_FREE);
736b86efd96Sagiri 			bp->buf_ep = NULL;
737b86efd96Sagiri 			bp = bp->buf_nextp;
738b86efd96Sagiri 		}
739b86efd96Sagiri 		ASSERT(bp->buf_state == RDS_RCVBUF_FREE);
740b86efd96Sagiri 		bp->buf_ep = NULL;
741b86efd96Sagiri 		bp->buf_nextp = NULL;
742b86efd96Sagiri 		pool->pool_tailp = bp;
743b86efd96Sagiri 	}
744b86efd96Sagiri 	/* tail is always the last buffer */
745b86efd96Sagiri 	pool->pool_tailp->buf_nextp = NULL;
746b86efd96Sagiri 
747b86efd96Sagiri 	pool->pool_nfree += nbuf;
748b86efd96Sagiri 	pool->pool_nbusy -= nbuf;
749b86efd96Sagiri 
750b86efd96Sagiri 	mutex_exit(&pool->pool_lock);
751b86efd96Sagiri 
752b86efd96Sagiri 	RDS_DPRINTF4("rds_free_buf", "Return");
753b86efd96Sagiri }
754b86efd96Sagiri 
755b86efd96Sagiri /* Get buffers from the global pools, either cpool or dpool */
756b86efd96Sagiri rds_buf_t *
rds_get_buf(rds_bufpool_t * pool,uint_t nbuf,uint_t * nret)757b86efd96Sagiri rds_get_buf(rds_bufpool_t *pool, uint_t nbuf, uint_t *nret)
758b86efd96Sagiri {
759b86efd96Sagiri 	rds_buf_t	*bp = NULL, *bp1;
760b86efd96Sagiri 	uint_t		ix;
761b86efd96Sagiri 
762b86efd96Sagiri 	RDS_DPRINTF4("rds_get_buf", "Enter");
763b86efd96Sagiri 
764b86efd96Sagiri 	mutex_enter(&pool->pool_lock);
765b86efd96Sagiri 
766b86efd96Sagiri 	RDS_DPRINTF3("rds_get_buf", "Available: %d Needed: %d",
767b86efd96Sagiri 	    pool->pool_nfree, nbuf);
768b86efd96Sagiri 
769b86efd96Sagiri 	if (nbuf < pool->pool_nfree) {
770b86efd96Sagiri 		*nret = nbuf;
771b86efd96Sagiri 
772b86efd96Sagiri 		bp1 = pool->pool_headp;
773b86efd96Sagiri 		for (ix = 1; ix < nbuf; ix++) {
774b86efd96Sagiri 			bp1 = bp1->buf_nextp;
775b86efd96Sagiri 		}
776b86efd96Sagiri 
777b86efd96Sagiri 		bp = pool->pool_headp;
778b86efd96Sagiri 		pool->pool_headp = bp1->buf_nextp;
779b86efd96Sagiri 		bp1->buf_nextp = NULL;
780b86efd96Sagiri 
781b86efd96Sagiri 		pool->pool_nfree -= nbuf;
782b86efd96Sagiri 		pool->pool_nbusy += nbuf;
783b86efd96Sagiri 	} else if (nbuf >= pool->pool_nfree) {
784b86efd96Sagiri 		*nret = pool->pool_nfree;
785b86efd96Sagiri 
786b86efd96Sagiri 		bp = pool->pool_headp;
787b86efd96Sagiri 
788b86efd96Sagiri 		pool->pool_headp = NULL;
789b86efd96Sagiri 		pool->pool_tailp = NULL;
790b86efd96Sagiri 
791b86efd96Sagiri 		pool->pool_nbusy += pool->pool_nfree;
792b86efd96Sagiri 		pool->pool_nfree = 0;
793b86efd96Sagiri 	}
794b86efd96Sagiri 
795b86efd96Sagiri 	mutex_exit(&pool->pool_lock);
796b86efd96Sagiri 
797b86efd96Sagiri 	RDS_DPRINTF4("rds_get_buf", "Return");
798b86efd96Sagiri 
799b86efd96Sagiri 	return (bp);
800b86efd96Sagiri }
801b86efd96Sagiri 
802b86efd96Sagiri boolean_t
rds_is_recvq_empty(rds_ep_t * ep,boolean_t wait)803b86efd96Sagiri rds_is_recvq_empty(rds_ep_t *ep, boolean_t wait)
804b86efd96Sagiri {
805b86efd96Sagiri 	rds_qp_t	*recvqp;
806b86efd96Sagiri 	rds_bufpool_t	*rpool;
807b86efd96Sagiri 	boolean_t ret = B_TRUE;
808b86efd96Sagiri 
809b86efd96Sagiri 	recvqp = &ep->ep_recvqp;
810b86efd96Sagiri 	mutex_enter(&recvqp->qp_lock);
811b86efd96Sagiri 	RDS_DPRINTF2("rds_is_recvq_empty", "EP(%p): QP has %d WRs",
812b86efd96Sagiri 	    ep, recvqp->qp_level);
813b86efd96Sagiri 	if (wait) {
814b86efd96Sagiri 		/* wait until the RQ is empty */
815b86efd96Sagiri 		while (recvqp->qp_level != 0) {
816b86efd96Sagiri 			/* wait one second and try again */
817b86efd96Sagiri 			mutex_exit(&recvqp->qp_lock);
818b86efd96Sagiri 			delay(drv_usectohz(1000000));
819b86efd96Sagiri 			mutex_enter(&recvqp->qp_lock);
820b86efd96Sagiri 		}
821b86efd96Sagiri 	} else if (recvqp->qp_level != 0) {
822b86efd96Sagiri 			ret = B_FALSE;
823b86efd96Sagiri 	}
824b86efd96Sagiri 	mutex_exit(&recvqp->qp_lock);
825b86efd96Sagiri 
826b86efd96Sagiri 	rpool = &ep->ep_rcvpool;
827b86efd96Sagiri 	mutex_enter(&rpool->pool_lock);
8280c19630bSagiri 
8290c19630bSagiri 	/*
8300c19630bSagiri 	 * During failovers/reconnects, the app may still have some buffers
8310c19630bSagiri 	 * on thier socket queues. Waiting here for those buffers may
8320c19630bSagiri 	 * cause a hang. It seems ok for those buffers to get freed later.
8330c19630bSagiri 	 */
8340c19630bSagiri 	if (rpool->pool_nbusy != 0) {
835b86efd96Sagiri 		RDS_DPRINTF2("rds_is_recvq_empty", "EP(%p): "
8360c19630bSagiri 		    "There are %d pending buffers on sockqs", ep,
8370c19630bSagiri 		    rpool->pool_nbusy);
838b86efd96Sagiri 		ret = B_FALSE;
839b86efd96Sagiri 	}
840b86efd96Sagiri 	mutex_exit(&rpool->pool_lock);
841b86efd96Sagiri 
842b86efd96Sagiri 	return (ret);
843b86efd96Sagiri }
844b86efd96Sagiri 
845b86efd96Sagiri boolean_t
rds_is_sendq_empty(rds_ep_t * ep,uint_t wait)846b86efd96Sagiri rds_is_sendq_empty(rds_ep_t *ep, uint_t wait)
847b86efd96Sagiri {
848b86efd96Sagiri 	rds_bufpool_t	*spool;
849b86efd96Sagiri 	rds_buf_t	*bp;
850b86efd96Sagiri 	boolean_t	ret1 = B_TRUE;
851b86efd96Sagiri 
852b86efd96Sagiri 	/* check if all the sends completed */
853b86efd96Sagiri 	spool = &ep->ep_sndpool;
854b86efd96Sagiri 	mutex_enter(&spool->pool_lock);
855b86efd96Sagiri 	RDS_DPRINTF2("rds_is_sendq_empty", "EP(%p): "
856b86efd96Sagiri 	    "Send Pool contains: %d", ep, spool->pool_nbusy);
857b86efd96Sagiri 	if (wait) {
858b86efd96Sagiri 		while (spool->pool_nbusy != 0) {
859b86efd96Sagiri 			if (rds_no_interrupts) {
860b86efd96Sagiri 				/* wait one second and try again */
861b86efd96Sagiri 				delay(drv_usectohz(1000000));
862b86efd96Sagiri 				rds_poll_send_completions(ep->ep_sendcq, ep,
863b86efd96Sagiri 				    B_TRUE);
864b86efd96Sagiri 			} else {
865b86efd96Sagiri 				/* wait one second and try again */
866b86efd96Sagiri 				mutex_exit(&spool->pool_lock);
867b86efd96Sagiri 				delay(drv_usectohz(1000000));
868b86efd96Sagiri 				mutex_enter(&spool->pool_lock);
869b86efd96Sagiri 			}
870b86efd96Sagiri 		}
871b86efd96Sagiri 
872b86efd96Sagiri 		if ((wait == 2) && (ep->ep_type == RDS_EP_TYPE_DATA)) {
873b86efd96Sagiri 			rds_buf_t	*ackbp;
87400a3eaf3SRamaswamy Tummala 			rds_buf_t	*prev_ackbp;
875b86efd96Sagiri 
876b86efd96Sagiri 			/*
877b86efd96Sagiri 			 * If the last one is acknowledged then everything
878b86efd96Sagiri 			 * is acknowledged
879b86efd96Sagiri 			 */
880b86efd96Sagiri 			bp = spool->pool_tailp;
881b86efd96Sagiri 			ackbp = *(rds_buf_t **)ep->ep_ack_addr;
88200a3eaf3SRamaswamy Tummala 			prev_ackbp = ackbp;
883b86efd96Sagiri 			RDS_DPRINTF2("rds_is_sendq_empty", "EP(%p): "
884b86efd96Sagiri 			    "Checking for acknowledgements", ep);
885b86efd96Sagiri 			while (bp != ackbp) {
886b86efd96Sagiri 				RDS_DPRINTF2("rds_is_sendq_empty",
887b86efd96Sagiri 				    "EP(%p) BP(0x%p/0x%p) last "
888b86efd96Sagiri 				    "sent/acknowledged", ep, bp, ackbp);
889b86efd96Sagiri 				mutex_exit(&spool->pool_lock);
890b86efd96Sagiri 				delay(drv_usectohz(1000000));
891b86efd96Sagiri 				mutex_enter(&spool->pool_lock);
892b86efd96Sagiri 
893b86efd96Sagiri 				bp = spool->pool_tailp;
894b86efd96Sagiri 				ackbp = *(rds_buf_t **)ep->ep_ack_addr;
89500a3eaf3SRamaswamy Tummala 				if (ackbp == prev_ackbp) {
89600a3eaf3SRamaswamy Tummala 					RDS_DPRINTF2("rds_is_sendq_empty",
89700a3eaf3SRamaswamy Tummala 					    "There has been no progress,"
89800a3eaf3SRamaswamy Tummala 					    "give up and proceed");
89900a3eaf3SRamaswamy Tummala 					break;
90000a3eaf3SRamaswamy Tummala 				}
90100a3eaf3SRamaswamy Tummala 				prev_ackbp = ackbp;
902b86efd96Sagiri 			}
903b86efd96Sagiri 		}
904b86efd96Sagiri 	} else if (spool->pool_nbusy != 0) {
905b86efd96Sagiri 			ret1 = B_FALSE;
906b86efd96Sagiri 	}
907b86efd96Sagiri 	mutex_exit(&spool->pool_lock);
908b86efd96Sagiri 
909b86efd96Sagiri 	/* check if all the rdma acks completed */
910b86efd96Sagiri 	mutex_enter(&ep->ep_lock);
911b86efd96Sagiri 	RDS_DPRINTF2("rds_is_sendq_empty", "EP(%p): "
912b86efd96Sagiri 	    "Outstanding RDMA Acks: %d", ep, ep->ep_rdmacnt);
913b86efd96Sagiri 	if (wait) {
914b86efd96Sagiri 		while (ep->ep_rdmacnt != 0) {
915b86efd96Sagiri 			if (rds_no_interrupts) {
916b86efd96Sagiri 				/* wait one second and try again */
917b86efd96Sagiri 				delay(drv_usectohz(1000000));
918b86efd96Sagiri 				rds_poll_send_completions(ep->ep_sendcq, ep,
919b86efd96Sagiri 				    B_FALSE);
920b86efd96Sagiri 			} else {
921b86efd96Sagiri 				/* wait one second and try again */
922b86efd96Sagiri 				mutex_exit(&ep->ep_lock);
923b86efd96Sagiri 				delay(drv_usectohz(1000000));
924b86efd96Sagiri 				mutex_enter(&ep->ep_lock);
925b86efd96Sagiri 			}
926b86efd96Sagiri 		}
927b86efd96Sagiri 	} else if (ep->ep_rdmacnt != 0) {
928b86efd96Sagiri 			ret1 = B_FALSE;
929b86efd96Sagiri 	}
930b86efd96Sagiri 	mutex_exit(&ep->ep_lock);
931b86efd96Sagiri 
932b86efd96Sagiri 	return (ret1);
933b86efd96Sagiri }
934b86efd96Sagiri 
935b86efd96Sagiri /* Get buffers from the send pool */
936b86efd96Sagiri rds_buf_t *
rds_get_send_buf(rds_ep_t * ep,uint_t nbuf)937b86efd96Sagiri rds_get_send_buf(rds_ep_t *ep, uint_t nbuf)
938b86efd96Sagiri {
939b86efd96Sagiri 	rds_buf_t	*bp = NULL, *bp1;
940b86efd96Sagiri 	rds_bufpool_t	*spool;
941b86efd96Sagiri 	uint_t		waittime = rds_waittime_ms * 1000;
942b86efd96Sagiri 	uint_t		ix;
943b86efd96Sagiri 	int		ret;
944b86efd96Sagiri 
945b86efd96Sagiri 	RDS_DPRINTF4("rds_get_send_buf", "Enter: EP(%p) Buffers requested: %d",
946b86efd96Sagiri 	    ep, nbuf);
947b86efd96Sagiri 
948b86efd96Sagiri 	spool = &ep->ep_sndpool;
949b86efd96Sagiri 	mutex_enter(&spool->pool_lock);
950b86efd96Sagiri 
951b86efd96Sagiri 	if (rds_no_interrupts) {
952b86efd96Sagiri 		if ((spool->pool_sqpoll_pending == B_FALSE) &&
953b86efd96Sagiri 		    (spool->pool_nbusy >
954b86efd96Sagiri 		    (spool->pool_nbuffers * rds_poll_percent_full)/100)) {
955b86efd96Sagiri 			spool->pool_sqpoll_pending = B_TRUE;
956b86efd96Sagiri 			mutex_exit(&spool->pool_lock);
957b86efd96Sagiri 			rds_poll_send_completions(ep->ep_sendcq, ep, B_FALSE);
958b86efd96Sagiri 			mutex_enter(&spool->pool_lock);
959b86efd96Sagiri 			spool->pool_sqpoll_pending = B_FALSE;
960b86efd96Sagiri 		}
961b86efd96Sagiri 	}
962b86efd96Sagiri 
963b86efd96Sagiri 	if (spool->pool_nfree < nbuf) {
964b86efd96Sagiri 		/* wait for buffers to become available */
965b86efd96Sagiri 		spool->pool_cv_count += nbuf;
966d3d50737SRafael Vanoni 		ret = cv_reltimedwait_sig(&spool->pool_cv, &spool->pool_lock,
967d3d50737SRafael Vanoni 		    drv_usectohz(waittime), TR_CLOCK_TICK);
968b86efd96Sagiri 		/* ret = cv_wait_sig(&spool->pool_cv, &spool->pool_lock); */
969b86efd96Sagiri 		if (ret == 0) {
970b86efd96Sagiri 			/* signal pending */
971b86efd96Sagiri 			spool->pool_cv_count -= nbuf;
972b86efd96Sagiri 			mutex_exit(&spool->pool_lock);
973b86efd96Sagiri 			return (NULL);
974b86efd96Sagiri 		}
975b86efd96Sagiri 
976b86efd96Sagiri 		spool->pool_cv_count -= nbuf;
977b86efd96Sagiri 	}
978b86efd96Sagiri 
979b86efd96Sagiri 	/* Have the number of buffers needed */
980b86efd96Sagiri 	if (spool->pool_nfree > nbuf) {
981b86efd96Sagiri 		bp = spool->pool_headp;
982b86efd96Sagiri 
983b86efd96Sagiri 		if (ep->ep_type == RDS_EP_TYPE_DATA) {
984b86efd96Sagiri 			rds_buf_t *ackbp;
985b86efd96Sagiri 			ackbp = *(rds_buf_t **)ep->ep_ack_addr;
986b86efd96Sagiri 
987b86efd96Sagiri 			/* check if all the needed buffers are acknowledged */
988b86efd96Sagiri 			bp1 = bp;
989b86efd96Sagiri 			for (ix = 0; ix < nbuf; ix++) {
990b86efd96Sagiri 				if ((bp1 == ackbp) ||
991b86efd96Sagiri 				    (bp1->buf_state != RDS_SNDBUF_FREE)) {
992b86efd96Sagiri 					/*
993b86efd96Sagiri 					 * The buffer is not yet signalled or
994b86efd96Sagiri 					 * is not yet acknowledged
995b86efd96Sagiri 					 */
996b86efd96Sagiri 					RDS_DPRINTF5("rds_get_send_buf",
997b86efd96Sagiri 					    "EP(%p) Buffer (%p) not yet "
998b86efd96Sagiri 					    "acked/completed", ep, bp1);
999b86efd96Sagiri 					mutex_exit(&spool->pool_lock);
1000b86efd96Sagiri 					return (NULL);
1001b86efd96Sagiri 				}
1002b86efd96Sagiri 
1003b86efd96Sagiri 				bp1 = bp1->buf_nextp;
1004b86efd96Sagiri 			}
1005b86efd96Sagiri 		}
1006b86efd96Sagiri 
1007b86efd96Sagiri 		/* mark the buffers as pending */
1008b86efd96Sagiri 		bp1 = bp;
1009b86efd96Sagiri 		for (ix = 1; ix < nbuf; ix++) {
1010b86efd96Sagiri 			ASSERT(bp1->buf_state == RDS_SNDBUF_FREE);
1011b86efd96Sagiri 			bp1->buf_state = RDS_SNDBUF_PENDING;
1012b86efd96Sagiri 			bp1 = bp1->buf_nextp;
1013b86efd96Sagiri 		}
1014b86efd96Sagiri 		ASSERT(bp1->buf_state == RDS_SNDBUF_FREE);
1015b86efd96Sagiri 		bp1->buf_state = RDS_SNDBUF_PENDING;
1016b86efd96Sagiri 
1017b86efd96Sagiri 		spool->pool_headp = bp1->buf_nextp;
1018b86efd96Sagiri 		bp1->buf_nextp = NULL;
1019b86efd96Sagiri 		if (spool->pool_headp == NULL)
1020b86efd96Sagiri 			spool->pool_tailp = NULL;
1021b86efd96Sagiri 		spool->pool_nfree -= nbuf;
1022b86efd96Sagiri 		spool->pool_nbusy += nbuf;
1023b86efd96Sagiri 	}
1024b86efd96Sagiri 	mutex_exit(&spool->pool_lock);
1025b86efd96Sagiri 
1026b86efd96Sagiri 	RDS_DPRINTF4("rds_get_send_buf", "Return: EP(%p) Buffers requested: %d",
1027b86efd96Sagiri 	    ep, nbuf);
1028b86efd96Sagiri 
1029b86efd96Sagiri 	return (bp);
1030b86efd96Sagiri }
1031b86efd96Sagiri 
1032b86efd96Sagiri #define	RDS_MIN_BUF_TO_WAKE_THREADS	10
1033b86efd96Sagiri 
1034b86efd96Sagiri void
rds_free_send_buf(rds_ep_t * ep,rds_buf_t * headp,rds_buf_t * tailp,uint_t nbuf,boolean_t lock)1035b86efd96Sagiri rds_free_send_buf(rds_ep_t *ep, rds_buf_t *headp, rds_buf_t *tailp, uint_t nbuf,
1036b86efd96Sagiri     boolean_t lock)
1037b86efd96Sagiri {
1038b86efd96Sagiri 	rds_bufpool_t	*spool;
1039b86efd96Sagiri 	rds_buf_t	*tmp;
1040b86efd96Sagiri 
1041b86efd96Sagiri 	RDS_DPRINTF4("rds_free_send_buf", "Enter");
1042b86efd96Sagiri 
1043b86efd96Sagiri 	ASSERT(nbuf != 0);
1044b86efd96Sagiri 
1045b86efd96Sagiri 	if (tailp == NULL) {
1046b86efd96Sagiri 		if (nbuf > 1) {
1047b86efd96Sagiri 			tmp = headp;
1048b86efd96Sagiri 			while (tmp->buf_nextp) {
1049b86efd96Sagiri 				tmp = tmp->buf_nextp;
1050b86efd96Sagiri 			}
1051b86efd96Sagiri 			tailp = tmp;
1052b86efd96Sagiri 		} else {
1053b86efd96Sagiri 			tailp = headp;
1054b86efd96Sagiri 		}
1055b86efd96Sagiri 	}
1056b86efd96Sagiri 
1057b86efd96Sagiri 	spool = &ep->ep_sndpool;
1058b86efd96Sagiri 
1059b86efd96Sagiri 	if (lock == B_FALSE) {
1060b86efd96Sagiri 		/* lock is not held outside */
1061b86efd96Sagiri 		mutex_enter(&spool->pool_lock);
1062b86efd96Sagiri 	}
1063b86efd96Sagiri 
1064b86efd96Sagiri 	if (spool->pool_nfree) {
1065b86efd96Sagiri 		spool->pool_tailp->buf_nextp = headp;
1066b86efd96Sagiri 	} else {
1067b86efd96Sagiri 		spool->pool_headp = headp;
1068b86efd96Sagiri 	}
1069b86efd96Sagiri 	spool->pool_tailp = tailp;
1070b86efd96Sagiri 
1071b86efd96Sagiri 	spool->pool_nfree += nbuf;
1072b86efd96Sagiri 	spool->pool_nbusy -= nbuf;
1073b86efd96Sagiri 
1074b86efd96Sagiri 	if ((spool->pool_cv_count > 0) &&
1075b86efd96Sagiri 	    (spool->pool_nfree > RDS_MIN_BUF_TO_WAKE_THREADS)) {
1076b86efd96Sagiri 		if (spool->pool_nfree >= spool->pool_cv_count)
1077b86efd96Sagiri 			cv_broadcast(&spool->pool_cv);
1078b86efd96Sagiri 		else
1079b86efd96Sagiri 			cv_signal(&spool->pool_cv);
1080b86efd96Sagiri 	}
1081b86efd96Sagiri 
1082b86efd96Sagiri 	if (lock == B_FALSE) {
1083b86efd96Sagiri 		mutex_exit(&spool->pool_lock);
1084b86efd96Sagiri 	}
1085b86efd96Sagiri 
1086b86efd96Sagiri 	RDS_DPRINTF4("rds_free_send_buf", "Return");
1087b86efd96Sagiri }
1088b86efd96Sagiri 
1089b86efd96Sagiri void
rds_free_recv_buf(rds_buf_t * bp,uint_t nbuf)1090b86efd96Sagiri rds_free_recv_buf(rds_buf_t *bp, uint_t nbuf)
1091b86efd96Sagiri {
1092b86efd96Sagiri 	rds_ep_t	*ep;
1093b86efd96Sagiri 	rds_bufpool_t	*rpool;
1094b86efd96Sagiri 	rds_buf_t	*bp1;
1095b86efd96Sagiri 	uint_t		ix;
1096b86efd96Sagiri 
1097b86efd96Sagiri 	RDS_DPRINTF4("rds_free_recv_buf", "Enter");
1098b86efd96Sagiri 
1099b86efd96Sagiri 	ASSERT(nbuf != 0);
1100b86efd96Sagiri 
1101b86efd96Sagiri 	ep = bp->buf_ep;
1102b86efd96Sagiri 	rpool = &ep->ep_rcvpool;
1103b86efd96Sagiri 
1104b86efd96Sagiri 	mutex_enter(&rpool->pool_lock);
1105b86efd96Sagiri 
1106b86efd96Sagiri 	/* Add the buffers to the local pool */
1107b86efd96Sagiri 	if (rpool->pool_tailp == NULL) {
1108b86efd96Sagiri 		ASSERT(rpool->pool_headp == NULL);
1109b86efd96Sagiri 		ASSERT(rpool->pool_nfree == 0);
1110b86efd96Sagiri 		rpool->pool_headp = bp;
1111b86efd96Sagiri 		bp1 = bp;
1112b86efd96Sagiri 		for (ix = 1; ix < nbuf; ix++) {
1113b86efd96Sagiri 			if (bp1->buf_state == RDS_RCVBUF_ONSOCKQ) {
1114b86efd96Sagiri 				rpool->pool_nbusy--;
1115b86efd96Sagiri 			}
1116b86efd96Sagiri 			bp1->buf_state = RDS_RCVBUF_FREE;
1117b86efd96Sagiri 			bp1 = bp1->buf_nextp;
1118b86efd96Sagiri 		}
1119b86efd96Sagiri 		bp1->buf_nextp = NULL;
1120b86efd96Sagiri 		if (bp->buf_state == RDS_RCVBUF_ONSOCKQ) {
1121b86efd96Sagiri 			rpool->pool_nbusy--;
1122b86efd96Sagiri 		}
1123b86efd96Sagiri 		bp->buf_state = RDS_RCVBUF_FREE;
1124b86efd96Sagiri 		rpool->pool_tailp = bp1;
1125b86efd96Sagiri 		rpool->pool_nfree += nbuf;
1126b86efd96Sagiri 	} else {
1127b86efd96Sagiri 		bp1 = bp;
1128b86efd96Sagiri 		for (ix = 1; ix < nbuf; ix++) {
1129b86efd96Sagiri 			if (bp1->buf_state == RDS_RCVBUF_ONSOCKQ) {
1130b86efd96Sagiri 				rpool->pool_nbusy--;
1131b86efd96Sagiri 			}
1132b86efd96Sagiri 			bp1->buf_state = RDS_RCVBUF_FREE;
1133b86efd96Sagiri 			bp1 = bp1->buf_nextp;
1134b86efd96Sagiri 		}
1135b86efd96Sagiri 		bp1->buf_nextp = NULL;
1136b86efd96Sagiri 		if (bp->buf_state == RDS_RCVBUF_ONSOCKQ) {
1137b86efd96Sagiri 			rpool->pool_nbusy--;
1138b86efd96Sagiri 		}
1139b86efd96Sagiri 		bp->buf_state = RDS_RCVBUF_FREE;
1140b86efd96Sagiri 		rpool->pool_tailp->buf_nextp = bp;
1141b86efd96Sagiri 		rpool->pool_tailp = bp1;
1142b86efd96Sagiri 		rpool->pool_nfree += nbuf;
1143b86efd96Sagiri 	}
1144b86efd96Sagiri 
11450c19630bSagiri 	if (rpool->pool_nfree >= rds_nbuffers_to_putback) {
1146b86efd96Sagiri 		bp = rpool->pool_headp;
1147b86efd96Sagiri 		nbuf = rpool->pool_nfree;
1148b86efd96Sagiri 		rpool->pool_headp = NULL;
1149b86efd96Sagiri 		rpool->pool_tailp = NULL;
1150b86efd96Sagiri 		rpool->pool_nfree = 0;
1151b86efd96Sagiri 		mutex_exit(&rpool->pool_lock);
1152b86efd96Sagiri 
1153b86efd96Sagiri 		/* Free the buffers to the global pool */
1154b86efd96Sagiri 		if (ep->ep_type == RDS_EP_TYPE_DATA) {
1155b86efd96Sagiri 			rds_free_buf(&rds_dpool, bp, nbuf);
1156b86efd96Sagiri 		} else {
1157b86efd96Sagiri 			rds_free_buf(&rds_cpool, bp, nbuf);
1158b86efd96Sagiri 		}
1159b86efd96Sagiri 
1160b86efd96Sagiri 		return;
1161b86efd96Sagiri 	}
1162b86efd96Sagiri 	mutex_exit(&rpool->pool_lock);
1163b86efd96Sagiri 
1164b86efd96Sagiri 	RDS_DPRINTF4("rds_free_recv_buf", "Return");
1165b86efd96Sagiri }
1166