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