14d0e5007SSukumar Swaminathan /*
24d0e5007SSukumar Swaminathan  * CDDL HEADER START
34d0e5007SSukumar Swaminathan  *
44d0e5007SSukumar Swaminathan  * The contents of this file are subject to the terms of the
54d0e5007SSukumar Swaminathan  * Common Development and Distribution License (the "License").
64d0e5007SSukumar Swaminathan  * You may not use this file except in compliance with the License.
74d0e5007SSukumar Swaminathan  *
84d0e5007SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94d0e5007SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
104d0e5007SSukumar Swaminathan  * See the License for the specific language governing permissions
114d0e5007SSukumar Swaminathan  * and limitations under the License.
124d0e5007SSukumar Swaminathan  *
134d0e5007SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
144d0e5007SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154d0e5007SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
164d0e5007SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
174d0e5007SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
184d0e5007SSukumar Swaminathan  *
194d0e5007SSukumar Swaminathan  * CDDL HEADER END
204d0e5007SSukumar Swaminathan  */
214d0e5007SSukumar Swaminathan 
22*3abb112fSGarrett D'Amore /* Copyright © 2003-2011 Emulex. All rights reserved.  */
234d0e5007SSukumar Swaminathan 
244d0e5007SSukumar Swaminathan /*
254d0e5007SSukumar Swaminathan  * Source file containing the implementation of the driver
264d0e5007SSukumar Swaminathan  * helper functions
274d0e5007SSukumar Swaminathan  */
284d0e5007SSukumar Swaminathan 
294d0e5007SSukumar Swaminathan #include <oce_impl.h>
304d0e5007SSukumar Swaminathan 
314d0e5007SSukumar Swaminathan static void oce_list_del_node(OCE_LIST_NODE_T *prev_node,
324d0e5007SSukumar Swaminathan     OCE_LIST_NODE_T *next_node);
334d0e5007SSukumar Swaminathan static void oce_list_remove(OCE_LIST_NODE_T *list_node);
344d0e5007SSukumar Swaminathan static void oce_list_insert_node(OCE_LIST_NODE_T  *list_node,
354d0e5007SSukumar Swaminathan     OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node);
364d0e5007SSukumar Swaminathan /*
374d0e5007SSukumar Swaminathan  * function to breakup a block of memory into pages and return the address
384d0e5007SSukumar Swaminathan  * in an array
394d0e5007SSukumar Swaminathan  *
404d0e5007SSukumar Swaminathan  * dbuf - pointer to structure describing DMA-able memory
414d0e5007SSukumar Swaminathan  * pa_list - [OUT] pointer to an array to return the PA of pages
424d0e5007SSukumar Swaminathan  * list_size - number of entries in pa_list
434d0e5007SSukumar Swaminathan  */
444d0e5007SSukumar Swaminathan void
oce_page_list(oce_dma_buf_t * dbuf,struct phys_addr * pa_list,int list_size)454d0e5007SSukumar Swaminathan oce_page_list(oce_dma_buf_t *dbuf,
464d0e5007SSukumar Swaminathan     struct phys_addr *pa_list, int list_size)
474d0e5007SSukumar Swaminathan {
484d0e5007SSukumar Swaminathan 	int i = 0;
494d0e5007SSukumar Swaminathan 	uint64_t paddr = 0;
504d0e5007SSukumar Swaminathan 
514d0e5007SSukumar Swaminathan 	ASSERT(dbuf != NULL);
524d0e5007SSukumar Swaminathan 	ASSERT(pa_list != NULL);
534d0e5007SSukumar Swaminathan 
544d0e5007SSukumar Swaminathan 	paddr = DBUF_PA(dbuf);
554d0e5007SSukumar Swaminathan 	for (i = 0; i < list_size; i++) {
564d0e5007SSukumar Swaminathan 		pa_list[i].lo = ADDR_LO(paddr);
574d0e5007SSukumar Swaminathan 		pa_list[i].hi = ADDR_HI(paddr);
584d0e5007SSukumar Swaminathan 		paddr += PAGE_4K;
594d0e5007SSukumar Swaminathan 	}
604d0e5007SSukumar Swaminathan } /* oce_page_list */
614d0e5007SSukumar Swaminathan 
625b9d3151SSukumar Swaminathan void
oce_list_link_init(OCE_LIST_NODE_T * list_node)635b9d3151SSukumar Swaminathan oce_list_link_init(OCE_LIST_NODE_T  *list_node)
645b9d3151SSukumar Swaminathan {
655b9d3151SSukumar Swaminathan 	list_node->next = NULL;
665b9d3151SSukumar Swaminathan 	list_node->prev = NULL;
675b9d3151SSukumar Swaminathan }
685b9d3151SSukumar Swaminathan 
694d0e5007SSukumar Swaminathan 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)704d0e5007SSukumar Swaminathan oce_list_insert_node(OCE_LIST_NODE_T  *list_node, OCE_LIST_NODE_T *prev_node,
714d0e5007SSukumar Swaminathan     OCE_LIST_NODE_T *next_node)
724d0e5007SSukumar Swaminathan {
734d0e5007SSukumar Swaminathan 	next_node->prev = list_node;
744d0e5007SSukumar Swaminathan 	list_node->next = next_node;
754d0e5007SSukumar Swaminathan 	list_node->prev = prev_node;
764d0e5007SSukumar Swaminathan 	prev_node->next = list_node;
774d0e5007SSukumar Swaminathan }
784d0e5007SSukumar Swaminathan 
794d0e5007SSukumar Swaminathan static inline void
oce_list_del_node(OCE_LIST_NODE_T * prev_node,OCE_LIST_NODE_T * next_node)804d0e5007SSukumar Swaminathan oce_list_del_node(OCE_LIST_NODE_T *prev_node, OCE_LIST_NODE_T *next_node)
814d0e5007SSukumar Swaminathan {
824d0e5007SSukumar Swaminathan 	next_node->prev = prev_node;
834d0e5007SSukumar Swaminathan 	prev_node->next = next_node;
844d0e5007SSukumar Swaminathan }
854d0e5007SSukumar Swaminathan 
864d0e5007SSukumar Swaminathan static inline void
oce_list_remove(OCE_LIST_NODE_T * list_node)874d0e5007SSukumar Swaminathan oce_list_remove(OCE_LIST_NODE_T *list_node)
884d0e5007SSukumar Swaminathan {
894d0e5007SSukumar Swaminathan 	oce_list_del_node(list_node->prev, list_node->next);
904d0e5007SSukumar Swaminathan 	list_node->next = list_node->prev = NULL;
914d0e5007SSukumar Swaminathan }
924d0e5007SSukumar Swaminathan 
934d0e5007SSukumar Swaminathan void
oce_list_create(OCE_LIST_T * list_hdr,void * arg)944d0e5007SSukumar Swaminathan oce_list_create(OCE_LIST_T  *list_hdr, void *arg)
954d0e5007SSukumar Swaminathan {
964d0e5007SSukumar Swaminathan 	list_hdr->head.next = list_hdr->head.prev = &list_hdr->head;
974d0e5007SSukumar Swaminathan 	mutex_init(&list_hdr->list_lock, NULL, MUTEX_DRIVER, arg);
984d0e5007SSukumar Swaminathan 	list_hdr->nitems = 0;
994d0e5007SSukumar Swaminathan }
1004d0e5007SSukumar Swaminathan 
1014d0e5007SSukumar Swaminathan void
oce_list_destroy(OCE_LIST_T * list_hdr)1024d0e5007SSukumar Swaminathan oce_list_destroy(OCE_LIST_T *list_hdr)
1034d0e5007SSukumar Swaminathan {
1044d0e5007SSukumar Swaminathan 	ASSERT(list_hdr->nitems == 0);
1054d0e5007SSukumar Swaminathan 	list_hdr->head.next = list_hdr->head.prev = NULL;
1064d0e5007SSukumar Swaminathan 	mutex_destroy(&list_hdr->list_lock);
1074d0e5007SSukumar Swaminathan 
1084d0e5007SSukumar Swaminathan }
1094d0e5007SSukumar Swaminathan 
1104d0e5007SSukumar Swaminathan void
oce_list_insert_tail(OCE_LIST_T * list_hdr,OCE_LIST_NODE_T * list_node)1114d0e5007SSukumar Swaminathan oce_list_insert_tail(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node)
1124d0e5007SSukumar Swaminathan {
1134d0e5007SSukumar Swaminathan 	OCE_LIST_NODE_T *head = &list_hdr->head;
1144d0e5007SSukumar Swaminathan 
1154d0e5007SSukumar Swaminathan 	ASSERT(list_hdr != NULL);
1164d0e5007SSukumar Swaminathan 	ASSERT(list_node != NULL);
1174d0e5007SSukumar Swaminathan 
1184d0e5007SSukumar Swaminathan 	mutex_enter(&list_hdr->list_lock);
1194d0e5007SSukumar Swaminathan 	oce_list_insert_node(list_node, head->prev, head);
1204d0e5007SSukumar Swaminathan 	list_hdr->nitems++;
1214d0e5007SSukumar Swaminathan 	mutex_exit(&list_hdr->list_lock);
1224d0e5007SSukumar Swaminathan }
1234d0e5007SSukumar Swaminathan 
1244d0e5007SSukumar Swaminathan void
oce_list_insert_head(OCE_LIST_T * list_hdr,OCE_LIST_NODE_T * list_node)1254d0e5007SSukumar Swaminathan oce_list_insert_head(OCE_LIST_T *list_hdr, OCE_LIST_NODE_T *list_node)
1264d0e5007SSukumar Swaminathan {
1274d0e5007SSukumar Swaminathan 	OCE_LIST_NODE_T *head = &list_hdr->head;
1284d0e5007SSukumar Swaminathan 
1294d0e5007SSukumar Swaminathan 	ASSERT(list_hdr != NULL);
1304d0e5007SSukumar Swaminathan 	ASSERT(list_node != NULL);
1314d0e5007SSukumar Swaminathan 
1324d0e5007SSukumar Swaminathan 	mutex_enter(&list_hdr->list_lock);
1334d0e5007SSukumar Swaminathan 	oce_list_insert_node(list_node, head, head->next);
1344d0e5007SSukumar Swaminathan 	list_hdr->nitems++;
1354d0e5007SSukumar Swaminathan 	mutex_exit(&list_hdr->list_lock);
1364d0e5007SSukumar Swaminathan }
1374d0e5007SSukumar Swaminathan 
1384d0e5007SSukumar Swaminathan void *
oce_list_remove_tail(OCE_LIST_T * list_hdr)1394d0e5007SSukumar Swaminathan oce_list_remove_tail(OCE_LIST_T *list_hdr)
1404d0e5007SSukumar Swaminathan {
1414d0e5007SSukumar Swaminathan 	OCE_LIST_NODE_T *list_node;
1424d0e5007SSukumar Swaminathan 
1434d0e5007SSukumar Swaminathan 	if (list_hdr == NULL) {
1444d0e5007SSukumar Swaminathan 		return (NULL);
1454d0e5007SSukumar Swaminathan 	}
1464d0e5007SSukumar Swaminathan 
1474d0e5007SSukumar Swaminathan 	mutex_enter(&list_hdr->list_lock);
1484d0e5007SSukumar Swaminathan 
1494d0e5007SSukumar Swaminathan 	if (list_hdr->nitems <= 0) {
1504d0e5007SSukumar Swaminathan 		mutex_exit(&list_hdr->list_lock);
1514d0e5007SSukumar Swaminathan 		return (NULL);
1524d0e5007SSukumar Swaminathan 	}
1534d0e5007SSukumar Swaminathan 
1544d0e5007SSukumar Swaminathan 	list_node = list_hdr->head.prev;
1554d0e5007SSukumar Swaminathan 	oce_list_remove(list_node);
1564d0e5007SSukumar Swaminathan 	list_hdr->nitems--;
1574d0e5007SSukumar Swaminathan 	mutex_exit(&list_hdr->list_lock);
1584d0e5007SSukumar Swaminathan 	return (list_node);
1594d0e5007SSukumar Swaminathan }
1604d0e5007SSukumar Swaminathan 
1614d0e5007SSukumar Swaminathan void *
oce_list_remove_head(OCE_LIST_T * list_hdr)1624d0e5007SSukumar Swaminathan oce_list_remove_head(OCE_LIST_T  *list_hdr)
1634d0e5007SSukumar Swaminathan {
1644d0e5007SSukumar Swaminathan 	OCE_LIST_NODE_T *list_node;
1654d0e5007SSukumar Swaminathan 
1664d0e5007SSukumar Swaminathan 	if (list_hdr == NULL) {
1674d0e5007SSukumar Swaminathan 		return (NULL);
1684d0e5007SSukumar Swaminathan 	}
1694d0e5007SSukumar Swaminathan 
1704d0e5007SSukumar Swaminathan 	mutex_enter(&list_hdr->list_lock);
1714d0e5007SSukumar Swaminathan 
1724d0e5007SSukumar Swaminathan 	if (list_hdr->nitems <= 0) {
1734d0e5007SSukumar Swaminathan 		mutex_exit(&list_hdr->list_lock);
1744d0e5007SSukumar Swaminathan 		return (NULL);
1754d0e5007SSukumar Swaminathan 	}
1764d0e5007SSukumar Swaminathan 
1774d0e5007SSukumar Swaminathan 	list_node = list_hdr->head.next;
1784d0e5007SSukumar Swaminathan 
1794d0e5007SSukumar Swaminathan 	if (list_node != NULL) {
1804d0e5007SSukumar Swaminathan 		oce_list_remove(list_node);
1814d0e5007SSukumar Swaminathan 		list_hdr->nitems--;
1824d0e5007SSukumar Swaminathan 	}
1834d0e5007SSukumar Swaminathan 
1844d0e5007SSukumar Swaminathan 	mutex_exit(&list_hdr->list_lock);
1854d0e5007SSukumar Swaminathan 	return (list_node);
1864d0e5007SSukumar Swaminathan }
1874d0e5007SSukumar Swaminathan 
1884d0e5007SSukumar Swaminathan boolean_t
oce_list_is_empty(OCE_LIST_T * list_hdr)1894d0e5007SSukumar Swaminathan oce_list_is_empty(OCE_LIST_T *list_hdr)
1904d0e5007SSukumar Swaminathan {
1914d0e5007SSukumar Swaminathan 	if (list_hdr == NULL)
1924d0e5007SSukumar Swaminathan 		return (B_TRUE);
1934d0e5007SSukumar Swaminathan 	else
1944d0e5007SSukumar Swaminathan 		return (list_hdr->nitems <= 0);
1954d0e5007SSukumar Swaminathan }
1964d0e5007SSukumar Swaminathan 
1974d0e5007SSukumar Swaminathan int
oce_list_items_avail(OCE_LIST_T * list_hdr)1984d0e5007SSukumar Swaminathan oce_list_items_avail(OCE_LIST_T *list_hdr)
1994d0e5007SSukumar Swaminathan {
2004d0e5007SSukumar Swaminathan 	if (list_hdr == NULL)
2014d0e5007SSukumar Swaminathan 		return (0);
2024d0e5007SSukumar Swaminathan 	else
2034d0e5007SSukumar Swaminathan 		return (list_hdr->nitems);
2044d0e5007SSukumar Swaminathan }
2054d0e5007SSukumar Swaminathan 
2064d0e5007SSukumar Swaminathan void
oce_list_remove_node(OCE_LIST_T * list_hdr,OCE_LIST_NODE_T * list_node)2074d0e5007SSukumar Swaminathan oce_list_remove_node(OCE_LIST_T  *list_hdr, OCE_LIST_NODE_T *list_node)
2084d0e5007SSukumar Swaminathan {
2094d0e5007SSukumar Swaminathan 	mutex_enter(&list_hdr->list_lock);
2104d0e5007SSukumar Swaminathan 	oce_list_remove(list_node);
2114d0e5007SSukumar Swaminathan 	mutex_exit(&list_hdr->list_lock);
2124d0e5007SSukumar Swaminathan }
2135b9d3151SSukumar Swaminathan 
2145b9d3151SSukumar Swaminathan void
oce_gen_hkey(char * hkey,int key_size)2155b9d3151SSukumar Swaminathan oce_gen_hkey(char *hkey, int key_size)
2165b9d3151SSukumar Swaminathan {
2175b9d3151SSukumar Swaminathan 	int i;
2185b9d3151SSukumar Swaminathan 	int nkeys = key_size/sizeof (uint32_t);
2195b9d3151SSukumar Swaminathan 	for (i = 0; i < nkeys; i++) {
2205b9d3151SSukumar Swaminathan 		(void) random_get_pseudo_bytes(
2215b9d3151SSukumar Swaminathan 		    (uint8_t *)&hkey[i * sizeof (uint32_t)],
2225b9d3151SSukumar Swaminathan 		    sizeof (uint32_t));
2235b9d3151SSukumar Swaminathan 	}
2245b9d3151SSukumar Swaminathan }
2255b9d3151SSukumar Swaminathan 
2265b9d3151SSukumar Swaminathan int
oce_atomic_reserve(uint32_t * count_p,uint32_t n)2275b9d3151SSukumar Swaminathan oce_atomic_reserve(uint32_t *count_p, uint32_t n)
2285b9d3151SSukumar Swaminathan {
2295b9d3151SSukumar Swaminathan 	uint32_t oldval;
2305b9d3151SSukumar Swaminathan 	uint32_t newval;
2315b9d3151SSukumar Swaminathan 
2325b9d3151SSukumar Swaminathan 	/*
2335b9d3151SSukumar Swaminathan 	 * ATOMICALLY
2345b9d3151SSukumar Swaminathan 	 */
2355b9d3151SSukumar Swaminathan 	do {
2365b9d3151SSukumar Swaminathan 		oldval = *count_p;
2375b9d3151SSukumar Swaminathan 		if (oldval < n)
2385b9d3151SSukumar Swaminathan 			return (-1);
2395b9d3151SSukumar Swaminathan 		newval = oldval - n;
2405b9d3151SSukumar Swaminathan 
2415b9d3151SSukumar Swaminathan 	} while (atomic_cas_32(count_p, oldval, newval) != oldval);
2425b9d3151SSukumar Swaminathan 
2435b9d3151SSukumar Swaminathan 	return (newval);
2445b9d3151SSukumar Swaminathan }
245