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 /* 23*046cfe5cSSriharsha Basavapatna * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24d10e4ef2Snarayan */ 25d10e4ef2Snarayan 26d10e4ef2Snarayan #include <sys/types.h> 27d10e4ef2Snarayan #include <sys/sysmacros.h> 28d10e4ef2Snarayan #include <sys/errno.h> 29d10e4ef2Snarayan #include <sys/kmem.h> 30d10e4ef2Snarayan #include <sys/ksynch.h> 31d10e4ef2Snarayan #include <sys/stream.h> 32d10e4ef2Snarayan #include <sys/ddi.h> 33d10e4ef2Snarayan #include <sys/sunddi.h> 34d10e4ef2Snarayan #include <sys/vio_util.h> 35d10e4ef2Snarayan 366f09f0feSWENTAO YANG static int vio_pool_cleanup_retries = 10; /* Max retries to free pool */ 376f09f0feSWENTAO YANG static int vio_pool_cleanup_delay = 10000; /* 10ms */ 386f09f0feSWENTAO YANG 39d10e4ef2Snarayan /* 40d10e4ef2Snarayan * Create a pool of mblks from which future vio_allocb() requests 41d10e4ef2Snarayan * will be serviced. 42d10e4ef2Snarayan * 43d10e4ef2Snarayan * NOTE: num_mblks has to non-zero and a power-of-2 44d10e4ef2Snarayan * 456f09f0feSWENTAO YANG * Returns 466f09f0feSWENTAO YANG * 0 on success 476f09f0feSWENTAO YANG * EINVAL if num_mblks is zero or not a power of 2. 486f09f0feSWENTAO YANG * ENOSPC if the pool could not be created due to alloc failures. 49d10e4ef2Snarayan */ 50d10e4ef2Snarayan int 517bd3a2e2SSriharsha Basavapatna vio_create_mblks(uint64_t num_mblks, size_t mblk_size, uint8_t *mblk_datap, 527bd3a2e2SSriharsha Basavapatna vio_mblk_pool_t **poolp) 53d10e4ef2Snarayan { 54d10e4ef2Snarayan vio_mblk_pool_t *vmplp; 55d10e4ef2Snarayan vio_mblk_t *vmp; 56d10e4ef2Snarayan uint8_t *datap; 57d10e4ef2Snarayan int i; 583ab636deSWENTAO 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); 767bd3a2e2SSriharsha Basavapatna if (mblk_datap == NULL) { 77d10e4ef2Snarayan vmplp->datap = kmem_zalloc(num_mblks * mblk_size, KM_SLEEP); 787bd3a2e2SSriharsha Basavapatna } else { 797bd3a2e2SSriharsha Basavapatna vmplp->datap = mblk_datap; 807bd3a2e2SSriharsha Basavapatna vmplp->flag |= VMPL_FLAG_CLIENT_DATA; 817bd3a2e2SSriharsha Basavapatna } 82d10e4ef2Snarayan vmplp->nextp = NULL; 83d10e4ef2Snarayan 84d10e4ef2Snarayan /* create a queue of pointers to free vio_mblk_t's */ 85844e62a3Sraghuram vmplp->quep = kmem_zalloc(vmplp->quelen * 86844e62a3Sraghuram sizeof (vio_mblk_t *), KM_SLEEP); 87d10e4ef2Snarayan vmplp->head = 0; 88d10e4ef2Snarayan vmplp->tail = 0; 89d10e4ef2Snarayan 90d10e4ef2Snarayan for (i = 0, datap = vmplp->datap; i < num_mblks; i++) { 91d10e4ef2Snarayan 92d10e4ef2Snarayan vmp = &(vmplp->basep[i]); 93d10e4ef2Snarayan vmp->vmplp = vmplp; 94d10e4ef2Snarayan vmp->datap = datap; 95d10e4ef2Snarayan vmp->reclaim.free_func = vio_freeb; 96d10e4ef2Snarayan vmp->reclaim.free_arg = (caddr_t)vmp; 97d10e4ef2Snarayan vmp->mp = desballoc(vmp->datap, mblk_size, BPRI_MED, 98d10e4ef2Snarayan &vmp->reclaim); 99d10e4ef2Snarayan 1006f09f0feSWENTAO YANG if (vmp->mp == NULL) { 1016f09f0feSWENTAO YANG /* reset tail */ 1026f09f0feSWENTAO YANG vmplp->tail = vmplp->head; 1036f09f0feSWENTAO YANG 1046f09f0feSWENTAO YANG /* 1056f09f0feSWENTAO YANG * vio_destroy_mblks() frees mblks that have been 1066f09f0feSWENTAO YANG * allocated so far and then destroys the pool. 1076f09f0feSWENTAO YANG */ 1083ab636deSWENTAO YANG rv = vio_destroy_mblks(vmplp); 1093ab636deSWENTAO YANG ASSERT(rv == 0); 1106f09f0feSWENTAO YANG 1116f09f0feSWENTAO YANG *poolp = NULL; 1126f09f0feSWENTAO YANG return (ENOSPC); 1136f09f0feSWENTAO YANG } 114d10e4ef2Snarayan 1157bd3a2e2SSriharsha Basavapatna vmp->index = i; 1167bd3a2e2SSriharsha Basavapatna vmp->state = VIO_MBLK_FREE; 1177bd3a2e2SSriharsha Basavapatna 118d10e4ef2Snarayan /* put this vmp on the free stack */ 119d10e4ef2Snarayan vmplp->quep[vmplp->tail] = vmp; 120d10e4ef2Snarayan vmplp->tail = (vmplp->tail + 1) & vmplp->quemask; 121d10e4ef2Snarayan 122d10e4ef2Snarayan datap += mblk_size; 123d10e4ef2Snarayan } 124d10e4ef2Snarayan 125d10e4ef2Snarayan *poolp = vmplp; 126d10e4ef2Snarayan return (0); 127d10e4ef2Snarayan } 128d10e4ef2Snarayan 129d10e4ef2Snarayan /* 130d10e4ef2Snarayan * Destroy the pool of mblks. This can only succeed when 131d10e4ef2Snarayan * all allocated mblks have been returned to the pool. 132d10e4ef2Snarayan * 133d10e4ef2Snarayan * It is up to the caller to ensure that no further mblks are 134d10e4ef2Snarayan * requested from the pool after destroy has been invoked. 135d10e4ef2Snarayan * 136d10e4ef2Snarayan * Returns 0 on success, EINVAL if handle is invalid, or 137d10e4ef2Snarayan * EBUSY if not all mblks reclaimed yet. 138d10e4ef2Snarayan */ 139d10e4ef2Snarayan int 140d10e4ef2Snarayan vio_destroy_mblks(vio_mblk_pool_t *vmplp) 141d10e4ef2Snarayan { 1423af08d82Slm66018 uint64_t i; 1433af08d82Slm66018 uint64_t num_mblks; 1443af08d82Slm66018 vio_mblk_t *vmp; 1456f09f0feSWENTAO YANG int pool_cleanup_retries = 0; 1466f09f0feSWENTAO YANG 1473af08d82Slm66018 148d10e4ef2Snarayan if (vmplp == NULL) 149d10e4ef2Snarayan return (EINVAL); 150d10e4ef2Snarayan 151d10e4ef2Snarayan /* 152d10e4ef2Snarayan * We can only destroy the pool once all the mblks have 153d10e4ef2Snarayan * been reclaimed. 154d10e4ef2Snarayan */ 1556f09f0feSWENTAO YANG do { 1566f09f0feSWENTAO YANG if (vmplp->head == vmplp->tail) { 1576f09f0feSWENTAO YANG break; 1586f09f0feSWENTAO YANG } 1596f09f0feSWENTAO YANG 160d10e4ef2Snarayan /* some mblks still in use */ 1616f09f0feSWENTAO YANG drv_usecwait(vio_pool_cleanup_delay); 1626f09f0feSWENTAO YANG } while (++pool_cleanup_retries < vio_pool_cleanup_retries); 1636f09f0feSWENTAO YANG 1646f09f0feSWENTAO YANG if (vmplp->head != vmplp->tail) { 165d10e4ef2Snarayan return (EBUSY); 166d10e4ef2Snarayan } 167d10e4ef2Snarayan 1683af08d82Slm66018 num_mblks = vmplp->quelen; 1693af08d82Slm66018 1703af08d82Slm66018 /* 1713af08d82Slm66018 * Set pool flag to tell vio_freeb() which is invoked from freeb(), 1723af08d82Slm66018 * that it is being called in the context of vio_destroy_mblks(). 1733af08d82Slm66018 * This results in freeing only mblk_t and dblk_t structures for 1743af08d82Slm66018 * each mp. The associated data buffers are freed below as one big 1753af08d82Slm66018 * chunk through kmem_free(vmplp->datap). 1763af08d82Slm66018 */ 1773af08d82Slm66018 vmplp->flag |= VMPL_FLAG_DESTROYING; 1783af08d82Slm66018 for (i = 0; i < num_mblks; i++) { 1793af08d82Slm66018 vmp = &(vmplp->basep[i]); 1806f09f0feSWENTAO YANG /* 1816f09f0feSWENTAO YANG * It is possible that mblks have been allocated only upto 1826f09f0feSWENTAO YANG * a certain index and the entire quelen has not been 1836f09f0feSWENTAO YANG * initialized. This might happen due to desballoc() failure 1846f09f0feSWENTAO YANG * while creating the pool. The below check handles this 1856f09f0feSWENTAO YANG * condition. 1866f09f0feSWENTAO YANG */ 1876f09f0feSWENTAO YANG if (vmp->mp != NULL) 1883af08d82Slm66018 freeb(vmp->mp); 1893af08d82Slm66018 } 1903af08d82Slm66018 vmplp->flag &= ~(VMPL_FLAG_DESTROYING); 1913af08d82Slm66018 1923af08d82Slm66018 kmem_free(vmplp->basep, num_mblks * sizeof (vio_mblk_t)); 1937bd3a2e2SSriharsha Basavapatna if ((vmplp->flag & VMPL_FLAG_CLIENT_DATA) == 0) { 1943af08d82Slm66018 kmem_free(vmplp->datap, num_mblks * vmplp->mblk_size); 1957bd3a2e2SSriharsha Basavapatna } 1963af08d82Slm66018 kmem_free(vmplp->quep, num_mblks * sizeof (vio_mblk_t *)); 197d10e4ef2Snarayan 198d10e4ef2Snarayan mutex_destroy(&vmplp->hlock); 199d10e4ef2Snarayan mutex_destroy(&vmplp->tlock); 200d10e4ef2Snarayan 201d10e4ef2Snarayan kmem_free(vmplp, sizeof (*vmplp)); 202d10e4ef2Snarayan 203d10e4ef2Snarayan return (0); 204d10e4ef2Snarayan } 205d10e4ef2Snarayan 206d10e4ef2Snarayan /* 2077bd3a2e2SSriharsha Basavapatna * Allocate a vio_mblk from the free pool if one is available. 208d10e4ef2Snarayan * Otherwise returns NULL. 209d10e4ef2Snarayan */ 2107bd3a2e2SSriharsha Basavapatna vio_mblk_t * 211d10e4ef2Snarayan vio_allocb(vio_mblk_pool_t *vmplp) 212d10e4ef2Snarayan { 213d10e4ef2Snarayan vio_mblk_t *vmp = NULL; 214d10e4ef2Snarayan uint32_t head; 215d10e4ef2Snarayan 216d10e4ef2Snarayan mutex_enter(&vmplp->hlock); 217d10e4ef2Snarayan head = (vmplp->head + 1) & vmplp->quemask; 218d10e4ef2Snarayan if (head != vmplp->tail) { 219d10e4ef2Snarayan /* we have free mblks */ 220d10e4ef2Snarayan vmp = vmplp->quep[vmplp->head]; 221d10e4ef2Snarayan vmplp->head = head; 2227bd3a2e2SSriharsha Basavapatna ASSERT(vmp->state == VIO_MBLK_FREE); 2237bd3a2e2SSriharsha Basavapatna vmp->state = VIO_MBLK_BOUND; 224d10e4ef2Snarayan } 225d10e4ef2Snarayan mutex_exit(&vmplp->hlock); 226d10e4ef2Snarayan 2277bd3a2e2SSriharsha Basavapatna return (vmp); 228d10e4ef2Snarayan } 229d10e4ef2Snarayan 230d10e4ef2Snarayan /* 231d10e4ef2Snarayan * Return a mblk to the free pool. Invoked when the upper IP 232d10e4ef2Snarayan * layers do freemsg() etc on the mblk they were passed. 233d10e4ef2Snarayan */ 234d10e4ef2Snarayan void 235d10e4ef2Snarayan vio_freeb(void *arg) 236d10e4ef2Snarayan { 237d10e4ef2Snarayan vio_mblk_t *vmp = (vio_mblk_t *)arg; 238d10e4ef2Snarayan vio_mblk_pool_t *vmplp = vmp->vmplp; 239d10e4ef2Snarayan 2403af08d82Slm66018 if (vmplp->flag & VMPL_FLAG_DESTROYING) { 2413af08d82Slm66018 /* 2423af08d82Slm66018 * This flag indicates that freeb() is being called from 2433af08d82Slm66018 * vio_destroy_mblks(). 2443af08d82Slm66018 * We don't need to alloc a new mblk_t/dblk_t pair for 2453af08d82Slm66018 * this data buffer, return from here and the data buffer 2463af08d82Slm66018 * itself will be freed in vio_destroy_mblks(). 2473af08d82Slm66018 */ 2483af08d82Slm66018 return; 2493af08d82Slm66018 } 2503af08d82Slm66018 251d10e4ef2Snarayan vmp->mp = desballoc(vmp->datap, vmplp->mblk_size, 252d10e4ef2Snarayan BPRI_MED, &vmp->reclaim); 2537bd3a2e2SSriharsha Basavapatna vmp->state = VIO_MBLK_FREE; 254d10e4ef2Snarayan 255d10e4ef2Snarayan mutex_enter(&vmplp->tlock); 256d10e4ef2Snarayan vmplp->quep[vmplp->tail] = vmp; 257d10e4ef2Snarayan vmplp->tail = (vmplp->tail + 1) & vmplp->quemask; 258d10e4ef2Snarayan mutex_exit(&vmplp->tlock); 259d10e4ef2Snarayan } 260844e62a3Sraghuram 2617bd3a2e2SSriharsha Basavapatna 2627bd3a2e2SSriharsha Basavapatna /* 2637bd3a2e2SSriharsha Basavapatna * This function searches the given mblk pool for mblks that are in the 2647bd3a2e2SSriharsha Basavapatna * BOUND state and moves them to the FREE state. Note that only clients that 2657bd3a2e2SSriharsha Basavapatna * are operating in RxDringData mode use this function. This allows such 2667bd3a2e2SSriharsha Basavapatna * clients to reclaim buffers that are provided to the peer as shared memory, 2677bd3a2e2SSriharsha Basavapatna * before calling vio_destroy_mblks(). We don't need this in other cases 2687bd3a2e2SSriharsha Basavapatna * as the buffer is locally managed. 2697bd3a2e2SSriharsha Basavapatna */ 2707bd3a2e2SSriharsha Basavapatna void 2717bd3a2e2SSriharsha Basavapatna vio_clobber_pool(vio_mblk_pool_t *vmplp) 2727bd3a2e2SSriharsha Basavapatna { 2737bd3a2e2SSriharsha Basavapatna uint64_t num_mblks = vmplp->quelen; 2747bd3a2e2SSriharsha Basavapatna uint64_t i; 2757bd3a2e2SSriharsha Basavapatna vio_mblk_t *vmp; 2767bd3a2e2SSriharsha Basavapatna 2777bd3a2e2SSriharsha Basavapatna mutex_enter(&vmplp->hlock); 2787bd3a2e2SSriharsha Basavapatna mutex_enter(&vmplp->tlock); 2797bd3a2e2SSriharsha Basavapatna for (i = 0; i < num_mblks; i++) { 2807bd3a2e2SSriharsha Basavapatna vmp = &(vmplp->basep[i]); 2817bd3a2e2SSriharsha Basavapatna if ((vmp->state & VIO_MBLK_BOUND) != 0) { 2827bd3a2e2SSriharsha Basavapatna /* put this vmp on the free stack */ 2837bd3a2e2SSriharsha Basavapatna vmp->state = VIO_MBLK_FREE; 2847bd3a2e2SSriharsha Basavapatna ASSERT(vmplp->tail != vmplp->head); 2857bd3a2e2SSriharsha Basavapatna vmplp->quep[vmplp->tail] = vmp; 2867bd3a2e2SSriharsha Basavapatna vmplp->tail = (vmplp->tail + 1) & vmplp->quemask; 2877bd3a2e2SSriharsha Basavapatna } 2887bd3a2e2SSriharsha Basavapatna } 2897bd3a2e2SSriharsha Basavapatna mutex_exit(&vmplp->tlock); 2907bd3a2e2SSriharsha Basavapatna mutex_exit(&vmplp->hlock); 2917bd3a2e2SSriharsha Basavapatna } 2927bd3a2e2SSriharsha Basavapatna 293844e62a3Sraghuram /* 294844e62a3Sraghuram * Create a multiple pools of mblks from which future vio_allocb() 295844e62a3Sraghuram * or vio_multipool_allocb() requests will be serviced. 296844e62a3Sraghuram * 297844e62a3Sraghuram * Arguments: 298844e62a3Sraghuram * vmultip -- A pointer to vio_multi_pool_t structure. 299844e62a3Sraghuram * num_pools -- Number of the pools. 300844e62a3Sraghuram * ... -- Variable arguments consisting a list of buffer sizes for 301844e62a3Sraghuram * each pool and list of number of buffers for each pool. 302844e62a3Sraghuram * 303844e62a3Sraghuram * NOTE: The restrictions of vio_create_mblks() apply to this interface also. 304844e62a3Sraghuram * 305844e62a3Sraghuram * Returns 0 on success or an error returned by vio_create_mblks(). 306844e62a3Sraghuram */ 307844e62a3Sraghuram int 308844e62a3Sraghuram vio_init_multipools(vio_multi_pool_t *vmultip, int num_pools, ...) 309844e62a3Sraghuram { 310844e62a3Sraghuram int i; 311844e62a3Sraghuram int status; 312844e62a3Sraghuram char *tbuf; 313844e62a3Sraghuram va_list vap; 314844e62a3Sraghuram vio_mblk_pool_t *fvmp = NULL; 315844e62a3Sraghuram 316844e62a3Sraghuram /* 317844e62a3Sraghuram * Allocate memory for all of the following in one allocation. 318844e62a3Sraghuram * bufsz_tbl -- sizeof (uint32_t) * num_pools 319844e62a3Sraghuram * nbuf_tbl -- sizeof (uint32_t) * num_pools 320844e62a3Sraghuram * vmpp -- sizeof (vio_mblk_pool_t *) * numpools 321844e62a3Sraghuram */ 322844e62a3Sraghuram vmultip->tbsz = (sizeof (uint32_t) * num_pools) + 323844e62a3Sraghuram (sizeof (uint32_t) * num_pools) + 324844e62a3Sraghuram (sizeof (vio_mblk_pool_t *) * num_pools); 325844e62a3Sraghuram tbuf = kmem_zalloc(vmultip->tbsz, KM_SLEEP); 326844e62a3Sraghuram vmultip->bufsz_tbl = (uint32_t *)tbuf; 327844e62a3Sraghuram vmultip->nbuf_tbl = (uint32_t *)(tbuf + 328844e62a3Sraghuram (sizeof (uint32_t) * num_pools)); 329844e62a3Sraghuram vmultip->vmpp = (vio_mblk_pool_t **)(tbuf + 330844e62a3Sraghuram (sizeof (uint32_t) * num_pools * 2)); 331844e62a3Sraghuram vmultip->num_pools = num_pools; 332844e62a3Sraghuram 333844e62a3Sraghuram /* initialize the array first */ 334844e62a3Sraghuram va_start(vap, num_pools); 335844e62a3Sraghuram for (i = 0; i < num_pools; i++) { 336844e62a3Sraghuram vmultip->bufsz_tbl[i] = va_arg(vap, uint32_t); 337844e62a3Sraghuram } 338844e62a3Sraghuram for (i = 0; i < num_pools; i++) { 339844e62a3Sraghuram vmultip->nbuf_tbl[i] = va_arg(vap, uint32_t); 340844e62a3Sraghuram } 341844e62a3Sraghuram va_end(vap); 342844e62a3Sraghuram 343844e62a3Sraghuram for (i = 0; i < vmultip->num_pools; i++) { 344844e62a3Sraghuram status = vio_create_mblks(vmultip->nbuf_tbl[i], 3457bd3a2e2SSriharsha Basavapatna vmultip->bufsz_tbl[i], NULL, &vmultip->vmpp[i]); 346844e62a3Sraghuram if (status != 0) { 347844e62a3Sraghuram vio_destroy_multipools(vmultip, &fvmp); 348844e62a3Sraghuram /* We expect to free the pools without failure here */ 349844e62a3Sraghuram ASSERT(fvmp == NULL); 350844e62a3Sraghuram return (status); 351844e62a3Sraghuram } 352844e62a3Sraghuram } 353844e62a3Sraghuram return (0); 354844e62a3Sraghuram } 355844e62a3Sraghuram 356844e62a3Sraghuram /* 357844e62a3Sraghuram * Destroy the multiple pools of mblks. This can only succeed when 358844e62a3Sraghuram * all allocated mblks have been returned to the pool. 359844e62a3Sraghuram * 360844e62a3Sraghuram * If a pool of mblks couldn't be destroyed, then the failed vio_mblk_pool_t 361844e62a3Sraghuram * pointers are returned via th fvmp list. Its the caller's 362844e62a3Sraghuram * responsibility to check this list and free them later at an appropriate 363844e62a3Sraghuram * time with vio_destroy_mblks(). 364844e62a3Sraghuram * 365844e62a3Sraghuram * Arguments: 366844e62a3Sraghuram * vmultip -- A pointer to vio_multi_pool_t structure. 367844e62a3Sraghuram * fvmp -- A list in which the pools that couldn't be destroyed are 368844e62a3Sraghuram * returned. 369844e62a3Sraghuram */ 370844e62a3Sraghuram void 371844e62a3Sraghuram vio_destroy_multipools(vio_multi_pool_t *vmultip, vio_mblk_pool_t **fvmp) 372844e62a3Sraghuram { 373844e62a3Sraghuram int i; 374844e62a3Sraghuram vio_mblk_pool_t *vmp; 375844e62a3Sraghuram 376844e62a3Sraghuram for (i = 0; i < vmultip->num_pools; i++) { 377844e62a3Sraghuram if ((vmp = vmultip->vmpp[i]) != NULL) { 378844e62a3Sraghuram if (vio_destroy_mblks(vmp)) { 379844e62a3Sraghuram /* 380844e62a3Sraghuram * if we cannot reclaim all mblks, then 381844e62a3Sraghuram * return the pool in the failed vmp 382844e62a3Sraghuram * list(fvmp). 383844e62a3Sraghuram */ 384844e62a3Sraghuram vmp->nextp = *fvmp; 385844e62a3Sraghuram *fvmp = vmp; 386844e62a3Sraghuram } 387844e62a3Sraghuram } 388844e62a3Sraghuram } 3896f09f0feSWENTAO YANG if (vmultip->tbsz != 0) 390844e62a3Sraghuram kmem_free(vmultip->bufsz_tbl, vmultip->tbsz); 391844e62a3Sraghuram vmultip->bufsz_tbl = NULL; 392844e62a3Sraghuram vmultip->nbuf_tbl = NULL; 393844e62a3Sraghuram vmultip->vmpp = NULL; 3947b1f684aSSriharsha Basavapatna vmultip->num_pools = 0; 3957b1f684aSSriharsha Basavapatna vmultip->tbsz = 0; 396844e62a3Sraghuram } 397844e62a3Sraghuram 398844e62a3Sraghuram 399844e62a3Sraghuram /* 4007bd3a2e2SSriharsha Basavapatna * Allocate an vio_mblk from one of the free pools, but tries the pool that 401844e62a3Sraghuram * best fits size requested first. 402844e62a3Sraghuram */ 4037bd3a2e2SSriharsha Basavapatna vio_mblk_t * 404844e62a3Sraghuram vio_multipool_allocb(vio_multi_pool_t *vmultip, size_t size) 405844e62a3Sraghuram { 406844e62a3Sraghuram int i; 4077bd3a2e2SSriharsha Basavapatna vio_mblk_t *vmp = NULL; 408844e62a3Sraghuram 409844e62a3Sraghuram /* Try allocating any size that fits */ 410844e62a3Sraghuram for (i = 0; i < vmultip->num_pools; i++) { 411844e62a3Sraghuram if (size > vmultip->bufsz_tbl[i]) { 412844e62a3Sraghuram continue; 413844e62a3Sraghuram } 4147bd3a2e2SSriharsha Basavapatna vmp = vio_allocb(vmultip->vmpp[i]); 4157bd3a2e2SSriharsha Basavapatna if (vmp != NULL) { 416844e62a3Sraghuram break; 417844e62a3Sraghuram } 418844e62a3Sraghuram } 4197bd3a2e2SSriharsha Basavapatna return (vmp); 420844e62a3Sraghuram } 42117cadca8Slm66018 42217cadca8Slm66018 /* 42317cadca8Slm66018 * ----------------------------------------------------------------------------- 42417cadca8Slm66018 * LDoms versioning functions 42517cadca8Slm66018 * 42617cadca8Slm66018 * Future work: the version negotiating code in the various VIO drivers 42717cadca8Slm66018 * could be made common and placed here. 42817cadca8Slm66018 */ 42917cadca8Slm66018 43017cadca8Slm66018 /* 43117cadca8Slm66018 * Description: 43217cadca8Slm66018 * This function checks to see if the supplied version tuple (major,minor) 43317cadca8Slm66018 * is supported by the version 'ver', negotiated during the handshake 43417cadca8Slm66018 * between the client and the server (ver). 43517cadca8Slm66018 * 43617cadca8Slm66018 * Assumption: 43717cadca8Slm66018 * This function assumes that backward compatability is not broken in 43817cadca8Slm66018 * newer minor versions of the protocol (e.g. v1.5 & v1.1 support v1.0) 43917cadca8Slm66018 * 44017cadca8Slm66018 * Return Value: 44117cadca8Slm66018 * B_TRUE - The (major,minor) version is supported 44217cadca8Slm66018 * B_FALSE - not supported 44317cadca8Slm66018 */ 44417cadca8Slm66018 boolean_t 44517cadca8Slm66018 vio_ver_is_supported(vio_ver_t ver, uint16_t major, uint16_t minor) 44617cadca8Slm66018 { 44717cadca8Slm66018 if ((ver.major == major) && (ver.minor >= minor)) 44817cadca8Slm66018 return (B_TRUE); 44917cadca8Slm66018 45017cadca8Slm66018 return (B_FALSE); 45117cadca8Slm66018 } 452