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 /* Copyright © 2003-2011 Emulex. All rights reserved. */ 23 24 /* 25 * Source file containing the implementation of the driver 26 * helper functions 27 */ 28 29 #include <oce_impl.h> 30 31 static void oce_list_del_node(OCE_LIST_NODE_T *prev_node, 32 OCE_LIST_NODE_T *next_node); 33 static void oce_list_remove(OCE_LIST_NODE_T *list_node); 34 static void oce_list_insert_node(OCE_LIST_NODE_T *list_node, 35 OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node); 36 /* 37 * function to breakup a block of memory into pages and return the address 38 * in an array 39 * 40 * dbuf - pointer to structure describing DMA-able memory 41 * pa_list - [OUT] pointer to an array to return the PA of pages 42 * list_size - number of entries in pa_list 43 */ 44 void 45 oce_page_list(oce_dma_buf_t *dbuf, 46 struct phys_addr *pa_list, int list_size) 47 { 48 int i = 0; 49 uint64_t paddr = 0; 50 51 ASSERT(dbuf != NULL); 52 ASSERT(pa_list != NULL); 53 54 paddr = DBUF_PA(dbuf); 55 for (i = 0; i < list_size; i++) { 56 pa_list[i].lo = ADDR_LO(paddr); 57 pa_list[i].hi = ADDR_HI(paddr); 58 paddr += PAGE_4K; 59 } 60 } /* oce_page_list */ 61 62 void 63 oce_list_link_init(OCE_LIST_NODE_T *list_node) 64 { 65 list_node->next = NULL; 66 list_node->prev = NULL; 67 } 68 69 static inline void 70 oce_list_insert_node(OCE_LIST_NODE_T *list_node, OCE_LIST_NODE_T *prev_node, 71 OCE_LIST_NODE_T *next_node) 72 { 73 next_node->prev = list_node; 74 list_node->next = next_node; 75 list_node->prev = prev_node; 76 prev_node->next = list_node; 77 } 78 79 static inline void 80 oce_list_del_node(OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node) 81 { 82 next_node->prev = prev_node; 83 prev_node->next = next_node; 84 } 85 86 static inline void 87 oce_list_remove(OCE_LIST_NODE_T *list_node) 88 { 89 oce_list_del_node(list_node->prev, list_node->next); 90 list_node->next = list_node->prev = NULL; 91 } 92 93 void 94 oce_list_create(OCE_LIST_T *list_hdr, void *arg) 95 { 96 list_hdr->head.next = list_hdr->head.prev = &list_hdr->head; 97 mutex_init(&list_hdr->list_lock, NULL, MUTEX_DRIVER, arg); 98 list_hdr->nitems = 0; 99 } 100 101 void 102 oce_list_destroy(OCE_LIST_T *list_hdr) 103 { 104 ASSERT(list_hdr->nitems == 0); 105 list_hdr->head.next = list_hdr->head.prev = NULL; 106 mutex_destroy(&list_hdr->list_lock); 107 108 } 109 110 void 111 oce_list_insert_tail(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 112 { 113 OCE_LIST_NODE_T *head = &list_hdr->head; 114 115 ASSERT(list_hdr != NULL); 116 ASSERT(list_node != NULL); 117 118 mutex_enter(&list_hdr->list_lock); 119 oce_list_insert_node(list_node, head->prev, head); 120 list_hdr->nitems++; 121 mutex_exit(&list_hdr->list_lock); 122 } 123 124 void 125 oce_list_insert_head(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 126 { 127 OCE_LIST_NODE_T *head = &list_hdr->head; 128 129 ASSERT(list_hdr != NULL); 130 ASSERT(list_node != NULL); 131 132 mutex_enter(&list_hdr->list_lock); 133 oce_list_insert_node(list_node, head, head->next); 134 list_hdr->nitems++; 135 mutex_exit(&list_hdr->list_lock); 136 } 137 138 void * 139 oce_list_remove_tail(OCE_LIST_T *list_hdr) 140 { 141 OCE_LIST_NODE_T *list_node; 142 143 if (list_hdr == NULL) { 144 return (NULL); 145 } 146 147 mutex_enter(&list_hdr->list_lock); 148 149 if (list_hdr->nitems <= 0) { 150 mutex_exit(&list_hdr->list_lock); 151 return (NULL); 152 } 153 154 list_node = list_hdr->head.prev; 155 oce_list_remove(list_node); 156 list_hdr->nitems--; 157 mutex_exit(&list_hdr->list_lock); 158 return (list_node); 159 } 160 161 void * 162 oce_list_remove_head(OCE_LIST_T *list_hdr) 163 { 164 OCE_LIST_NODE_T *list_node; 165 166 if (list_hdr == NULL) { 167 return (NULL); 168 } 169 170 mutex_enter(&list_hdr->list_lock); 171 172 if (list_hdr->nitems <= 0) { 173 mutex_exit(&list_hdr->list_lock); 174 return (NULL); 175 } 176 177 list_node = list_hdr->head.next; 178 179 if (list_node != NULL) { 180 oce_list_remove(list_node); 181 list_hdr->nitems--; 182 } 183 184 mutex_exit(&list_hdr->list_lock); 185 return (list_node); 186 } 187 188 boolean_t 189 oce_list_is_empty(OCE_LIST_T *list_hdr) 190 { 191 if (list_hdr == NULL) 192 return (B_TRUE); 193 else 194 return (list_hdr->nitems <= 0); 195 } 196 197 int 198 oce_list_items_avail(OCE_LIST_T *list_hdr) 199 { 200 if (list_hdr == NULL) 201 return (0); 202 else 203 return (list_hdr->nitems); 204 } 205 206 void 207 oce_list_remove_node(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 208 { 209 mutex_enter(&list_hdr->list_lock); 210 oce_list_remove(list_node); 211 mutex_exit(&list_hdr->list_lock); 212 } 213 214 void 215 oce_gen_hkey(char *hkey, int key_size) 216 { 217 int i; 218 int nkeys = key_size/sizeof (uint32_t); 219 for (i = 0; i < nkeys; i++) { 220 (void) random_get_pseudo_bytes( 221 (uint8_t *)&hkey[i * sizeof (uint32_t)], 222 sizeof (uint32_t)); 223 } 224 } 225 226 int 227 oce_atomic_reserve(uint32_t *count_p, uint32_t n) 228 { 229 uint32_t oldval; 230 uint32_t newval; 231 232 /* 233 * ATOMICALLY 234 */ 235 do { 236 oldval = *count_p; 237 if (oldval < n) 238 return (-1); 239 newval = oldval - n; 240 241 } while (atomic_cas_32(count_p, oldval, newval) != oldval); 242 243 return (newval); 244 } 245