xref: /illumos-gate/usr/src/uts/sun4v/io/vio_util.c (revision 3ab636de)
1d10e4ef2Snarayan /*
2d10e4ef2Snarayan  * CDDL HEADER START
3d10e4ef2Snarayan  *
4d10e4ef2Snarayan  * The contents of this file are subject to the terms of the
5d10e4ef2Snarayan  * Common Development and Distribution License (the "License").
6d10e4ef2Snarayan  * You may not use this file except in compliance with the License.
7d10e4ef2Snarayan  *
8d10e4ef2Snarayan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d10e4ef2Snarayan  * or http://www.opensolaris.org/os/licensing.
10d10e4ef2Snarayan  * See the License for the specific language governing permissions
11d10e4ef2Snarayan  * and limitations under the License.
12d10e4ef2Snarayan  *
13d10e4ef2Snarayan  * When distributing Covered Code, include this CDDL HEADER in each
14d10e4ef2Snarayan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d10e4ef2Snarayan  * If applicable, add the following below this CDDL HEADER, with the
16d10e4ef2Snarayan  * fields enclosed by brackets "[]" replaced with your own identifying
17d10e4ef2Snarayan  * information: Portions Copyright [yyyy] [name of copyright owner]
18d10e4ef2Snarayan  *
19d10e4ef2Snarayan  * CDDL HEADER END
20d10e4ef2Snarayan  */
21d10e4ef2Snarayan 
22d10e4ef2Snarayan /*
236f09f0feSWENTAO YANG  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24d10e4ef2Snarayan  * Use is subject to license terms.
25d10e4ef2Snarayan  */
26d10e4ef2Snarayan 
27d10e4ef2Snarayan #include <sys/types.h>
28d10e4ef2Snarayan #include <sys/sysmacros.h>
29d10e4ef2Snarayan #include <sys/errno.h>
30d10e4ef2Snarayan #include <sys/kmem.h>
31d10e4ef2Snarayan #include <sys/ksynch.h>
32d10e4ef2Snarayan #include <sys/stream.h>
33d10e4ef2Snarayan #include <sys/ddi.h>
34d10e4ef2Snarayan #include <sys/sunddi.h>
35d10e4ef2Snarayan #include <sys/vio_util.h>
36d10e4ef2Snarayan 
376f09f0feSWENTAO YANG static int vio_pool_cleanup_retries = 10;	/* Max retries to free pool */
386f09f0feSWENTAO YANG static int vio_pool_cleanup_delay = 10000;	/* 10ms */
396f09f0feSWENTAO YANG 
40d10e4ef2Snarayan /*
41d10e4ef2Snarayan  * Create a pool of mblks from which future vio_allocb() requests
42d10e4ef2Snarayan  * will be serviced.
43d10e4ef2Snarayan  *
44d10e4ef2Snarayan  * NOTE: num_mblks has to non-zero and a power-of-2
45d10e4ef2Snarayan  *
466f09f0feSWENTAO YANG  * Returns
476f09f0feSWENTAO YANG  *	0 on success
486f09f0feSWENTAO YANG  *	EINVAL if num_mblks is zero or not a power of 2.
496f09f0feSWENTAO YANG  *	ENOSPC if the pool could not be created due to alloc failures.
50d10e4ef2Snarayan  */
51d10e4ef2Snarayan int
52d10e4ef2Snarayan vio_create_mblks(uint64_t num_mblks, size_t mblk_size, vio_mblk_pool_t **poolp)
53d10e4ef2Snarayan {
54d10e4ef2Snarayan 	vio_mblk_pool_t		*vmplp;
55d10e4ef2Snarayan 	vio_mblk_t		*vmp;
56d10e4ef2Snarayan 	uint8_t			*datap;
57d10e4ef2Snarayan 	int			i;
58*3ab636deSWENTAO YANG 	int			rv;
59d10e4ef2Snarayan 
60d10e4ef2Snarayan 	if (!(num_mblks) || (!ISP2(num_mblks))) {
61d10e4ef2Snarayan 		*poolp = 0;
62d10e4ef2Snarayan 		return (EINVAL);
63d10e4ef2Snarayan 	}
64d10e4ef2Snarayan 
65d10e4ef2Snarayan 	vmplp = kmem_zalloc(sizeof (*vmplp), KM_SLEEP);
66d10e4ef2Snarayan 	vmplp->quelen = num_mblks;
67d10e4ef2Snarayan 	vmplp->quemask = num_mblks - 1; /* expects quelen is power-of-2 */
68d10e4ef2Snarayan 	vmplp->mblk_size = mblk_size;
69d10e4ef2Snarayan 
70d10e4ef2Snarayan 	mutex_init(&vmplp->hlock, NULL, MUTEX_DRIVER,
71d10e4ef2Snarayan 	    DDI_INTR_PRI(DDI_INTR_SOFTPRI_DEFAULT));
72d10e4ef2Snarayan 	mutex_init(&vmplp->tlock, NULL, MUTEX_DRIVER,
73d10e4ef2Snarayan 	    DDI_INTR_PRI(DDI_INTR_SOFTPRI_DEFAULT));
74d10e4ef2Snarayan 
75d10e4ef2Snarayan 	vmplp->basep = kmem_zalloc(num_mblks * sizeof (vio_mblk_t), KM_SLEEP);
76d10e4ef2Snarayan 	vmplp->datap = kmem_zalloc(num_mblks * mblk_size, KM_SLEEP);
77d10e4ef2Snarayan 	vmplp->nextp = NULL;
78d10e4ef2Snarayan 
79d10e4ef2Snarayan 	/* create a queue of pointers to free vio_mblk_t's */
80844e62a3Sraghuram 	vmplp->quep = kmem_zalloc(vmplp->quelen *
81844e62a3Sraghuram 	    sizeof (vio_mblk_t *), KM_SLEEP);
82d10e4ef2Snarayan 	vmplp->head = 0;
83d10e4ef2Snarayan 	vmplp->tail =  0;
84d10e4ef2Snarayan 
85d10e4ef2Snarayan 	for (i = 0, datap = vmplp->datap; i < num_mblks; i++) {
86d10e4ef2Snarayan 
87d10e4ef2Snarayan 		vmp = &(vmplp->basep[i]);
88d10e4ef2Snarayan 		vmp->vmplp = vmplp;
89d10e4ef2Snarayan 		vmp->datap = datap;
90d10e4ef2Snarayan 		vmp->reclaim.free_func = vio_freeb;
91d10e4ef2Snarayan 		vmp->reclaim.free_arg = (caddr_t)vmp;
92d10e4ef2Snarayan 		vmp->mp = desballoc(vmp->datap, mblk_size, BPRI_MED,
93d10e4ef2Snarayan 		    &vmp->reclaim);
94d10e4ef2Snarayan 
956f09f0feSWENTAO YANG 		if (vmp->mp == NULL) {
966f09f0feSWENTAO YANG 			/* reset tail */
976f09f0feSWENTAO YANG 			vmplp->tail = vmplp->head;
986f09f0feSWENTAO YANG 
996f09f0feSWENTAO YANG 			/*
1006f09f0feSWENTAO YANG 			 * vio_destroy_mblks() frees mblks that have been
1016f09f0feSWENTAO YANG 			 * allocated so far and then destroys the pool.
1026f09f0feSWENTAO YANG 			 */
103*3ab636deSWENTAO YANG 			rv = vio_destroy_mblks(vmplp);
104*3ab636deSWENTAO YANG 			ASSERT(rv == 0);
1056f09f0feSWENTAO YANG 
1066f09f0feSWENTAO YANG 			*poolp = NULL;
1076f09f0feSWENTAO YANG 			return (ENOSPC);
1086f09f0feSWENTAO YANG 		}
109d10e4ef2Snarayan 
110d10e4ef2Snarayan 		/* put this vmp on the free stack */
111d10e4ef2Snarayan 		vmplp->quep[vmplp->tail] = vmp;
112d10e4ef2Snarayan 		vmplp->tail = (vmplp->tail + 1) & vmplp->quemask;
113d10e4ef2Snarayan 
114d10e4ef2Snarayan 		datap += mblk_size;
115d10e4ef2Snarayan 	}
116d10e4ef2Snarayan 
117d10e4ef2Snarayan 	*poolp = vmplp;
118d10e4ef2Snarayan 	return (0);
119d10e4ef2Snarayan }
120d10e4ef2Snarayan 
121d10e4ef2Snarayan /*
122d10e4ef2Snarayan  * Destroy the pool of mblks. This can only succeed when
123d10e4ef2Snarayan  * all allocated mblks have been returned to the pool.
124d10e4ef2Snarayan  *
125d10e4ef2Snarayan  * It is up to the caller to ensure that no further mblks are
126d10e4ef2Snarayan  * requested from the pool after destroy has been invoked.
127d10e4ef2Snarayan  *
128d10e4ef2Snarayan  * Returns 0 on success, EINVAL if handle is invalid, or
129d10e4ef2Snarayan  * EBUSY if not all mblks reclaimed yet.
130d10e4ef2Snarayan  */
131d10e4ef2Snarayan int
132d10e4ef2Snarayan vio_destroy_mblks(vio_mblk_pool_t *vmplp)
133d10e4ef2Snarayan {
1343af08d82Slm66018 	uint64_t	i;
1353af08d82Slm66018 	uint64_t	num_mblks;
1363af08d82Slm66018 	vio_mblk_t	*vmp;
1376f09f0feSWENTAO YANG 	int		pool_cleanup_retries = 0;
1386f09f0feSWENTAO YANG 
1393af08d82Slm66018 
140d10e4ef2Snarayan 	if (vmplp == NULL)
141d10e4ef2Snarayan 		return (EINVAL);
142d10e4ef2Snarayan 
143d10e4ef2Snarayan 	/*
144d10e4ef2Snarayan 	 * We can only destroy the pool once all the mblks have
145d10e4ef2Snarayan 	 * been reclaimed.
146d10e4ef2Snarayan 	 */
1476f09f0feSWENTAO YANG 	do {
1486f09f0feSWENTAO YANG 		if (vmplp->head == vmplp->tail) {
1496f09f0feSWENTAO YANG 			break;
1506f09f0feSWENTAO YANG 		}
1516f09f0feSWENTAO YANG 
152d10e4ef2Snarayan 		/* some mblks still in use */
1536f09f0feSWENTAO YANG 		drv_usecwait(vio_pool_cleanup_delay);
1546f09f0feSWENTAO YANG 	} while (++pool_cleanup_retries < vio_pool_cleanup_retries);
1556f09f0feSWENTAO YANG 
1566f09f0feSWENTAO YANG 	if (vmplp->head != vmplp->tail) {
157d10e4ef2Snarayan 		return (EBUSY);
158d10e4ef2Snarayan 	}
159d10e4ef2Snarayan 
1603af08d82Slm66018 	num_mblks = vmplp->quelen;
1613af08d82Slm66018 
1623af08d82Slm66018 	/*
1633af08d82Slm66018 	 * Set pool flag to tell vio_freeb() which is invoked from freeb(),
1643af08d82Slm66018 	 * that it is being called in the context of vio_destroy_mblks().
1653af08d82Slm66018 	 * This results in freeing only mblk_t and dblk_t structures for
1663af08d82Slm66018 	 * each mp. The associated data buffers are freed below as one big
1673af08d82Slm66018 	 * chunk through kmem_free(vmplp->datap).
1683af08d82Slm66018 	 */
1693af08d82Slm66018 	vmplp->flag |= VMPL_FLAG_DESTROYING;
1703af08d82Slm66018 	for (i = 0; i < num_mblks; i++) {
1713af08d82Slm66018 		vmp = &(vmplp->basep[i]);
1726f09f0feSWENTAO YANG 		/*
1736f09f0feSWENTAO YANG 		 * It is possible that mblks have been allocated only upto
1746f09f0feSWENTAO YANG 		 * a certain index and the entire quelen has not been
1756f09f0feSWENTAO YANG 		 * initialized. This might happen due to desballoc() failure
1766f09f0feSWENTAO YANG 		 * while creating the pool. The below check handles this
1776f09f0feSWENTAO YANG 		 * condition.
1786f09f0feSWENTAO YANG 		 */
1796f09f0feSWENTAO YANG 		if (vmp->mp != NULL)
1803af08d82Slm66018 			freeb(vmp->mp);
1813af08d82Slm66018 	}
1823af08d82Slm66018 	vmplp->flag &= ~(VMPL_FLAG_DESTROYING);
1833af08d82Slm66018 
1843af08d82Slm66018 	kmem_free(vmplp->basep, num_mblks * sizeof (vio_mblk_t));
1853af08d82Slm66018 	kmem_free(vmplp->datap, num_mblks * vmplp->mblk_size);
1863af08d82Slm66018 	kmem_free(vmplp->quep, num_mblks * sizeof (vio_mblk_t *));
187d10e4ef2Snarayan 
188d10e4ef2Snarayan 	mutex_destroy(&vmplp->hlock);
189d10e4ef2Snarayan 	mutex_destroy(&vmplp->tlock);
190d10e4ef2Snarayan 
191d10e4ef2Snarayan 	kmem_free(vmplp, sizeof (*vmplp));
192d10e4ef2Snarayan 
193d10e4ef2Snarayan 	return (0);
194d10e4ef2Snarayan }
195d10e4ef2Snarayan 
196d10e4ef2Snarayan /*
197d10e4ef2Snarayan  * Allocate a mblk from the free pool if one is available.
198d10e4ef2Snarayan  * Otherwise returns NULL.
199d10e4ef2Snarayan  */
200d10e4ef2Snarayan mblk_t *
201d10e4ef2Snarayan vio_allocb(vio_mblk_pool_t *vmplp)
202d10e4ef2Snarayan {
203d10e4ef2Snarayan 	vio_mblk_t	*vmp = NULL;
204d10e4ef2Snarayan 	mblk_t		*mp = NULL;
205d10e4ef2Snarayan 	uint32_t	head;
206d10e4ef2Snarayan 
207d10e4ef2Snarayan 	mutex_enter(&vmplp->hlock);
208d10e4ef2Snarayan 	head = (vmplp->head + 1) & vmplp->quemask;
209d10e4ef2Snarayan 	if (head != vmplp->tail) {
210d10e4ef2Snarayan 		/* we have free mblks */
211d10e4ef2Snarayan 		vmp = vmplp->quep[vmplp->head];
212d10e4ef2Snarayan 		mp = vmp->mp;
213d10e4ef2Snarayan 		vmplp->head = head;
214d10e4ef2Snarayan 	}
215d10e4ef2Snarayan 	mutex_exit(&vmplp->hlock);
216d10e4ef2Snarayan 
217d10e4ef2Snarayan 	return (mp);
218d10e4ef2Snarayan }
219d10e4ef2Snarayan 
220d10e4ef2Snarayan /*
221d10e4ef2Snarayan  * Return a mblk to the free pool. Invoked when the upper IP
222d10e4ef2Snarayan  * layers do freemsg() etc on the mblk they were passed.
223d10e4ef2Snarayan  */
224d10e4ef2Snarayan void
225d10e4ef2Snarayan vio_freeb(void *arg)
226d10e4ef2Snarayan {
227d10e4ef2Snarayan 	vio_mblk_t	*vmp = (vio_mblk_t *)arg;
228d10e4ef2Snarayan 	vio_mblk_pool_t	*vmplp = vmp->vmplp;
229d10e4ef2Snarayan 
2303af08d82Slm66018 	if (vmplp->flag & VMPL_FLAG_DESTROYING) {
2313af08d82Slm66018 		/*
2323af08d82Slm66018 		 * This flag indicates that freeb() is being called from
2333af08d82Slm66018 		 * vio_destroy_mblks().
2343af08d82Slm66018 		 * We don't need to alloc a new mblk_t/dblk_t pair for
2353af08d82Slm66018 		 * this data buffer, return from here and the data buffer
2363af08d82Slm66018 		 * itself will be freed in vio_destroy_mblks().
2373af08d82Slm66018 		 */
2383af08d82Slm66018 		return;
2393af08d82Slm66018 	}
2403af08d82Slm66018 
241d10e4ef2Snarayan 	vmp->mp = desballoc(vmp->datap, vmplp->mblk_size,
242d10e4ef2Snarayan 	    BPRI_MED, &vmp->reclaim);
243d10e4ef2Snarayan 
244d10e4ef2Snarayan 	mutex_enter(&vmplp->tlock);
245d10e4ef2Snarayan 	vmplp->quep[vmplp->tail] = vmp;
246d10e4ef2Snarayan 	vmplp->tail = (vmplp->tail + 1) & vmplp->quemask;
247d10e4ef2Snarayan 	mutex_exit(&vmplp->tlock);
248d10e4ef2Snarayan }
249844e62a3Sraghuram 
250844e62a3Sraghuram /*
251844e62a3Sraghuram  * Create a multiple pools of mblks from which future vio_allocb()
252844e62a3Sraghuram  * or vio_multipool_allocb() requests will be serviced.
253844e62a3Sraghuram  *
254844e62a3Sraghuram  * Arguments:
255844e62a3Sraghuram  *	vmultip -- A pointer to vio_multi_pool_t structure.
256844e62a3Sraghuram  *	num_pools -- Number of the pools.
257844e62a3Sraghuram  *	... -- Variable arguments consisting a list of buffer sizes for
258844e62a3Sraghuram  *		each pool and list of number of buffers for each pool.
259844e62a3Sraghuram  *
260844e62a3Sraghuram  * NOTE: The restrictions of vio_create_mblks() apply to this interface also.
261844e62a3Sraghuram  *
262844e62a3Sraghuram  * Returns 0 on success or an error returned by vio_create_mblks().
263844e62a3Sraghuram  */
264844e62a3Sraghuram int
265844e62a3Sraghuram vio_init_multipools(vio_multi_pool_t *vmultip, int num_pools, ...)
266844e62a3Sraghuram {
267844e62a3Sraghuram 	int		i;
268844e62a3Sraghuram 	int		status;
269844e62a3Sraghuram 	char		*tbuf;
270844e62a3Sraghuram 	va_list		vap;
271844e62a3Sraghuram 	vio_mblk_pool_t *fvmp = NULL;
272844e62a3Sraghuram 
273844e62a3Sraghuram 	/*
274844e62a3Sraghuram 	 * Allocate memory for all of the following in one allocation.
275844e62a3Sraghuram 	 * 	bufsz_tbl -- sizeof (uint32_t) * num_pools
276844e62a3Sraghuram 	 * 	nbuf_tbl  -- sizeof (uint32_t) * num_pools
277844e62a3Sraghuram 	 *	vmpp	  -- sizeof (vio_mblk_pool_t *) * numpools
278844e62a3Sraghuram 	 */
279844e62a3Sraghuram 	vmultip->tbsz = (sizeof (uint32_t) * num_pools) +
280844e62a3Sraghuram 	    (sizeof (uint32_t) * num_pools) +
281844e62a3Sraghuram 	    (sizeof (vio_mblk_pool_t *) * num_pools);
282844e62a3Sraghuram 	tbuf = kmem_zalloc(vmultip->tbsz, KM_SLEEP);
283844e62a3Sraghuram 	vmultip->bufsz_tbl = (uint32_t *)tbuf;
284844e62a3Sraghuram 	vmultip->nbuf_tbl = (uint32_t *)(tbuf +
285844e62a3Sraghuram 	    (sizeof (uint32_t) * num_pools));
286844e62a3Sraghuram 	vmultip->vmpp = (vio_mblk_pool_t **)(tbuf +
287844e62a3Sraghuram 	    (sizeof (uint32_t) * num_pools * 2));
288844e62a3Sraghuram 	vmultip->num_pools = num_pools;
289844e62a3Sraghuram 
290844e62a3Sraghuram 	/* initialize the array first */
291844e62a3Sraghuram 	va_start(vap, num_pools);
292844e62a3Sraghuram 	for (i = 0; i < num_pools; i++) {
293844e62a3Sraghuram 		vmultip->bufsz_tbl[i] = va_arg(vap, uint32_t);
294844e62a3Sraghuram 	}
295844e62a3Sraghuram 	for (i = 0; i < num_pools; i++) {
296844e62a3Sraghuram 		vmultip->nbuf_tbl[i] = va_arg(vap, uint32_t);
297844e62a3Sraghuram 	}
298844e62a3Sraghuram 	va_end(vap);
299844e62a3Sraghuram 
300844e62a3Sraghuram 	for (i = 0; i < vmultip->num_pools; i++) {
301844e62a3Sraghuram 		status = vio_create_mblks(vmultip->nbuf_tbl[i],
302844e62a3Sraghuram 		    vmultip->bufsz_tbl[i], &vmultip->vmpp[i]);
303844e62a3Sraghuram 		if (status != 0) {
304844e62a3Sraghuram 			vio_destroy_multipools(vmultip, &fvmp);
305844e62a3Sraghuram 			/* We expect to free the pools without failure here */
306844e62a3Sraghuram 			ASSERT(fvmp == NULL);
307844e62a3Sraghuram 			return (status);
308844e62a3Sraghuram 		}
309844e62a3Sraghuram 	}
310844e62a3Sraghuram 	return (0);
311844e62a3Sraghuram }
312844e62a3Sraghuram 
313844e62a3Sraghuram /*
314844e62a3Sraghuram  * Destroy the multiple pools of mblks. This can only succeed when
315844e62a3Sraghuram  * all allocated mblks have been returned to the pool.
316844e62a3Sraghuram  *
317844e62a3Sraghuram  * If a pool of mblks couldn't be destroyed, then the failed vio_mblk_pool_t
318844e62a3Sraghuram  * pointers are returned via th fvmp list. Its the caller's
319844e62a3Sraghuram  * responsibility to check this list and free them later at an appropriate
320844e62a3Sraghuram  * time with vio_destroy_mblks().
321844e62a3Sraghuram  *
322844e62a3Sraghuram  * Arguments:
323844e62a3Sraghuram  *	vmultip -- A pointer to vio_multi_pool_t structure.
324844e62a3Sraghuram  *	fvmp -- A list in which the pools that couldn't be destroyed are
325844e62a3Sraghuram  *		returned.
326844e62a3Sraghuram  */
327844e62a3Sraghuram void
328844e62a3Sraghuram vio_destroy_multipools(vio_multi_pool_t *vmultip, vio_mblk_pool_t **fvmp)
329844e62a3Sraghuram {
330844e62a3Sraghuram 	int i;
331844e62a3Sraghuram 	vio_mblk_pool_t *vmp;
332844e62a3Sraghuram 
333844e62a3Sraghuram 	for (i = 0; i < vmultip->num_pools; i++) {
334844e62a3Sraghuram 		if ((vmp = vmultip->vmpp[i]) != NULL) {
335844e62a3Sraghuram 			if (vio_destroy_mblks(vmp)) {
336844e62a3Sraghuram 				/*
337844e62a3Sraghuram 				 * if we cannot reclaim all mblks, then
338844e62a3Sraghuram 				 * return the pool in the failed vmp
339844e62a3Sraghuram 				 * list(fvmp).
340844e62a3Sraghuram 				 */
341844e62a3Sraghuram 				vmp->nextp =  *fvmp;
342844e62a3Sraghuram 				*fvmp = vmp;
343844e62a3Sraghuram 			}
344844e62a3Sraghuram 		}
345844e62a3Sraghuram 	}
3466f09f0feSWENTAO YANG 	if (vmultip->tbsz != 0)
347844e62a3Sraghuram 		kmem_free(vmultip->bufsz_tbl, vmultip->tbsz);
348844e62a3Sraghuram 	vmultip->bufsz_tbl = NULL;
349844e62a3Sraghuram 	vmultip->nbuf_tbl = NULL;
350844e62a3Sraghuram 	vmultip->vmpp = NULL;
3517b1f684aSSriharsha Basavapatna 	vmultip->num_pools = 0;
3527b1f684aSSriharsha Basavapatna 	vmultip->tbsz = 0;
353844e62a3Sraghuram }
354844e62a3Sraghuram 
355844e62a3Sraghuram 
356844e62a3Sraghuram /*
357844e62a3Sraghuram  * Allocate an mblk from one of the free pools, but tries the pool that
358844e62a3Sraghuram  * best fits size requested first.
359844e62a3Sraghuram  */
360844e62a3Sraghuram mblk_t *
361844e62a3Sraghuram vio_multipool_allocb(vio_multi_pool_t *vmultip, size_t size)
362844e62a3Sraghuram {
363844e62a3Sraghuram 	int i;
364844e62a3Sraghuram 	mblk_t *mp = NULL;
365844e62a3Sraghuram 
366844e62a3Sraghuram 	/* Try allocating any size that fits */
367844e62a3Sraghuram 	for (i = 0; i < vmultip->num_pools; i++) {
368844e62a3Sraghuram 		if (size > vmultip->bufsz_tbl[i]) {
369844e62a3Sraghuram 			continue;
370844e62a3Sraghuram 		}
371844e62a3Sraghuram 		mp = vio_allocb(vmultip->vmpp[i]);
372844e62a3Sraghuram 		if (mp != NULL) {
373844e62a3Sraghuram 			break;
374844e62a3Sraghuram 		}
375844e62a3Sraghuram 	}
376844e62a3Sraghuram 	return (mp);
377844e62a3Sraghuram }
37817cadca8Slm66018 
37917cadca8Slm66018 /*
38017cadca8Slm66018  * -----------------------------------------------------------------------------
38117cadca8Slm66018  * LDoms versioning functions
38217cadca8Slm66018  *
38317cadca8Slm66018  * Future work: the version negotiating code in the various VIO drivers
38417cadca8Slm66018  * could be made common and placed here.
38517cadca8Slm66018  */
38617cadca8Slm66018 
38717cadca8Slm66018 /*
38817cadca8Slm66018  * Description:
38917cadca8Slm66018  *	This function checks to see if the supplied version tuple (major,minor)
39017cadca8Slm66018  *	is supported by the version 'ver', negotiated during the handshake
39117cadca8Slm66018  *	between the client and the server (ver).
39217cadca8Slm66018  *
39317cadca8Slm66018  * Assumption:
39417cadca8Slm66018  *	This function assumes that backward compatability is not broken in
39517cadca8Slm66018  *	newer minor versions of the protocol (e.g. v1.5 & v1.1 support v1.0)
39617cadca8Slm66018  *
39717cadca8Slm66018  * Return Value:
39817cadca8Slm66018  *	B_TRUE		- The (major,minor) version is supported
39917cadca8Slm66018  *	B_FALSE		- not supported
40017cadca8Slm66018  */
40117cadca8Slm66018 boolean_t
40217cadca8Slm66018 vio_ver_is_supported(vio_ver_t ver, uint16_t major, uint16_t minor)
40317cadca8Slm66018 {
40417cadca8Slm66018 	if ((ver.major == major) && (ver.minor >= minor))
40517cadca8Slm66018 		return (B_TRUE);
40617cadca8Slm66018 
40717cadca8Slm66018 	return (B_FALSE);
40817cadca8Slm66018 }
409