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