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 static inline void 66 oce_list_insert_node(OCE_LIST_NODE_T *list_node, OCE_LIST_NODE_T *prev_node, 67 OCE_LIST_NODE_T *next_node) 68 { 69 next_node->prev = list_node; 70 list_node->next = next_node; 71 list_node->prev = prev_node; 72 prev_node->next = list_node; 73 } 74 75 static inline void 76 oce_list_del_node(OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node) 77 { 78 next_node->prev = prev_node; 79 prev_node->next = next_node; 80 } 81 82 static inline void 83 oce_list_remove(OCE_LIST_NODE_T *list_node) 84 { 85 oce_list_del_node(list_node->prev, list_node->next); 86 list_node->next = list_node->prev = NULL; 87 } 88 89 void 90 oce_list_create(OCE_LIST_T *list_hdr, void *arg) 91 { 92 list_hdr->head.next = list_hdr->head.prev = &list_hdr->head; 93 mutex_init(&list_hdr->list_lock, NULL, MUTEX_DRIVER, arg); 94 list_hdr->nitems = 0; 95 } 96 97 void 98 oce_list_destroy(OCE_LIST_T *list_hdr) 99 { 100 ASSERT(list_hdr->nitems == 0); 101 list_hdr->head.next = list_hdr->head.prev = NULL; 102 mutex_destroy(&list_hdr->list_lock); 103 104 } 105 106 void 107 oce_list_insert_tail(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 108 { 109 OCE_LIST_NODE_T *head = &list_hdr->head; 110 111 ASSERT(list_hdr != NULL); 112 ASSERT(list_node != NULL); 113 114 mutex_enter(&list_hdr->list_lock); 115 oce_list_insert_node(list_node, head->prev, head); 116 list_hdr->nitems++; 117 mutex_exit(&list_hdr->list_lock); 118 } 119 120 void 121 oce_list_insert_head(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 122 { 123 OCE_LIST_NODE_T *head = &list_hdr->head; 124 125 ASSERT(list_hdr != NULL); 126 ASSERT(list_node != NULL); 127 128 mutex_enter(&list_hdr->list_lock); 129 oce_list_insert_node(list_node, head, head->next); 130 list_hdr->nitems++; 131 mutex_exit(&list_hdr->list_lock); 132 } 133 134 void * 135 oce_list_remove_tail(OCE_LIST_T *list_hdr) 136 { 137 OCE_LIST_NODE_T *list_node; 138 139 if (list_hdr == NULL) { 140 return (NULL); 141 } 142 143 mutex_enter(&list_hdr->list_lock); 144 145 if (list_hdr->nitems <= 0) { 146 mutex_exit(&list_hdr->list_lock); 147 return (NULL); 148 } 149 150 list_node = list_hdr->head.prev; 151 oce_list_remove(list_node); 152 list_hdr->nitems--; 153 mutex_exit(&list_hdr->list_lock); 154 return (list_node); 155 } 156 157 void * 158 oce_list_remove_head(OCE_LIST_T *list_hdr) 159 { 160 OCE_LIST_NODE_T *list_node; 161 162 if (list_hdr == NULL) { 163 return (NULL); 164 } 165 166 mutex_enter(&list_hdr->list_lock); 167 168 if (list_hdr->nitems <= 0) { 169 mutex_exit(&list_hdr->list_lock); 170 return (NULL); 171 } 172 173 list_node = list_hdr->head.next; 174 175 if (list_node != NULL) { 176 oce_list_remove(list_node); 177 list_hdr->nitems--; 178 } 179 180 mutex_exit(&list_hdr->list_lock); 181 return (list_node); 182 } 183 184 boolean_t 185 oce_list_is_empty(OCE_LIST_T *list_hdr) 186 { 187 if (list_hdr == NULL) 188 return (B_TRUE); 189 else 190 return (list_hdr->nitems <= 0); 191 } 192 193 int 194 oce_list_items_avail(OCE_LIST_T *list_hdr) 195 { 196 if (list_hdr == NULL) 197 return (0); 198 else 199 return (list_hdr->nitems); 200 } 201 202 void 203 oce_list_remove_node(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node) 204 { 205 mutex_enter(&list_hdr->list_lock); 206 oce_list_remove(list_node); 207 mutex_exit(&list_hdr->list_lock); 208 } 209