1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _VIO_UTIL_H 28 #define _VIO_UTIL_H 29 30 #include <sys/stream.h> 31 #include <sys/vio_mailbox.h> 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 /* 38 * Helper routines for the Logical Domains (LDoms) drivers 39 * 40 * Note: The contents of this file are private to the implementation of the 41 * LDoms drivers and are subject to change at any time without notice. 42 */ 43 44 /* 45 * A message is composed of three structures. A message block (mblk_t), a 46 * data block to which it points and a data buffer. desballoc(9F) allows 47 * the caller to specify the data buffer and a free function which will 48 * be invoked when freeb(9F) is called to free the message. This allows 49 * the user to reclaim and reuse the data buffer, as opposed to using 50 * allocb(9F) where the message block, data block and data buffer are 51 * all destroyed by freeb(). 52 * 53 * Note that even with desballoc the message and data blocks are destroyed 54 * by freeb() and must be recreated. It is only the data buffer which is 55 * preserved. 56 * 57 * The caller first creates a pool of vio_mblk_t's by invoking 58 * vio_create_mblks() and specifying the number of mblks and the size of the 59 * associated data buffers. Each vio_mblk_t contains a pointer to the 60 * mblk_t, a pointer to the data buffer and a function pointer to the 61 * reclaim function. The caller is returned a pointer to the pool which is 62 * used in subsequent allocation/destroy requests. 63 * 64 * The pool is managed as a circular queue with a head and tail pointer. 65 * Allocation requests result in the head index being incremented, mblks 66 * being returned to the pool result in the tail pointer being incremented. 67 * 68 * The pool can only be destroyed when all the mblks have been returned. It 69 * is the responsibility of the caller to ensure that all vio_allocb() 70 * requests have been completed before the pool is destroyed. 71 * 72 * 73 * vio_mblk_pool_t 74 * +-------------+ 75 * | tail |--------------------------------+ 76 * +-------------+ | 77 * | head |--------+ | 78 * +-------------+ | | 79 * ............... V V 80 * +-------------+ +-------+-------+-------+-------+ 81 * | quep |---->| vmp_t | vmp_t | vmp_t | vmp_t | 82 * +-------------+ +-------+-------+-------+-------+ 83 * | | | | | | 84 * ... | | | | +------------+ 85 * | | | +-->| data block | 86 * | | | +------------+ 87 * | | | +------------+ 88 * | | +-->| data block | 89 * | | +------------+ 90 * | | +------------+ 91 * | +-->| data block | 92 * | +------------+ 93 * | +------------+ 94 * +-->| data block | 95 * +------------+ 96 * 97 */ 98 99 /* mblk pool flags */ 100 #define VMPL_FLAG_DESTROYING 0x1 /* pool is being destroyed */ 101 #define VMPL_FLAG_CLIENT_DATA 0x2 /* pool data area provided by client */ 102 103 struct vio_mblk_pool; 104 105 /* VIO mblk states */ 106 typedef enum vio_mblk_state { 107 VIO_MBLK_FREE = 0x1, /* free to use */ 108 VIO_MBLK_BOUND = 0x2, /* allocated/bound to a descriptor */ 109 VIO_MBLK_HAS_DATA = 0x4 /* contains valid data */ 110 } vio_mblk_state_t; 111 112 typedef struct vio_mblk { 113 uint8_t *datap; /* data buffer */ 114 mblk_t *mp; /* mblk using datap */ 115 frtn_t reclaim; /* mblk reclaim routine */ 116 struct vio_mblk_pool *vmplp; /* pointer to parent pool */ 117 uint_t index; /* index in the pool */ 118 vio_mblk_state_t state; /* state flags */ 119 } vio_mblk_t; 120 121 typedef struct vio_mblk_pool { 122 struct vio_mblk_pool *nextp; /* next in a list */ 123 kmutex_t hlock; /* sync access to head */ 124 kmutex_t tlock; /* sync access to tail */ 125 vio_mblk_t *basep; /* base pointer to pool of vio_mblks */ 126 vio_mblk_t **quep; /* queue of free vio_mblks */ 127 uint8_t *datap; /* rx data buffer area */ 128 uint32_t head; /* queue head */ 129 uint32_t tail; /* queue tail */ 130 uint64_t quelen; /* queue len (# mblks) */ 131 uint64_t quemask; /* quelen - 1 */ 132 size_t mblk_size; /* data buf size of each mblk */ 133 uint32_t flag; /* pool-related flags */ 134 } vio_mblk_pool_t; 135 136 typedef struct vio_multi_pool { 137 uint32_t num_pools; /* no. of vio mblk pools */ 138 uint32_t tbsz; /* allocated buffer size */ 139 uint32_t *bufsz_tbl; /* buffer sizes table */ 140 uint32_t *nbuf_tbl; /* no. of buffers table */ 141 vio_mblk_pool_t **vmpp; /* vio mblk pools */ 142 } vio_multi_pool_t; 143 144 #define VIO_MBLK_DATA_OFF(vmp) ((vmp)->datap - ((vmp)->vmplp)->datap) 145 146 int vio_create_mblks(uint64_t num_mblks, 147 size_t mblk_size, uint8_t *mblk_datap, 148 vio_mblk_pool_t **poolp); 149 int vio_destroy_mblks(vio_mblk_pool_t *); 150 vio_mblk_t *vio_allocb(vio_mblk_pool_t *); 151 void vio_freeb(void *arg); 152 int vio_init_multipools(vio_multi_pool_t *vmultip, int num_pools, ...); 153 void vio_destroy_multipools(vio_multi_pool_t *vmultip, vio_mblk_pool_t **fvmp); 154 vio_mblk_t *vio_multipool_allocb(vio_multi_pool_t *vmultip, size_t size); 155 int vio_check_pending_pools(vio_multi_pool_t *vmultip); 156 void vio_clobber_pool(vio_mblk_pool_t *vmplp); 157 158 /* VIO versioning helpers */ 159 #define VIO_VER_IS_NEGOTIATED(ver, maj, min) \ 160 ((ver.major == (maj)) && (ver.minor == (min))) 161 162 boolean_t vio_ver_is_supported(vio_ver_t ver, uint16_t maj, uint16_t min); 163 164 #ifdef __cplusplus 165 } 166 #endif 167 168 #endif /* _VIO_UTIL_H */ 169