xref: /onnv-gate/usr/src/uts/common/io/fibre-channel/fca/oce/oce_utils.c (revision 13020:1b6086d6d5a1)
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