111374SSukumar.Swaminathan@Sun.COM /*
211374SSukumar.Swaminathan@Sun.COM * CDDL HEADER START
311374SSukumar.Swaminathan@Sun.COM *
411374SSukumar.Swaminathan@Sun.COM * The contents of this file are subject to the terms of the
511374SSukumar.Swaminathan@Sun.COM * Common Development and Distribution License (the "License").
611374SSukumar.Swaminathan@Sun.COM * You may not use this file except in compliance with the License.
711374SSukumar.Swaminathan@Sun.COM *
811374SSukumar.Swaminathan@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911374SSukumar.Swaminathan@Sun.COM * or http://www.opensolaris.org/os/licensing.
1011374SSukumar.Swaminathan@Sun.COM * See the License for the specific language governing permissions
1111374SSukumar.Swaminathan@Sun.COM * and limitations under the License.
1211374SSukumar.Swaminathan@Sun.COM *
1311374SSukumar.Swaminathan@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1411374SSukumar.Swaminathan@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511374SSukumar.Swaminathan@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1611374SSukumar.Swaminathan@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1711374SSukumar.Swaminathan@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1811374SSukumar.Swaminathan@Sun.COM *
1911374SSukumar.Swaminathan@Sun.COM * CDDL HEADER END
2011374SSukumar.Swaminathan@Sun.COM */
2111374SSukumar.Swaminathan@Sun.COM
2211374SSukumar.Swaminathan@Sun.COM /*
2311374SSukumar.Swaminathan@Sun.COM * Copyright 2009 Emulex. All rights reserved.
2411374SSukumar.Swaminathan@Sun.COM * Use is subject to license terms.
2511374SSukumar.Swaminathan@Sun.COM */
2611374SSukumar.Swaminathan@Sun.COM
2711374SSukumar.Swaminathan@Sun.COM /*
2811374SSukumar.Swaminathan@Sun.COM * Source file containing the implementation of the driver
2911374SSukumar.Swaminathan@Sun.COM * helper functions
3011374SSukumar.Swaminathan@Sun.COM */
3111374SSukumar.Swaminathan@Sun.COM
3211374SSukumar.Swaminathan@Sun.COM #include <oce_impl.h>
3311374SSukumar.Swaminathan@Sun.COM
3411374SSukumar.Swaminathan@Sun.COM static void oce_list_del_node(OCE_LIST_NODE_T *prev_node,
3511374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *next_node);
3611374SSukumar.Swaminathan@Sun.COM static void oce_list_remove(OCE_LIST_NODE_T *list_node);
3711374SSukumar.Swaminathan@Sun.COM static void oce_list_insert_node(OCE_LIST_NODE_T *list_node,
3811374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node);
3911374SSukumar.Swaminathan@Sun.COM /*
4011374SSukumar.Swaminathan@Sun.COM * function to breakup a block of memory into pages and return the address
4111374SSukumar.Swaminathan@Sun.COM * in an array
4211374SSukumar.Swaminathan@Sun.COM *
4311374SSukumar.Swaminathan@Sun.COM * dbuf - pointer to structure describing DMA-able memory
4411374SSukumar.Swaminathan@Sun.COM * pa_list - [OUT] pointer to an array to return the PA of pages
4511374SSukumar.Swaminathan@Sun.COM * list_size - number of entries in pa_list
4611374SSukumar.Swaminathan@Sun.COM */
4711374SSukumar.Swaminathan@Sun.COM void
oce_page_list(oce_dma_buf_t * dbuf,struct phys_addr * pa_list,int list_size)4811374SSukumar.Swaminathan@Sun.COM oce_page_list(oce_dma_buf_t *dbuf,
4911374SSukumar.Swaminathan@Sun.COM struct phys_addr *pa_list, int list_size)
5011374SSukumar.Swaminathan@Sun.COM {
5111374SSukumar.Swaminathan@Sun.COM int i = 0;
5211374SSukumar.Swaminathan@Sun.COM uint64_t paddr = 0;
5311374SSukumar.Swaminathan@Sun.COM
5411374SSukumar.Swaminathan@Sun.COM ASSERT(dbuf != NULL);
5511374SSukumar.Swaminathan@Sun.COM ASSERT(pa_list != NULL);
5611374SSukumar.Swaminathan@Sun.COM
5711374SSukumar.Swaminathan@Sun.COM paddr = DBUF_PA(dbuf);
5811374SSukumar.Swaminathan@Sun.COM for (i = 0; i < list_size; i++) {
5911374SSukumar.Swaminathan@Sun.COM pa_list[i].lo = ADDR_LO(paddr);
6011374SSukumar.Swaminathan@Sun.COM pa_list[i].hi = ADDR_HI(paddr);
6111374SSukumar.Swaminathan@Sun.COM paddr += PAGE_4K;
6211374SSukumar.Swaminathan@Sun.COM }
6311374SSukumar.Swaminathan@Sun.COM } /* oce_page_list */
6411374SSukumar.Swaminathan@Sun.COM
65*13020SSukumar.Swaminathan@Sun.COM void
oce_list_link_init(OCE_LIST_NODE_T * list_node)66*13020SSukumar.Swaminathan@Sun.COM oce_list_link_init(OCE_LIST_NODE_T *list_node)
67*13020SSukumar.Swaminathan@Sun.COM {
68*13020SSukumar.Swaminathan@Sun.COM list_node->next = NULL;
69*13020SSukumar.Swaminathan@Sun.COM list_node->prev = NULL;
70*13020SSukumar.Swaminathan@Sun.COM }
71*13020SSukumar.Swaminathan@Sun.COM
7211374SSukumar.Swaminathan@Sun.COM static inline void
oce_list_insert_node(OCE_LIST_NODE_T * list_node,OCE_LIST_NODE_T * prev_node,OCE_LIST_NODE_T * next_node)7311374SSukumar.Swaminathan@Sun.COM oce_list_insert_node(OCE_LIST_NODE_T *list_node, OCE_LIST_NODE_T *prev_node,
7411374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *next_node)
7511374SSukumar.Swaminathan@Sun.COM {
7611374SSukumar.Swaminathan@Sun.COM next_node->prev = list_node;
7711374SSukumar.Swaminathan@Sun.COM list_node->next = next_node;
7811374SSukumar.Swaminathan@Sun.COM list_node->prev = prev_node;
7911374SSukumar.Swaminathan@Sun.COM prev_node->next = list_node;
8011374SSukumar.Swaminathan@Sun.COM }
8111374SSukumar.Swaminathan@Sun.COM
8211374SSukumar.Swaminathan@Sun.COM static inline void
oce_list_del_node(OCE_LIST_NODE_T * prev_node,OCE_LIST_NODE_T * next_node)8311374SSukumar.Swaminathan@Sun.COM oce_list_del_node(OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node)
8411374SSukumar.Swaminathan@Sun.COM {
8511374SSukumar.Swaminathan@Sun.COM next_node->prev = prev_node;
8611374SSukumar.Swaminathan@Sun.COM prev_node->next = next_node;
8711374SSukumar.Swaminathan@Sun.COM }
8811374SSukumar.Swaminathan@Sun.COM
8911374SSukumar.Swaminathan@Sun.COM static inline void
oce_list_remove(OCE_LIST_NODE_T * list_node)9011374SSukumar.Swaminathan@Sun.COM oce_list_remove(OCE_LIST_NODE_T *list_node)
9111374SSukumar.Swaminathan@Sun.COM {
9211374SSukumar.Swaminathan@Sun.COM oce_list_del_node(list_node->prev, list_node->next);
9311374SSukumar.Swaminathan@Sun.COM list_node->next = list_node->prev = NULL;
9411374SSukumar.Swaminathan@Sun.COM }
9511374SSukumar.Swaminathan@Sun.COM
9611374SSukumar.Swaminathan@Sun.COM void
oce_list_create(OCE_LIST_T * list_hdr,void * arg)9711374SSukumar.Swaminathan@Sun.COM oce_list_create(OCE_LIST_T *list_hdr, void *arg)
9811374SSukumar.Swaminathan@Sun.COM {
9911374SSukumar.Swaminathan@Sun.COM list_hdr->head.next = list_hdr->head.prev = &list_hdr->head;
10011374SSukumar.Swaminathan@Sun.COM mutex_init(&list_hdr->list_lock, NULL, MUTEX_DRIVER, arg);
10111374SSukumar.Swaminathan@Sun.COM list_hdr->nitems = 0;
10211374SSukumar.Swaminathan@Sun.COM }
10311374SSukumar.Swaminathan@Sun.COM
10411374SSukumar.Swaminathan@Sun.COM void
oce_list_destroy(OCE_LIST_T * list_hdr)10511374SSukumar.Swaminathan@Sun.COM oce_list_destroy(OCE_LIST_T *list_hdr)
10611374SSukumar.Swaminathan@Sun.COM {
10711374SSukumar.Swaminathan@Sun.COM ASSERT(list_hdr->nitems == 0);
10811374SSukumar.Swaminathan@Sun.COM list_hdr->head.next = list_hdr->head.prev = NULL;
10911374SSukumar.Swaminathan@Sun.COM mutex_destroy(&list_hdr->list_lock);
11011374SSukumar.Swaminathan@Sun.COM
11111374SSukumar.Swaminathan@Sun.COM }
11211374SSukumar.Swaminathan@Sun.COM
11311374SSukumar.Swaminathan@Sun.COM void
oce_list_insert_tail(OCE_LIST_T * list_hdr,OCE_LIST_NODE_T * list_node)11411374SSukumar.Swaminathan@Sun.COM oce_list_insert_tail(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node)
11511374SSukumar.Swaminathan@Sun.COM {
11611374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *head = &list_hdr->head;
11711374SSukumar.Swaminathan@Sun.COM
11811374SSukumar.Swaminathan@Sun.COM ASSERT(list_hdr != NULL);
11911374SSukumar.Swaminathan@Sun.COM ASSERT(list_node != NULL);
12011374SSukumar.Swaminathan@Sun.COM
12111374SSukumar.Swaminathan@Sun.COM mutex_enter(&list_hdr->list_lock);
12211374SSukumar.Swaminathan@Sun.COM oce_list_insert_node(list_node, head->prev, head);
12311374SSukumar.Swaminathan@Sun.COM list_hdr->nitems++;
12411374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
12511374SSukumar.Swaminathan@Sun.COM }
12611374SSukumar.Swaminathan@Sun.COM
12711374SSukumar.Swaminathan@Sun.COM void
oce_list_insert_head(OCE_LIST_T * list_hdr,OCE_LIST_NODE_T * list_node)12811374SSukumar.Swaminathan@Sun.COM oce_list_insert_head(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node)
12911374SSukumar.Swaminathan@Sun.COM {
13011374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *head = &list_hdr->head;
13111374SSukumar.Swaminathan@Sun.COM
13211374SSukumar.Swaminathan@Sun.COM ASSERT(list_hdr != NULL);
13311374SSukumar.Swaminathan@Sun.COM ASSERT(list_node != NULL);
13411374SSukumar.Swaminathan@Sun.COM
13511374SSukumar.Swaminathan@Sun.COM mutex_enter(&list_hdr->list_lock);
13611374SSukumar.Swaminathan@Sun.COM oce_list_insert_node(list_node, head, head->next);
13711374SSukumar.Swaminathan@Sun.COM list_hdr->nitems++;
13811374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
13911374SSukumar.Swaminathan@Sun.COM }
14011374SSukumar.Swaminathan@Sun.COM
14111374SSukumar.Swaminathan@Sun.COM void *
oce_list_remove_tail(OCE_LIST_T * list_hdr)14211374SSukumar.Swaminathan@Sun.COM oce_list_remove_tail(OCE_LIST_T *list_hdr)
14311374SSukumar.Swaminathan@Sun.COM {
14411374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *list_node;
14511374SSukumar.Swaminathan@Sun.COM
14611374SSukumar.Swaminathan@Sun.COM if (list_hdr == NULL) {
14711374SSukumar.Swaminathan@Sun.COM return (NULL);
14811374SSukumar.Swaminathan@Sun.COM }
14911374SSukumar.Swaminathan@Sun.COM
15011374SSukumar.Swaminathan@Sun.COM mutex_enter(&list_hdr->list_lock);
15111374SSukumar.Swaminathan@Sun.COM
15211374SSukumar.Swaminathan@Sun.COM if (list_hdr->nitems <= 0) {
15311374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
15411374SSukumar.Swaminathan@Sun.COM return (NULL);
15511374SSukumar.Swaminathan@Sun.COM }
15611374SSukumar.Swaminathan@Sun.COM
15711374SSukumar.Swaminathan@Sun.COM list_node = list_hdr->head.prev;
15811374SSukumar.Swaminathan@Sun.COM oce_list_remove(list_node);
15911374SSukumar.Swaminathan@Sun.COM list_hdr->nitems--;
16011374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
16111374SSukumar.Swaminathan@Sun.COM return (list_node);
16211374SSukumar.Swaminathan@Sun.COM }
16311374SSukumar.Swaminathan@Sun.COM
16411374SSukumar.Swaminathan@Sun.COM void *
oce_list_remove_head(OCE_LIST_T * list_hdr)16511374SSukumar.Swaminathan@Sun.COM oce_list_remove_head(OCE_LIST_T *list_hdr)
16611374SSukumar.Swaminathan@Sun.COM {
16711374SSukumar.Swaminathan@Sun.COM OCE_LIST_NODE_T *list_node;
16811374SSukumar.Swaminathan@Sun.COM
16911374SSukumar.Swaminathan@Sun.COM if (list_hdr == NULL) {
17011374SSukumar.Swaminathan@Sun.COM return (NULL);
17111374SSukumar.Swaminathan@Sun.COM }
17211374SSukumar.Swaminathan@Sun.COM
17311374SSukumar.Swaminathan@Sun.COM mutex_enter(&list_hdr->list_lock);
17411374SSukumar.Swaminathan@Sun.COM
17511374SSukumar.Swaminathan@Sun.COM if (list_hdr->nitems <= 0) {
17611374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
17711374SSukumar.Swaminathan@Sun.COM return (NULL);
17811374SSukumar.Swaminathan@Sun.COM }
17911374SSukumar.Swaminathan@Sun.COM
18011374SSukumar.Swaminathan@Sun.COM list_node = list_hdr->head.next;
18111374SSukumar.Swaminathan@Sun.COM
18211374SSukumar.Swaminathan@Sun.COM if (list_node != NULL) {
18311374SSukumar.Swaminathan@Sun.COM oce_list_remove(list_node);
18411374SSukumar.Swaminathan@Sun.COM list_hdr->nitems--;
18511374SSukumar.Swaminathan@Sun.COM }
18611374SSukumar.Swaminathan@Sun.COM
18711374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
18811374SSukumar.Swaminathan@Sun.COM return (list_node);
18911374SSukumar.Swaminathan@Sun.COM }
19011374SSukumar.Swaminathan@Sun.COM
19111374SSukumar.Swaminathan@Sun.COM boolean_t
oce_list_is_empty(OCE_LIST_T * list_hdr)19211374SSukumar.Swaminathan@Sun.COM oce_list_is_empty(OCE_LIST_T *list_hdr)
19311374SSukumar.Swaminathan@Sun.COM {
19411374SSukumar.Swaminathan@Sun.COM if (list_hdr == NULL)
19511374SSukumar.Swaminathan@Sun.COM return (B_TRUE);
19611374SSukumar.Swaminathan@Sun.COM else
19711374SSukumar.Swaminathan@Sun.COM return (list_hdr->nitems <= 0);
19811374SSukumar.Swaminathan@Sun.COM }
19911374SSukumar.Swaminathan@Sun.COM
20011374SSukumar.Swaminathan@Sun.COM int
oce_list_items_avail(OCE_LIST_T * list_hdr)20111374SSukumar.Swaminathan@Sun.COM oce_list_items_avail(OCE_LIST_T *list_hdr)
20211374SSukumar.Swaminathan@Sun.COM {
20311374SSukumar.Swaminathan@Sun.COM if (list_hdr == NULL)
20411374SSukumar.Swaminathan@Sun.COM return (0);
20511374SSukumar.Swaminathan@Sun.COM else
20611374SSukumar.Swaminathan@Sun.COM return (list_hdr->nitems);
20711374SSukumar.Swaminathan@Sun.COM }
20811374SSukumar.Swaminathan@Sun.COM
20911374SSukumar.Swaminathan@Sun.COM void
oce_list_remove_node(OCE_LIST_T * list_hdr,OCE_LIST_NODE_T * list_node)21011374SSukumar.Swaminathan@Sun.COM oce_list_remove_node(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node)
21111374SSukumar.Swaminathan@Sun.COM {
21211374SSukumar.Swaminathan@Sun.COM mutex_enter(&list_hdr->list_lock);
21311374SSukumar.Swaminathan@Sun.COM oce_list_remove(list_node);
21411374SSukumar.Swaminathan@Sun.COM mutex_exit(&list_hdr->list_lock);
21511374SSukumar.Swaminathan@Sun.COM }
216*13020SSukumar.Swaminathan@Sun.COM
217*13020SSukumar.Swaminathan@Sun.COM void
oce_gen_hkey(char * hkey,int key_size)218*13020SSukumar.Swaminathan@Sun.COM oce_gen_hkey(char *hkey, int key_size)
219*13020SSukumar.Swaminathan@Sun.COM {
220*13020SSukumar.Swaminathan@Sun.COM int i;
221*13020SSukumar.Swaminathan@Sun.COM int nkeys = key_size/sizeof (uint32_t);
222*13020SSukumar.Swaminathan@Sun.COM for (i = 0; i < nkeys; i++) {
223*13020SSukumar.Swaminathan@Sun.COM (void) random_get_pseudo_bytes(
224*13020SSukumar.Swaminathan@Sun.COM (uint8_t *)&hkey[i * sizeof (uint32_t)],
225*13020SSukumar.Swaminathan@Sun.COM sizeof (uint32_t));
226*13020SSukumar.Swaminathan@Sun.COM }
227*13020SSukumar.Swaminathan@Sun.COM }
228*13020SSukumar.Swaminathan@Sun.COM
229*13020SSukumar.Swaminathan@Sun.COM int
oce_atomic_reserve(uint32_t * count_p,uint32_t n)230*13020SSukumar.Swaminathan@Sun.COM oce_atomic_reserve(uint32_t *count_p, uint32_t n)
231*13020SSukumar.Swaminathan@Sun.COM {
232*13020SSukumar.Swaminathan@Sun.COM uint32_t oldval;
233*13020SSukumar.Swaminathan@Sun.COM uint32_t newval;
234*13020SSukumar.Swaminathan@Sun.COM
235*13020SSukumar.Swaminathan@Sun.COM /*
236*13020SSukumar.Swaminathan@Sun.COM * ATOMICALLY
237*13020SSukumar.Swaminathan@Sun.COM */
238*13020SSukumar.Swaminathan@Sun.COM do {
239*13020SSukumar.Swaminathan@Sun.COM oldval = *count_p;
240*13020SSukumar.Swaminathan@Sun.COM if (oldval < n)
241*13020SSukumar.Swaminathan@Sun.COM return (-1);
242*13020SSukumar.Swaminathan@Sun.COM newval = oldval - n;
243*13020SSukumar.Swaminathan@Sun.COM
244*13020SSukumar.Swaminathan@Sun.COM } while (atomic_cas_32(count_p, oldval, newval) != oldval);
245*13020SSukumar.Swaminathan@Sun.COM
246*13020SSukumar.Swaminathan@Sun.COM return (newval);
247*13020SSukumar.Swaminathan@Sun.COM }
248