xgehal-channel.c revision 171095
1/*-
2 * Copyright (c) 2002-2007 Neterion, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/nxge/xgehal/xgehal-channel.c 171095 2007-06-29 22:47:18Z sam $
27 */
28
29/*
30 *  FileName :    xgehal-channel.c
31 *
32 *  Description:  chipset channel abstraction
33 *
34 *  Created:      10 May 2004
35 */
36
37#include <dev/nxge/include/xgehal-channel.h>
38#include <dev/nxge/include/xgehal-fifo.h>
39#include <dev/nxge/include/xgehal-ring.h>
40#include <dev/nxge/include/xgehal-device.h>
41#include <dev/nxge/include/xgehal-regs.h>
42#ifdef XGEHAL_RNIC
43#include <dev/nxge/include/xgehal-types.h>
44#include "xgehal-iov.h"
45#endif
46
47/*
48 * __hal_channel_dtr_next_reservelist
49 *
50 * Walking through the all available DTRs.
51 */
52static xge_hal_status_e
53__hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,
54		xge_hal_dtr_h *dtrh)
55{
56	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
57
58	if (channel->reserve_top >= channel->reserve_length) {
59		return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
60	}
61
62	*dtrh = channel->reserve_arr[channel->reserve_top++];
63
64	return XGE_HAL_OK;
65}
66
67/*
68 * __hal_channel_dtr_next_freelist
69 *
70 * Walking through the "freed" DTRs.
71 */
72static xge_hal_status_e
73__hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
74{
75	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
76
77	if (channel->reserve_initial == channel->free_length) {
78		return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
79	}
80
81	*dtrh = channel->free_arr[channel->free_length++];
82
83	return XGE_HAL_OK;
84}
85
86/*
87 * __hal_channel_dtr_next_not_completed - Get the _next_ posted but
88 *                                     not completed descriptor.
89 *
90 * Walking through the "not completed" DTRs.
91 */
92static xge_hal_status_e
93__hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,
94		xge_hal_dtr_h *dtrh)
95{
96#ifndef XGEHAL_RNIC
97	xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */
98#endif
99
100	__hal_channel_dtr_try_complete(channelh, dtrh);
101	if (*dtrh == NULL) {
102		return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
103	}
104
105#ifndef XGEHAL_RNIC
106	rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
107	xge_assert(rxdp->host_control!=0);
108#endif
109
110	__hal_channel_dtr_complete(channelh);
111
112	return XGE_HAL_OK;
113}
114
115xge_hal_channel_t*
116__hal_channel_allocate(xge_hal_device_h devh, int post_qid,
117#ifdef XGEHAL_RNIC
118		u32 vp_id,
119#endif
120		xge_hal_channel_type_e type)
121{
122	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
123	xge_hal_channel_t *channel;
124	int size = 0;
125
126	switch(type) {
127		case XGE_HAL_CHANNEL_TYPE_FIFO:
128			xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM &&
129				 post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM);
130			size = sizeof(xge_hal_fifo_t);
131			break;
132		case XGE_HAL_CHANNEL_TYPE_RING:
133			xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM &&
134				post_qid + 1 <= XGE_HAL_MAX_RING_NUM);
135			size = sizeof(xge_hal_ring_t);
136			break;
137#ifdef XGEHAL_RNIC
138		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
139			size = sizeof(__hal_sq_t);
140			break;
141		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
142			size = sizeof(__hal_srq_t);
143			break;
144		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
145			size = sizeof(__hal_cqrq_t);
146			break;
147		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
148			size = sizeof(__hal_umq_t);
149			break;
150		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
151			size = sizeof(__hal_dmq_t);
152			break;
153#endif
154		default :
155			xge_assert(size);
156			break;
157
158	}
159
160
161	/* allocate FIFO channel */
162	channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size);
163	if (channel == NULL) {
164		return NULL;
165	}
166	xge_os_memzero(channel, size);
167
168	channel->pdev		= hldev->pdev;
169	channel->regh0		= hldev->regh0;
170	channel->regh1		= hldev->regh1;
171	channel->type		= type;
172	channel->devh		= devh;
173#ifdef XGEHAL_RNIC
174	channel->vp_id		= vp_id;
175#endif
176	channel->post_qid	= post_qid;
177	channel->compl_qid	= 0;
178
179	return channel;
180}
181
182void __hal_channel_free(xge_hal_channel_t *channel)
183{
184	int size = 0;
185
186	xge_assert(channel->pdev);
187
188	switch(channel->type) {
189		case XGE_HAL_CHANNEL_TYPE_FIFO:
190			size = sizeof(xge_hal_fifo_t);
191			break;
192		case XGE_HAL_CHANNEL_TYPE_RING:
193			size = sizeof(xge_hal_ring_t);
194			break;
195#ifdef XGEHAL_RNIC
196		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
197			size = sizeof(__hal_sq_t);
198			break;
199		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
200			size = sizeof(__hal_srq_t);
201			break;
202		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
203			size = sizeof(__hal_cqrq_t);
204			break;
205		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
206			size = sizeof(__hal_umq_t);
207			break;
208		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
209			size = sizeof(__hal_dmq_t);
210			break;
211#else
212		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
213		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
214		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
215		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
216		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
217			xge_assert(size);
218			break;
219#endif
220		default:
221			break;
222	}
223
224	xge_os_free(channel->pdev, channel, size);
225}
226
227xge_hal_status_e
228__hal_channel_initialize (xge_hal_channel_h channelh,
229		xge_hal_channel_attr_t *attr, void **reserve_arr,
230		int reserve_initial, int reserve_max, int reserve_threshold)
231{
232	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
233	xge_hal_device_t *hldev;
234
235	hldev = (xge_hal_device_t *)channel->devh;
236
237	channel->dtr_term = attr->dtr_term;
238	channel->dtr_init = attr->dtr_init;
239	channel->callback = attr->callback;
240	channel->userdata = attr->userdata;
241	channel->flags = attr->flags;
242	channel->per_dtr_space = attr->per_dtr_space;
243
244	channel->reserve_arr = reserve_arr;
245	channel->reserve_initial = reserve_initial;
246	channel->reserve_max = reserve_max;
247	channel->reserve_length = channel->reserve_initial;
248	channel->reserve_threshold = reserve_threshold;
249	channel->reserve_top = 0;
250	channel->saved_arr = (void **) xge_os_malloc(hldev->pdev,
251					   sizeof(void*)*channel->reserve_max);
252	if (channel->saved_arr == NULL) {
253		return XGE_HAL_ERR_OUT_OF_MEMORY;
254	}
255	xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max);
256	channel->free_arr = channel->saved_arr;
257	channel->free_length = channel->reserve_initial;
258	channel->work_arr = (void **) xge_os_malloc(hldev->pdev,
259				  sizeof(void*)*channel->reserve_max);
260	if (channel->work_arr == NULL) {
261		return XGE_HAL_ERR_OUT_OF_MEMORY;
262	}
263	xge_os_memzero(channel->work_arr,
264                       sizeof(void*)*channel->reserve_max);
265	channel->post_index = 0;
266	channel->compl_index = 0;
267	channel->length = channel->reserve_initial;
268
269	channel->orig_arr = (void **) xge_os_malloc(hldev->pdev,
270						sizeof(void*)*channel->reserve_max);
271	if (channel->orig_arr == NULL)
272		return XGE_HAL_ERR_OUT_OF_MEMORY;
273
274	xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max);
275
276#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
277	xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh);
278#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
279	xge_os_spin_lock_init(&channel->free_lock, hldev->pdev);
280#endif
281
282	return XGE_HAL_OK;
283}
284
285void __hal_channel_terminate(xge_hal_channel_h channelh)
286{
287	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
288	xge_hal_device_t *hldev;
289
290	hldev = (xge_hal_device_t *)channel->devh;
291
292	xge_assert(channel->pdev);
293	/* undo changes made at channel_initialize() */
294	if (channel->work_arr) {
295		xge_os_free(channel->pdev, channel->work_arr,
296		          sizeof(void*)*channel->reserve_max);
297		channel->work_arr = NULL;
298	}
299
300	if (channel->saved_arr) {
301		xge_os_free(channel->pdev, channel->saved_arr,
302		          sizeof(void*)*channel->reserve_max);
303		channel->saved_arr = NULL;
304	}
305
306	if (channel->orig_arr) {
307		xge_os_free(channel->pdev, channel->orig_arr,
308		          sizeof(void*)*channel->reserve_max);
309		channel->orig_arr = NULL;
310	}
311
312#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
313	xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh);
314#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
315	xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev);
316#endif
317}
318
319/**
320 * xge_hal_channel_open - Open communication channel.
321 * @devh: HAL device, pointer to xge_hal_device_t structure.
322 * @attr: Contains attributes required to open
323 *        the channel.
324 * @channelh:  The channel handle. On success (XGE_HAL_OK) HAL fills
325 * this "out" parameter with a valid channel handle.
326 * @reopen: See  xge_hal_channel_reopen_e{}.
327 *
328 * Open communication channel with the device.
329 *
330 * HAL uses (persistent) channel configuration to allocate both channel
331 * and Xframe Tx and Rx descriptors.
332 * Notes:
333 *     1) The channel config data is fed into HAL prior to
334 *        xge_hal_channel_open().
335 *
336 *     2) The corresponding hardware queues must be already configured and
337 *        enabled.
338 *
339 *     3) Either down or up queue may be omitted, in which case the channel
340 *        is treated as _unidirectional_.
341 *
342 *     4) Post and completion queue may be the same, in which case the channel
343 *        is said to have "in-band completions".
344 *
345 * Note that free_channels list is not protected. i.e. caller must provide
346 * safe context.
347 *
348 * Returns: XGE_HAL_OK  - success.
349 * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel.
350 * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed.
351 *
352 * See also: xge_hal_channel_attr_t{}.
353 * Usage: See ex_open{}.
354 */
355xge_hal_status_e
356xge_hal_channel_open(xge_hal_device_h devh,
357		     xge_hal_channel_attr_t *attr,
358		     xge_hal_channel_h *channelh,
359		     xge_hal_channel_reopen_e reopen)
360{
361	xge_list_t *item;
362	int i;
363	xge_hal_status_e status = XGE_HAL_OK;
364	xge_hal_channel_t *channel = NULL;
365	xge_hal_device_t *device = (xge_hal_device_t *)devh;
366
367	xge_assert(device);
368	xge_assert(attr);
369
370	*channelh = NULL;
371
372#ifdef XGEHAL_RNIC
373	if((attr->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
374		(attr->type == XGE_HAL_CHANNEL_TYPE_RING)) {
375#endif
376	/* find channel */
377		xge_list_for_each(item, &device->free_channels) {
378			xge_hal_channel_t *tmp;
379
380			tmp = xge_container_of(item, xge_hal_channel_t, item);
381			if (tmp->type == attr->type &&
382			tmp->post_qid == attr->post_qid &&
383			tmp->compl_qid == attr->compl_qid) {
384				channel = tmp;
385				break;
386			}
387		}
388
389		if (channel == NULL) {
390			return XGE_HAL_ERR_CHANNEL_NOT_FOUND;
391		}
392
393#ifdef XGEHAL_RNIC
394	}
395	else {
396		channel = __hal_channel_allocate(devh, attr->post_qid,
397#ifdef XGEHAL_RNIC
398			attr->vp_id,
399#endif
400			attr->type);
401		if (channel == NULL) {
402			xge_debug_device(XGE_ERR,
403					"__hal_channel_allocate failed");
404			return XGE_HAL_ERR_OUT_OF_MEMORY;
405		}
406	}
407#endif
408
409#ifndef XGEHAL_RNIC
410	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
411		(channel->type == XGE_HAL_CHANNEL_TYPE_RING));
412#endif
413
414#ifdef XGEHAL_RNIC
415	if((reopen == XGE_HAL_CHANNEL_OC_NORMAL) ||
416		((channel->type != XGE_HAL_CHANNEL_TYPE_FIFO) &&
417		 (channel->type != XGE_HAL_CHANNEL_TYPE_RING))) {
418#else
419	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
420#endif
421		/* allocate memory, initialize pointers, etc */
422		switch(channel->type) {
423			case XGE_HAL_CHANNEL_TYPE_FIFO:
424				status = __hal_fifo_open(channel, attr);
425				break;
426			case XGE_HAL_CHANNEL_TYPE_RING:
427				status = __hal_ring_open(channel, attr);
428				break;
429#ifdef XGEHAL_RNIC
430			case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
431				status = __hal_sq_open(channel, attr);
432				break;
433			case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
434				status = __hal_srq_open(channel, attr);
435				break;
436			case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
437				status = __hal_cqrq_open(channel, attr);
438				break;
439			case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
440				status = __hal_umq_open(channel, attr);
441				break;
442			case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
443				status = __hal_dmq_open(channel, attr);
444				break;
445#else
446			case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
447			case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
448			case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
449			case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
450			case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
451				status = XGE_HAL_FAIL;
452				break;
453#endif
454			default:
455				break;
456		}
457
458		if (status == XGE_HAL_OK) {
459			for (i = 0; i < channel->reserve_initial; i++) {
460				channel->orig_arr[i] =
461					channel->reserve_arr[i];
462			}
463		}
464		else
465			return status;
466	} else {
467	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
468
469		for (i = 0; i < channel->reserve_initial; i++) {
470			channel->reserve_arr[i] = channel->orig_arr[i];
471			channel->free_arr[i] = NULL;
472		}
473		channel->free_length = channel->reserve_initial;
474		channel->reserve_length = channel->reserve_initial;
475		channel->reserve_top = 0;
476		channel->post_index = 0;
477		channel->compl_index = 0;
478                if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
479			status = __hal_ring_initial_replenish(channel,
480							      reopen);
481                        if (status != XGE_HAL_OK)
482                                return status;
483		}
484	}
485
486	/* move channel to the open state list */
487
488	switch(channel->type) {
489		case XGE_HAL_CHANNEL_TYPE_FIFO:
490			xge_list_remove(&channel->item);
491			xge_list_insert(&channel->item, &device->fifo_channels);
492			break;
493		case XGE_HAL_CHANNEL_TYPE_RING:
494			xge_list_remove(&channel->item);
495			xge_list_insert(&channel->item, &device->ring_channels);
496			break;
497#ifdef XGEHAL_RNIC
498		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
499			xge_list_insert(&channel->item,
500				&device->virtual_paths[attr->vp_id].sq_channels);
501			device->virtual_paths[attr->vp_id].stats.no_sqs++;
502			break;
503		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
504			xge_list_insert(&channel->item,
505				&device->virtual_paths[attr->vp_id].srq_channels);
506			device->virtual_paths[attr->vp_id].stats.no_srqs++;
507			break;
508		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
509			xge_list_insert(&channel->item,
510				&device->virtual_paths[attr->vp_id].cqrq_channels);
511			device->virtual_paths[attr->vp_id].stats.no_cqrqs++;
512			break;
513		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
514			xge_list_init(&channel->item);
515			device->virtual_paths[attr->vp_id].umq_channelh = channel;
516			break;
517		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
518			xge_list_init(&channel->item);
519			device->virtual_paths[attr->vp_id].dmq_channelh = channel;
520			break;
521#else
522		case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
523		case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
524		case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
525		case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
526		case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
527			xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
528				   channel->type == XGE_HAL_CHANNEL_TYPE_RING);
529			break;
530#endif
531		default:
532			break;
533	}
534	channel->is_open = 1;
535	/*
536	 * The magic check the argument validity, has to be
537	 * removed before 03/01/2005.
538	 */
539	channel->magic = XGE_HAL_MAGIC;
540
541	*channelh = channel;
542
543	return XGE_HAL_OK;
544}
545
546/**
547 * xge_hal_channel_abort - Abort the channel.
548 * @channelh: Channel handle.
549 * @reopen: See  xge_hal_channel_reopen_e{}.
550 *
551 * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors.
552 * Currently used internally only by HAL, as part of its
553 * xge_hal_channel_close() and xge_hal_channel_open() in case
554 * of fatal error.
555 *
556 * See also: xge_hal_channel_dtr_term_f{}.
557 */
558void xge_hal_channel_abort(xge_hal_channel_h channelh,
559                           xge_hal_channel_reopen_e reopen)
560{
561	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
562	xge_hal_dtr_h dtr;
563#ifdef XGE_OS_MEMORY_CHECK
564	int check_cnt = 0;
565#endif
566	int free_length_sav;
567	int reserve_top_sav;
568
569	if (channel->dtr_term == NULL) {
570		return;
571	}
572
573	free_length_sav = channel->free_length;
574	while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) {
575#ifdef XGE_OS_MEMORY_CHECK
576#ifdef XGE_DEBUG_ASSERT
577		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
578		    xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
579		} else {
580		    if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
581			    xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
582		    }
583		}
584#endif
585		check_cnt++;
586#endif
587		channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED,
588				  channel->userdata, reopen);
589	}
590	channel->free_length = free_length_sav;
591
592	while (__hal_channel_dtr_next_not_completed(channelh, &dtr) ==
593	       XGE_HAL_OK) {
594#ifdef XGE_OS_MEMORY_CHECK
595#ifdef XGE_DEBUG_ASSERT
596		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
597			xge_assert(__hal_fifo_txdl_priv(dtr)->allocated);
598		} else {
599		    if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
600			xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)
601				   ->allocated);
602		    }
603		}
604#endif
605		check_cnt++;
606#endif
607		channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED,
608				  channel->userdata, reopen);
609
610	}
611
612	reserve_top_sav = channel->reserve_top;
613	while (__hal_channel_dtr_next_reservelist(channelh, &dtr) ==
614							XGE_HAL_OK) {
615#ifdef XGE_OS_MEMORY_CHECK
616#ifdef XGE_DEBUG_ASSERT
617		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
618		    xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
619		} else {
620		    if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
621			xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
622		    }
623		}
624#endif
625		check_cnt++;
626#endif
627		channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL,
628				  channel->userdata, reopen);
629	}
630	channel->reserve_top = reserve_top_sav;
631
632	xge_assert(channel->reserve_length ==
633                (channel->free_length + channel->reserve_top));
634
635#ifdef XGE_OS_MEMORY_CHECK
636	xge_assert(check_cnt == channel->reserve_initial);
637#endif
638
639}
640
641/**
642 * xge_hal_channel_close - Close communication channel.
643 * @channelh: The channel handle.
644 * @reopen: See  xge_hal_channel_reopen_e{}.
645 *
646 * Will close previously opened channel and deallocate associated resources.
647 * Channel must be opened otherwise assert will be generated.
648 * Note that free_channels list is not protected. i.e. caller must provide
649 * safe context.
650 */
651void xge_hal_channel_close(xge_hal_channel_h channelh,
652                           xge_hal_channel_reopen_e reopen)
653{
654	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
655	xge_hal_device_t *hldev;
656	xge_list_t *item;
657#ifdef XGEHAL_RNIC
658	u32 vp_id;
659#endif
660	xge_assert(channel);
661	xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX);
662
663	hldev = (xge_hal_device_t *)channel->devh;
664	channel->is_open = 0;
665	channel->magic = XGE_HAL_DEAD;
666
667#ifdef XGEHAL_RNIC
668	vp_id = channel->vp_id;
669
670	if((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
671		(channel->type == XGE_HAL_CHANNEL_TYPE_RING)) {
672#endif
673		/* sanity check: make sure channel is not in free list */
674		xge_list_for_each(item, &hldev->free_channels) {
675			xge_hal_channel_t *tmp;
676
677			tmp = xge_container_of(item, xge_hal_channel_t, item);
678			xge_assert(!tmp->is_open);
679			if (channel == tmp) {
680				return;
681			}
682		}
683#ifdef XGEHAL_RNIC
684	}
685#endif
686
687	xge_hal_channel_abort(channel, reopen);
688
689#ifndef XGEHAL_RNIC
690	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
691		   (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
692#endif
693
694	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
695		/* de-allocate */
696		switch(channel->type) {
697			case XGE_HAL_CHANNEL_TYPE_FIFO:
698				__hal_fifo_close(channelh);
699				break;
700			case XGE_HAL_CHANNEL_TYPE_RING:
701				__hal_ring_close(channelh);
702				break;
703#ifdef XGEHAL_RNIC
704			case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
705				__hal_sq_close(channelh);
706				hldev->virtual_paths[vp_id].stats.no_sqs--;
707				break;
708			case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
709				__hal_srq_close(channelh);
710				hldev->virtual_paths[vp_id].stats.no_srqs--;
711				break;
712			case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
713				__hal_cqrq_close(channelh);
714				hldev->virtual_paths[vp_id].stats.no_cqrqs--;
715				break;
716			case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
717				__hal_umq_close(channelh);
718				break;
719			case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
720				__hal_dmq_close(channelh);
721				break;
722#else
723			case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
724			case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
725			case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
726			case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
727			case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
728				xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
729					   channel->type == XGE_HAL_CHANNEL_TYPE_RING);
730				break;
731#endif
732			default:
733				break;
734		}
735	}
736	else
737	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
738
739	/* move channel back to free state list */
740	xge_list_remove(&channel->item);
741#ifdef XGEHAL_RNIC
742	if((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
743	   (channel->type == XGE_HAL_CHANNEL_TYPE_RING)) {
744#endif
745		xge_list_insert(&channel->item, &hldev->free_channels);
746
747		if (xge_list_is_empty(&hldev->fifo_channels) &&
748			xge_list_is_empty(&hldev->ring_channels)) {
749			/* clear msix_idx in case of following HW reset */
750			hldev->reset_needed_after_close = 1;
751		}
752#ifdef XGEHAL_RNIC
753	}
754	else {
755		__hal_channel_free(channel);
756	}
757#endif
758
759}
760