xref: /onnv-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-channel.c (revision 6937:a5e2c8b5c817)
11256Syl150051 /*
21256Syl150051  * CDDL HEADER START
31256Syl150051  *
41256Syl150051  * The contents of this file are subject to the terms of the
51256Syl150051  * Common Development and Distribution License (the "License").
61256Syl150051  * You may not use this file except in compliance with the License.
71256Syl150051  *
81256Syl150051  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91256Syl150051  * or http://www.opensolaris.org/os/licensing.
101256Syl150051  * See the License for the specific language governing permissions
111256Syl150051  * and limitations under the License.
121256Syl150051  *
131256Syl150051  * When distributing Covered Code, include this CDDL HEADER in each
141256Syl150051  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151256Syl150051  * If applicable, add the following below this CDDL HEADER, with the
161256Syl150051  * fields enclosed by brackets "[]" replaced with your own identifying
171256Syl150051  * information: Portions Copyright [yyyy] [name of copyright owner]
181256Syl150051  *
191256Syl150051  * CDDL HEADER END
201256Syl150051  *
213115Syl150051  * Copyright (c) 2002-2006 Neterion, Inc.
221256Syl150051  */
231256Syl150051 
241256Syl150051 #include "xgehal-channel.h"
251256Syl150051 #include "xgehal-fifo.h"
261256Syl150051 #include "xgehal-ring.h"
271256Syl150051 #include "xgehal-device.h"
281256Syl150051 #include "xgehal-regs.h"
291256Syl150051 
301256Syl150051 /*
311256Syl150051  * __hal_channel_dtr_next_reservelist
321256Syl150051  *
331256Syl150051  * Walking through the all available DTRs.
341256Syl150051  */
351256Syl150051 static xge_hal_status_e
__hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)361256Syl150051 __hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,
371256Syl150051 		xge_hal_dtr_h *dtrh)
381256Syl150051 {
391256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
401256Syl150051 
411256Syl150051 	if (channel->reserve_top >= channel->reserve_length) {
421256Syl150051 		return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
431256Syl150051 	}
441256Syl150051 
451256Syl150051 	*dtrh = channel->reserve_arr[channel->reserve_top++];
461256Syl150051 
471256Syl150051 	return XGE_HAL_OK;
481256Syl150051 }
491256Syl150051 
501256Syl150051 /*
511256Syl150051  * __hal_channel_dtr_next_freelist
521256Syl150051  *
531256Syl150051  * Walking through the "freed" DTRs.
541256Syl150051  */
551256Syl150051 static xge_hal_status_e
__hal_channel_dtr_next_freelist(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)561256Syl150051 __hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
571256Syl150051 {
581256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
591256Syl150051 
601256Syl150051 	if (channel->reserve_initial == channel->free_length) {
611256Syl150051 		return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
621256Syl150051 	}
631256Syl150051 
641256Syl150051 	*dtrh = channel->free_arr[channel->free_length++];
651256Syl150051 
661256Syl150051 	return XGE_HAL_OK;
671256Syl150051 }
681256Syl150051 
691256Syl150051 /*
703115Syl150051  * __hal_channel_dtr_next_not_completed - Get the _next_ posted but
711256Syl150051  *                                     not completed descriptor.
721256Syl150051  *
731256Syl150051  * Walking through the "not completed" DTRs.
741256Syl150051  */
751256Syl150051 static xge_hal_status_e
__hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)761256Syl150051 __hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,
771256Syl150051 		xge_hal_dtr_h *dtrh)
781256Syl150051 {
79*6937Sxw161283 	/* LINTED E_FUNC_SET_NOT_USED */
80*6937Sxw161283 	xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */
81*6937Sxw161283 
821256Syl150051 	__hal_channel_dtr_try_complete(channelh, dtrh);
833115Syl150051 	if (*dtrh == NULL) {
841256Syl150051 		return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
851256Syl150051 	}
861256Syl150051 
87*6937Sxw161283 	rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
88*6937Sxw161283 	xge_assert(rxdp->host_control!=0);
891256Syl150051 
901256Syl150051 	__hal_channel_dtr_complete(channelh);
911256Syl150051 
921256Syl150051 	return XGE_HAL_OK;
931256Syl150051 }
941256Syl150051 
951256Syl150051 xge_hal_channel_t*
__hal_channel_allocate(xge_hal_device_h devh,int post_qid,xge_hal_channel_type_e type)961256Syl150051 __hal_channel_allocate(xge_hal_device_h devh, int post_qid,
971256Syl150051 		xge_hal_channel_type_e type)
981256Syl150051 {
991256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1001256Syl150051 	xge_hal_channel_t *channel;
1011256Syl150051 	int size = 0;
1021256Syl150051 
1033115Syl150051 	switch(type) {
1043115Syl150051 		case XGE_HAL_CHANNEL_TYPE_FIFO:
1053115Syl150051 			xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM &&
1063115Syl150051 				 post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM);
1073115Syl150051 			size = sizeof(xge_hal_fifo_t);
1083115Syl150051 			break;
1093115Syl150051 		case XGE_HAL_CHANNEL_TYPE_RING:
1103115Syl150051 			xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM &&
1113115Syl150051 				post_qid + 1 <= XGE_HAL_MAX_RING_NUM);
1123115Syl150051 			size = sizeof(xge_hal_ring_t);
1133115Syl150051 			break;
1143115Syl150051 		default :
1153115Syl150051 			xge_assert(size);
1163115Syl150051 			break;
1171256Syl150051 
1181256Syl150051 	}
1191256Syl150051 
1201256Syl150051 
1211256Syl150051 	/* allocate FIFO channel */
1223115Syl150051 	channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size);
1231256Syl150051 	if (channel == NULL) {
1241256Syl150051 		return NULL;
1251256Syl150051 	}
1261256Syl150051 	xge_os_memzero(channel, size);
1271256Syl150051 
1281256Syl150051 	channel->pdev		= hldev->pdev;
1291256Syl150051 	channel->regh0		= hldev->regh0;
1301256Syl150051 	channel->regh1		= hldev->regh1;
1311256Syl150051 	channel->type		= type;
1321256Syl150051 	channel->devh		= devh;
1331256Syl150051 	channel->post_qid	= post_qid;
1341256Syl150051 	channel->compl_qid	= 0;
1351256Syl150051 
1361256Syl150051 	return channel;
1371256Syl150051 }
1381256Syl150051 
__hal_channel_free(xge_hal_channel_t * channel)1391256Syl150051 void __hal_channel_free(xge_hal_channel_t *channel)
1401256Syl150051 {
1411256Syl150051 	int size = 0;
1421256Syl150051 
1431256Syl150051 	xge_assert(channel->pdev);
1441256Syl150051 
1453115Syl150051 	switch(channel->type) {
1463115Syl150051 		case XGE_HAL_CHANNEL_TYPE_FIFO:
1473115Syl150051 			size = sizeof(xge_hal_fifo_t);
1483115Syl150051 			break;
1493115Syl150051 		case XGE_HAL_CHANNEL_TYPE_RING:
1503115Syl150051 			size = sizeof(xge_hal_ring_t);
1513115Syl150051 			break;
1523115Syl150051 		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
153*6937Sxw161283 		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
154*6937Sxw161283 		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
1553115Syl150051 		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
1563115Syl150051 		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
1573115Syl150051 			xge_assert(size);
1583115Syl150051 			break;
1593115Syl150051 		default:
1603115Syl150051 			break;
1611256Syl150051 	}
1621256Syl150051 
1631256Syl150051 	xge_os_free(channel->pdev, channel, size);
1641256Syl150051 }
1651256Syl150051 
1661256Syl150051 xge_hal_status_e
__hal_channel_initialize(xge_hal_channel_h channelh,xge_hal_channel_attr_t * attr,void ** reserve_arr,int reserve_initial,int reserve_max,int reserve_threshold)1671256Syl150051 __hal_channel_initialize (xge_hal_channel_h channelh,
1681256Syl150051 		xge_hal_channel_attr_t *attr, void **reserve_arr,
1691256Syl150051 		int reserve_initial, int reserve_max, int reserve_threshold)
1701256Syl150051 {
1711256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
1721256Syl150051 	xge_hal_device_t *hldev;
1731256Syl150051 
1741256Syl150051 	hldev = (xge_hal_device_t *)channel->devh;
1751256Syl150051 
1761256Syl150051 	channel->dtr_term = attr->dtr_term;
1771256Syl150051 	channel->dtr_init = attr->dtr_init;
1781256Syl150051 	channel->callback = attr->callback;
1791256Syl150051 	channel->userdata = attr->userdata;
1801256Syl150051 	channel->flags = attr->flags;
1811256Syl150051 	channel->per_dtr_space = attr->per_dtr_space;
1821256Syl150051 
1831256Syl150051 	channel->reserve_arr = reserve_arr;
1841256Syl150051 	channel->reserve_initial = reserve_initial;
1851256Syl150051 	channel->reserve_max = reserve_max;
1861256Syl150051 	channel->reserve_length = channel->reserve_initial;
1871256Syl150051 	channel->reserve_threshold = reserve_threshold;
1881256Syl150051 	channel->reserve_top = 0;
1893115Syl150051 	channel->saved_arr = (void **) xge_os_malloc(hldev->pdev,
1901256Syl150051 					   sizeof(void*)*channel->reserve_max);
1911256Syl150051 	if (channel->saved_arr == NULL) {
1921256Syl150051 		return XGE_HAL_ERR_OUT_OF_MEMORY;
1931256Syl150051 	}
1941256Syl150051 	xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max);
1951256Syl150051 	channel->free_arr = channel->saved_arr;
1961256Syl150051 	channel->free_length = channel->reserve_initial;
1973115Syl150051 	channel->work_arr = (void **) xge_os_malloc(hldev->pdev,
1981256Syl150051 				  sizeof(void*)*channel->reserve_max);
1991256Syl150051 	if (channel->work_arr == NULL) {
2001256Syl150051 		return XGE_HAL_ERR_OUT_OF_MEMORY;
2011256Syl150051 	}
2021256Syl150051 	xge_os_memzero(channel->work_arr,
2031256Syl150051                        sizeof(void*)*channel->reserve_max);
2041256Syl150051 	channel->post_index = 0;
2051256Syl150051 	channel->compl_index = 0;
2061256Syl150051 	channel->length = channel->reserve_initial;
2071256Syl150051 
2083115Syl150051 	channel->orig_arr = (void **) xge_os_malloc(hldev->pdev,
2093115Syl150051 						sizeof(void*)*channel->reserve_max);
2101256Syl150051 	if (channel->orig_arr == NULL)
2111256Syl150051 		return XGE_HAL_ERR_OUT_OF_MEMORY;
2121256Syl150051 
2131256Syl150051 	xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max);
2141256Syl150051 
2151256Syl150051 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
2161256Syl150051 	xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh);
2173115Syl150051 #elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
2181256Syl150051 	xge_os_spin_lock_init(&channel->free_lock, hldev->pdev);
2191256Syl150051 #endif
2201256Syl150051 
2211256Syl150051 	return XGE_HAL_OK;
2221256Syl150051 }
2231256Syl150051 
__hal_channel_terminate(xge_hal_channel_h channelh)2241256Syl150051 void __hal_channel_terminate(xge_hal_channel_h channelh)
2251256Syl150051 {
2261256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
2271256Syl150051 	xge_hal_device_t *hldev;
2281256Syl150051 
2291256Syl150051 	hldev = (xge_hal_device_t *)channel->devh;
2301256Syl150051 
2311256Syl150051 	xge_assert(channel->pdev);
2321256Syl150051 	/* undo changes made at channel_initialize() */
2331256Syl150051 	if (channel->work_arr) {
2341256Syl150051 		xge_os_free(channel->pdev, channel->work_arr,
2351256Syl150051 		          sizeof(void*)*channel->reserve_max);
2361256Syl150051 		channel->work_arr = NULL;
2371256Syl150051 	}
2381256Syl150051 
2391256Syl150051 	if (channel->saved_arr) {
2401256Syl150051 		xge_os_free(channel->pdev, channel->saved_arr,
2411256Syl150051 		          sizeof(void*)*channel->reserve_max);
2421256Syl150051 		channel->saved_arr = NULL;
2431256Syl150051 	}
2441256Syl150051 
2451256Syl150051 	if (channel->orig_arr) {
2461256Syl150051 		xge_os_free(channel->pdev, channel->orig_arr,
2471256Syl150051 		          sizeof(void*)*channel->reserve_max);
2481256Syl150051 		channel->orig_arr = NULL;
2491256Syl150051 	}
2501256Syl150051 
2511256Syl150051 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
2521256Syl150051 	xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh);
2533115Syl150051 #elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
2541256Syl150051 	xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev);
2551256Syl150051 #endif
2561256Syl150051 }
2571256Syl150051 
2581256Syl150051 /**
2591256Syl150051  * xge_hal_channel_open - Open communication channel.
2601256Syl150051  * @devh: HAL device, pointer to xge_hal_device_t structure.
2611256Syl150051  * @attr: Contains attributes required to open
2621256Syl150051  *        the channel.
2631256Syl150051  * @channelh:  The channel handle. On success (XGE_HAL_OK) HAL fills
2641256Syl150051  * this "out" parameter with a valid channel handle.
2651256Syl150051  * @reopen: See  xge_hal_channel_reopen_e{}.
2661256Syl150051  *
2671256Syl150051  * Open communication channel with the device.
2681256Syl150051  *
2691256Syl150051  * HAL uses (persistent) channel configuration to allocate both channel
2701256Syl150051  * and Xframe Tx and Rx descriptors.
2711256Syl150051  * Notes:
2721256Syl150051  *     1) The channel config data is fed into HAL prior to
2731256Syl150051  *        xge_hal_channel_open().
2741256Syl150051  *
2751256Syl150051  *     2) The corresponding hardware queues must be already configured and
2761256Syl150051  *        enabled.
2771256Syl150051  *
2781256Syl150051  *     3) Either down or up queue may be omitted, in which case the channel
2791256Syl150051  *        is treated as _unidirectional_.
2801256Syl150051  *
2811256Syl150051  *     4) Post and completion queue may be the same, in which case the channel
2821256Syl150051  *        is said to have "in-band completions".
2831256Syl150051  *
2841256Syl150051  * Note that free_channels list is not protected. i.e. caller must provide
2851256Syl150051  * safe context.
2861256Syl150051  *
2871256Syl150051  * Returns: XGE_HAL_OK  - success.
2881256Syl150051  * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel.
2891256Syl150051  * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed.
2901256Syl150051  *
2911256Syl150051  * See also: xge_hal_channel_attr_t{}.
2921256Syl150051  * Usage: See ex_open{}.
2931256Syl150051  */
2941256Syl150051 xge_hal_status_e
xge_hal_channel_open(xge_hal_device_h devh,xge_hal_channel_attr_t * attr,xge_hal_channel_h * channelh,xge_hal_channel_reopen_e reopen)2951256Syl150051 xge_hal_channel_open(xge_hal_device_h devh,
2961256Syl150051 		     xge_hal_channel_attr_t *attr,
2971256Syl150051 		     xge_hal_channel_h *channelh,
2981256Syl150051 		     xge_hal_channel_reopen_e reopen)
2991256Syl150051 {
3001256Syl150051 	xge_list_t *item;
3011256Syl150051 	int i;
3021256Syl150051 	xge_hal_status_e status = XGE_HAL_OK;
3031256Syl150051 	xge_hal_channel_t *channel = NULL;
3041256Syl150051 	xge_hal_device_t *device = (xge_hal_device_t *)devh;
3051256Syl150051 
3061256Syl150051 	xge_assert(device);
3071256Syl150051 	xge_assert(attr);
3081256Syl150051 
3091256Syl150051 	*channelh = NULL;
3101256Syl150051 
3111256Syl150051 	/* find channel */
3123115Syl150051 		xge_list_for_each(item, &device->free_channels) {
3133115Syl150051 			xge_hal_channel_t *tmp;
3141256Syl150051 
3153115Syl150051 			tmp = xge_container_of(item, xge_hal_channel_t, item);
3163115Syl150051 			if (tmp->type == attr->type &&
3173115Syl150051 			tmp->post_qid == attr->post_qid &&
3183115Syl150051 			tmp->compl_qid == attr->compl_qid) {
3193115Syl150051 				channel = tmp;
3203115Syl150051 				break;
3213115Syl150051 			}
3223115Syl150051 		}
3233115Syl150051 
3243115Syl150051 		if (channel == NULL) {
3253115Syl150051 			return XGE_HAL_ERR_CHANNEL_NOT_FOUND;
3263115Syl150051 		}
3273115Syl150051 
3281256Syl150051 	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
3291256Syl150051 		(channel->type == XGE_HAL_CHANNEL_TYPE_RING));
3301256Syl150051 
3311256Syl150051 	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
3321256Syl150051 		/* allocate memory, initialize pointers, etc */
3333115Syl150051 		switch(channel->type) {
3343115Syl150051 			case XGE_HAL_CHANNEL_TYPE_FIFO:
3353115Syl150051 				status = __hal_fifo_open(channel, attr);
3363115Syl150051 				break;
3373115Syl150051 			case XGE_HAL_CHANNEL_TYPE_RING:
3383115Syl150051 				status = __hal_ring_open(channel, attr);
3393115Syl150051 				break;
3403115Syl150051 			case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
341*6937Sxw161283 			case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
342*6937Sxw161283 			case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
3433115Syl150051 			case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
3443115Syl150051 			case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
3453115Syl150051 				status = XGE_HAL_FAIL;
3463115Syl150051 				break;
3473115Syl150051 			default:
3483115Syl150051 				break;
3493115Syl150051 		}
3501256Syl150051 
3511256Syl150051 		if (status == XGE_HAL_OK) {
3521256Syl150051 			for (i = 0; i < channel->reserve_initial; i++) {
3531256Syl150051 				channel->orig_arr[i] =
3541256Syl150051 					channel->reserve_arr[i];
3551256Syl150051 			}
3561256Syl150051 		}
3571256Syl150051 		else
3581256Syl150051 			return status;
3591256Syl150051 	} else {
3601256Syl150051 	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
3611256Syl150051 
3621256Syl150051 		for (i = 0; i < channel->reserve_initial; i++) {
3631256Syl150051 			channel->reserve_arr[i] = channel->orig_arr[i];
3641256Syl150051 			channel->free_arr[i] = NULL;
3651256Syl150051 		}
3661256Syl150051 		channel->free_length = channel->reserve_initial;
3671256Syl150051 		channel->reserve_length = channel->reserve_initial;
3681256Syl150051 		channel->reserve_top = 0;
3691256Syl150051 		channel->post_index = 0;
3701256Syl150051 		channel->compl_index = 0;
3711256Syl150051                 if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
3721256Syl150051 			status = __hal_ring_initial_replenish(channel,
3731256Syl150051 							      reopen);
3741256Syl150051                         if (status != XGE_HAL_OK)
3751256Syl150051                                 return status;
3761256Syl150051 		}
3771256Syl150051 	}
3781256Syl150051 
3791256Syl150051 	/* move channel to the open state list */
3803115Syl150051 
3813115Syl150051 	switch(channel->type) {
3823115Syl150051 		case XGE_HAL_CHANNEL_TYPE_FIFO:
3833115Syl150051 			xge_list_remove(&channel->item);
3843115Syl150051 			xge_list_insert(&channel->item, &device->fifo_channels);
3853115Syl150051 			break;
3863115Syl150051 		case XGE_HAL_CHANNEL_TYPE_RING:
3873115Syl150051 			xge_list_remove(&channel->item);
3883115Syl150051 			xge_list_insert(&channel->item, &device->ring_channels);
3893115Syl150051 			break;
3903115Syl150051 		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
391*6937Sxw161283 		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
392*6937Sxw161283 		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
3933115Syl150051 		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
3943115Syl150051 		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
3953115Syl150051 			xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
3963115Syl150051 				   channel->type == XGE_HAL_CHANNEL_TYPE_RING);
3973115Syl150051 			break;
3983115Syl150051 		default:
3993115Syl150051 			break;
4001256Syl150051 	}
4011256Syl150051 	channel->is_open = 1;
402*6937Sxw161283 	channel->terminating = 0;
4031256Syl150051 	/*
4041256Syl150051 	 * The magic check the argument validity, has to be
4051256Syl150051 	 * removed before 03/01/2005.
4061256Syl150051 	 */
4071256Syl150051 	channel->magic = XGE_HAL_MAGIC;
4081256Syl150051 
4091256Syl150051 	*channelh = channel;
4101256Syl150051 
4111256Syl150051 	return XGE_HAL_OK;
4121256Syl150051 }
4131256Syl150051 
4141256Syl150051 /**
4151256Syl150051  * xge_hal_channel_abort - Abort the channel.
4161256Syl150051  * @channelh: Channel handle.
4171256Syl150051  * @reopen: See  xge_hal_channel_reopen_e{}.
4181256Syl150051  *
4191256Syl150051  * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors.
4201256Syl150051  * Currently used internally only by HAL, as part of its
4211256Syl150051  * xge_hal_channel_close() and xge_hal_channel_open() in case
4221256Syl150051  * of fatal error.
4231256Syl150051  *
4241256Syl150051  * See also: xge_hal_channel_dtr_term_f{}.
4251256Syl150051  */
xge_hal_channel_abort(xge_hal_channel_h channelh,xge_hal_channel_reopen_e reopen)4261256Syl150051 void xge_hal_channel_abort(xge_hal_channel_h channelh,
4271256Syl150051                            xge_hal_channel_reopen_e reopen)
4281256Syl150051 {
4291256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
4301256Syl150051 	xge_hal_dtr_h dtr;
4311256Syl150051 #ifdef XGE_OS_MEMORY_CHECK
4321256Syl150051 	int check_cnt = 0;
4331256Syl150051 #endif
4341256Syl150051 	int free_length_sav;
4351256Syl150051 	int reserve_top_sav;
4361256Syl150051 
4371256Syl150051 	if (channel->dtr_term == NULL) {
4381256Syl150051 		return;
4391256Syl150051 	}
4401256Syl150051 
4411256Syl150051 	free_length_sav = channel->free_length;
4421256Syl150051 	while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) {
4431256Syl150051 #ifdef XGE_OS_MEMORY_CHECK
4441256Syl150051 #ifdef XGE_DEBUG_ASSERT
4451256Syl150051 		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
4461256Syl150051 		    xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
4471256Syl150051 		} else {
4483115Syl150051 		    if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
449*6937Sxw161283 			    xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
4503115Syl150051 		    }
4511256Syl150051 		}
4521256Syl150051 #endif
4531256Syl150051 		check_cnt++;
4541256Syl150051 #endif
4551256Syl150051 		channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED,
4561256Syl150051 				  channel->userdata, reopen);
4571256Syl150051 	}
4581256Syl150051 	channel->free_length = free_length_sav;
4591256Syl150051 
4601256Syl150051 	while (__hal_channel_dtr_next_not_completed(channelh, &dtr) ==
4611256Syl150051 	       XGE_HAL_OK) {
4621256Syl150051 #ifdef XGE_OS_MEMORY_CHECK
4631256Syl150051 #ifdef XGE_DEBUG_ASSERT
4641256Syl150051 		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
4651256Syl150051 			xge_assert(__hal_fifo_txdl_priv(dtr)->allocated);
4661256Syl150051 		} else {
4673115Syl150051 		    if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
468*6937Sxw161283 			xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)
4691256Syl150051 				   ->allocated);
4703115Syl150051 		    }
4711256Syl150051 		}
4721256Syl150051 #endif
4731256Syl150051 		check_cnt++;
4741256Syl150051 #endif
4751256Syl150051 		channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED,
4761256Syl150051 				  channel->userdata, reopen);
4773115Syl150051 
4781256Syl150051 	}
4791256Syl150051 
4801256Syl150051 	reserve_top_sav = channel->reserve_top;
4811256Syl150051 	while (__hal_channel_dtr_next_reservelist(channelh, &dtr) ==
4821256Syl150051 							XGE_HAL_OK) {
4831256Syl150051 #ifdef XGE_OS_MEMORY_CHECK
4841256Syl150051 #ifdef XGE_DEBUG_ASSERT
4851256Syl150051 		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
4861256Syl150051 		    xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
4871256Syl150051 		} else {
4883115Syl150051 		    if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
489*6937Sxw161283 			xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
4903115Syl150051 		    }
4911256Syl150051 		}
4921256Syl150051 #endif
4931256Syl150051 		check_cnt++;
4941256Syl150051 #endif
4951256Syl150051 		channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL,
4961256Syl150051 				  channel->userdata, reopen);
4971256Syl150051 	}
4981256Syl150051 	channel->reserve_top = reserve_top_sav;
4991256Syl150051 
5001256Syl150051 	xge_assert(channel->reserve_length ==
5011256Syl150051                 (channel->free_length + channel->reserve_top));
5021256Syl150051 
5031256Syl150051 #ifdef XGE_OS_MEMORY_CHECK
5041256Syl150051 	xge_assert(check_cnt == channel->reserve_initial);
5051256Syl150051 #endif
5061256Syl150051 
5071256Syl150051 }
5081256Syl150051 
5091256Syl150051 /**
5101256Syl150051  * xge_hal_channel_close - Close communication channel.
5111256Syl150051  * @channelh: The channel handle.
5121256Syl150051  * @reopen: See  xge_hal_channel_reopen_e{}.
5131256Syl150051  *
5141256Syl150051  * Will close previously opened channel and deallocate associated resources.
5151256Syl150051  * Channel must be opened otherwise assert will be generated.
5161256Syl150051  * Note that free_channels list is not protected. i.e. caller must provide
5171256Syl150051  * safe context.
5181256Syl150051  */
xge_hal_channel_close(xge_hal_channel_h channelh,xge_hal_channel_reopen_e reopen)5191256Syl150051 void xge_hal_channel_close(xge_hal_channel_h channelh,
5201256Syl150051                            xge_hal_channel_reopen_e reopen)
5211256Syl150051 {
5221256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
5231256Syl150051 	xge_hal_device_t *hldev;
5241256Syl150051 	xge_list_t *item;
5251256Syl150051 	xge_assert(channel);
5261256Syl150051 	xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX);
5271256Syl150051 
5281256Syl150051 	hldev = (xge_hal_device_t *)channel->devh;
5291256Syl150051 	channel->is_open = 0;
5301256Syl150051 	channel->magic = XGE_HAL_DEAD;
5311256Syl150051 
5323115Syl150051 		/* sanity check: make sure channel is not in free list */
5333115Syl150051 		xge_list_for_each(item, &hldev->free_channels) {
5343115Syl150051 			xge_hal_channel_t *tmp;
5351256Syl150051 
5363115Syl150051 			tmp = xge_container_of(item, xge_hal_channel_t, item);
5373115Syl150051 			xge_assert(!tmp->is_open);
5383115Syl150051 			if (channel == tmp) {
5393115Syl150051 				return;
5403115Syl150051 			}
5411256Syl150051 		}
5421256Syl150051 
5431256Syl150051 	xge_hal_channel_abort(channel, reopen);
5441256Syl150051 
5451256Syl150051 	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
5461256Syl150051 		   (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
5471256Syl150051 
5481256Syl150051 	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
5491256Syl150051 		/* de-allocate */
5503115Syl150051 		switch(channel->type) {
5513115Syl150051 			case XGE_HAL_CHANNEL_TYPE_FIFO:
5523115Syl150051 				__hal_fifo_close(channelh);
5533115Syl150051 				break;
5543115Syl150051 			case XGE_HAL_CHANNEL_TYPE_RING:
5553115Syl150051 				__hal_ring_close(channelh);
5563115Syl150051 				break;
5573115Syl150051 			case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
558*6937Sxw161283 			case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
559*6937Sxw161283 			case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
5603115Syl150051 			case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
5613115Syl150051 			case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
5623115Syl150051 				xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
563*6937Sxw161283 				    channel->type == XGE_HAL_CHANNEL_TYPE_RING);
5643115Syl150051 				break;
5653115Syl150051 			default:
5663115Syl150051 				break;
5671256Syl150051 		}
5681256Syl150051 	}
5691256Syl150051 
5701256Syl150051 	/* move channel back to free state list */
5711256Syl150051 	xge_list_remove(&channel->item);
5723115Syl150051 		xge_list_insert(&channel->item, &hldev->free_channels);
5731256Syl150051 
5743115Syl150051 		if (xge_list_is_empty(&hldev->fifo_channels) &&
5753115Syl150051 			xge_list_is_empty(&hldev->ring_channels)) {
5763115Syl150051 			/* clear msix_idx in case of following HW reset */
5773115Syl150051 			hldev->reset_needed_after_close = 1;
5783115Syl150051 		}
5791256Syl150051 }
580