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 /* 35 * inline function to get a list of pages from a dbuf 36 * 37 * dbuf - memory map from which to get the pa 38 * pa_list - physical address array to fill 39 * list_size - size of the array 40 * 41 * return none 42 */ 43 44 static void oce_list_del_node(OCE_LIST_NODE_T *prev_node, 45 OCE_LIST_NODE_T *next_node); 46 static void oce_list_remove(OCE_LIST_NODE_T *list_node); 47 static void oce_list_insert_node(OCE_LIST_NODE_T *list_node, 48 OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node); 49 /* 50 * function to breakup a block of memory into pages and return the address 51 * in an array 52 * 53 * dbuf - pointer to structure describing DMA-able memory 54 * pa_list - [OUT] pointer to an array to return the PA of pages 55 * list_size - number of entries in pa_list 56 */ 57 void 58 oce_page_list(oce_dma_buf_t *dbuf, 59 struct phys_addr *pa_list, int list_size) 60 { 61 int i = 0; 62 uint64_t paddr = 0; 63 64 ASSERT(dbuf != NULL); 65 ASSERT(pa_list != NULL); 66 67 paddr = DBUF_PA(dbuf); 68 for (i = 0; i < list_size; i++) { 69 pa_list[i].lo = ADDR_LO(paddr); 70 pa_list[i].hi = ADDR_HI(paddr); 71 paddr += PAGE_4K; 72 } 73 } /* oce_page_list */ 74 75 static inline void 76 oce_list_insert_node(OCE_LIST_NODE_T *list_node, OCE_LIST_NODE_T *prev_node, 77 OCE_LIST_NODE_T *next_node) 78 { 79 next_node->prev = list_node; 80 list_node->next = next_node; 81 list_node->prev = prev_node; 82 prev_node->next = list_node; 83 } 84 85 static inline void 86 oce_list_del_node(OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node) 87 { 88 next_node->prev = prev_node; 89 prev_node->next = next_node; 90 } 91 92 static inline void 93 oce_list_remove(OCE_LIST_NODE_T *list_node) 94 { 95 oce_list_del_node(list_node->prev, list_node->next); 96 list_node->next = list_node->prev = NULL; 97 } 98 99 void 100 oce_list_create(OCE_LIST_T *list_hdr, void *arg) 101 { 102 list_hdr->head.next = list_hdr->head.prev = &list_hdr->head; 103 mutex_init(&list_hdr->list_lock, NULL, MUTEX_DRIVER, arg); 104 list_hdr->nitems = 0; 105 } 106 107 void 108 oce_list_destroy(OCE_LIST_T *list_hdr) 109 { 110 ASSERT(list_hdr->nitems == 0); 111 list_hdr->head.next = list_hdr->head.prev = NULL; 112 mutex_destroy(&list_hdr->list_lock); 113 114 } 115 116 void 117 oce_list_insert_tail(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 118 { 119 OCE_LIST_NODE_T *head = &list_hdr->head; 120 121 ASSERT(list_hdr != NULL); 122 ASSERT(list_node != NULL); 123 124 mutex_enter(&list_hdr->list_lock); 125 oce_list_insert_node(list_node, head->prev, head); 126 list_hdr->nitems++; 127 mutex_exit(&list_hdr->list_lock); 128 } 129 130 void 131 oce_list_insert_head(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 132 { 133 OCE_LIST_NODE_T *head = &list_hdr->head; 134 135 ASSERT(list_hdr != NULL); 136 ASSERT(list_node != NULL); 137 138 mutex_enter(&list_hdr->list_lock); 139 oce_list_insert_node(list_node, head, head->next); 140 list_hdr->nitems++; 141 mutex_exit(&list_hdr->list_lock); 142 } 143 144 void * 145 oce_list_remove_tail(OCE_LIST_T *list_hdr) 146 { 147 OCE_LIST_NODE_T *list_node; 148 149 if (list_hdr == NULL) { 150 return (NULL); 151 } 152 153 mutex_enter(&list_hdr->list_lock); 154 155 if (list_hdr->nitems <= 0) { 156 mutex_exit(&list_hdr->list_lock); 157 return (NULL); 158 } 159 160 list_node = list_hdr->head.prev; 161 oce_list_remove(list_node); 162 list_hdr->nitems--; 163 mutex_exit(&list_hdr->list_lock); 164 return (list_node); 165 } 166 167 void * 168 oce_list_remove_head(OCE_LIST_T *list_hdr) 169 { 170 OCE_LIST_NODE_T *list_node; 171 172 if (list_hdr == NULL) { 173 return (NULL); 174 } 175 176 mutex_enter(&list_hdr->list_lock); 177 178 if (list_hdr->nitems <= 0) { 179 mutex_exit(&list_hdr->list_lock); 180 return (NULL); 181 } 182 183 list_node = list_hdr->head.next; 184 185 if (list_node != NULL) { 186 oce_list_remove(list_node); 187 list_hdr->nitems--; 188 } 189 190 mutex_exit(&list_hdr->list_lock); 191 return (list_node); 192 } 193 194 boolean_t 195 oce_list_is_empty(OCE_LIST_T *list_hdr) 196 { 197 if (list_hdr == NULL) 198 return (B_TRUE); 199 else 200 return (list_hdr->nitems <= 0); 201 } 202 203 int 204 oce_list_items_avail(OCE_LIST_T *list_hdr) 205 { 206 if (list_hdr == NULL) 207 return (0); 208 else 209 return (list_hdr->nitems); 210 } 211 212 void 213 oce_list_remove_node(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 214 { 215 mutex_enter(&list_hdr->list_lock); 216 oce_list_remove(list_node); 217 mutex_exit(&list_hdr->list_lock); 218 } 219