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: stable/10/sys/dev/nxge/xgehal/xgehal-channel.c 173139 2007-10-29 14:19:32Z rwatson $
27  */
28 
29 #include <dev/nxge/include/xgehal-channel.h>
30 #include <dev/nxge/include/xgehal-fifo.h>
31 #include <dev/nxge/include/xgehal-ring.h>
32 #include <dev/nxge/include/xgehal-device.h>
33 #include <dev/nxge/include/xgehal-regs.h>
34 
35 /*
36  * __hal_channel_dtr_next_reservelist
37  *
38  * Walking through the all available DTRs.
39  */
40 static xge_hal_status_e
__hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)41 __hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,
42 	    xge_hal_dtr_h *dtrh)
43 {
44 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
45 
46 	if (channel->reserve_top >= channel->reserve_length) {
47 	    return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
48 	}
49 
50 	*dtrh = channel->reserve_arr[channel->reserve_top++];
51 
52 	return XGE_HAL_OK;
53 }
54 
55 /*
56  * __hal_channel_dtr_next_freelist
57  *
58  * Walking through the "freed" DTRs.
59  */
60 static xge_hal_status_e
__hal_channel_dtr_next_freelist(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)61 __hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
62 {
63 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
64 
65 	if (channel->reserve_initial == channel->free_length) {
66 	    return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
67 	}
68 
69 	*dtrh = channel->free_arr[channel->free_length++];
70 
71 	return XGE_HAL_OK;
72 }
73 
74 /*
75  * __hal_channel_dtr_next_not_completed - Get the _next_ posted but
76  *                                     not completed descriptor.
77  *
78  * Walking through the "not completed" DTRs.
79  */
80 static xge_hal_status_e
__hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)81 __hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,
82 	    xge_hal_dtr_h *dtrh)
83 {
84 	xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */
85 	__hal_channel_dtr_try_complete(channelh, dtrh);
86 	if (*dtrh == NULL) {
87 	    return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
88 	}
89 
90 	rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
91 	xge_assert(rxdp->host_control!=0);
92 
93 	__hal_channel_dtr_complete(channelh);
94 
95 	return XGE_HAL_OK;
96 }
97 
98 xge_hal_channel_t*
__hal_channel_allocate(xge_hal_device_h devh,int post_qid,xge_hal_channel_type_e type)99 __hal_channel_allocate(xge_hal_device_h devh, int post_qid,
100 	    xge_hal_channel_type_e type)
101 {
102 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
103 	xge_hal_channel_t *channel;
104 	int size = 0;
105 
106 	switch(type) {
107 	    case XGE_HAL_CHANNEL_TYPE_FIFO:
108 	        xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM &&
109 	             post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM);
110 	        size = sizeof(xge_hal_fifo_t);
111 	        break;
112 	    case XGE_HAL_CHANNEL_TYPE_RING:
113 	        xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM &&
114 	            post_qid + 1 <= XGE_HAL_MAX_RING_NUM);
115 	        size = sizeof(xge_hal_ring_t);
116 	        break;
117 	    default :
118 	        xge_assert(size);
119 	        break;
120 
121 	}
122 
123 
124 	/* allocate FIFO channel */
125 	channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size);
126 	if (channel == NULL) {
127 	    return NULL;
128 	}
129 	xge_os_memzero(channel, size);
130 
131 	channel->pdev       = hldev->pdev;
132 	channel->regh0      = hldev->regh0;
133 	channel->regh1      = hldev->regh1;
134 	channel->type       = type;
135 	channel->devh       = devh;
136 	channel->post_qid   = post_qid;
137 	channel->compl_qid  = 0;
138 
139 	return channel;
140 }
141 
__hal_channel_free(xge_hal_channel_t * channel)142 void __hal_channel_free(xge_hal_channel_t *channel)
143 {
144 	int size = 0;
145 
146 	xge_assert(channel->pdev);
147 
148 	switch(channel->type) {
149 	    case XGE_HAL_CHANNEL_TYPE_FIFO:
150 	        size = sizeof(xge_hal_fifo_t);
151 	        break;
152 	    case XGE_HAL_CHANNEL_TYPE_RING:
153 	        size = sizeof(xge_hal_ring_t);
154 	        break;
155 	    case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
156 	    case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
157 	    case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
158 	    case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
159 	    case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
160 	        xge_assert(size);
161 	        break;
162 	    default:
163 	        break;
164 	}
165 
166 	xge_os_free(channel->pdev, channel, size);
167 }
168 
169 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)170 __hal_channel_initialize (xge_hal_channel_h channelh,
171 	    xge_hal_channel_attr_t *attr, void **reserve_arr,
172 	    int reserve_initial, int reserve_max, int reserve_threshold)
173 {
174 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
175 	xge_hal_device_t *hldev;
176 
177 	hldev = (xge_hal_device_t *)channel->devh;
178 
179 	channel->dtr_term = attr->dtr_term;
180 	channel->dtr_init = attr->dtr_init;
181 	channel->callback = attr->callback;
182 	channel->userdata = attr->userdata;
183 	channel->flags = attr->flags;
184 	channel->per_dtr_space = attr->per_dtr_space;
185 
186 	channel->reserve_arr = reserve_arr;
187 	channel->reserve_initial = reserve_initial;
188 	channel->reserve_max = reserve_max;
189 	channel->reserve_length = channel->reserve_initial;
190 	channel->reserve_threshold = reserve_threshold;
191 	channel->reserve_top = 0;
192 	channel->saved_arr = (void **) xge_os_malloc(hldev->pdev,
193 	                   sizeof(void*)*channel->reserve_max);
194 	if (channel->saved_arr == NULL) {
195 	    return XGE_HAL_ERR_OUT_OF_MEMORY;
196 	}
197 	xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max);
198 	channel->free_arr = channel->saved_arr;
199 	channel->free_length = channel->reserve_initial;
200 	channel->work_arr = (void **) xge_os_malloc(hldev->pdev,
201 	              sizeof(void*)*channel->reserve_max);
202 	if (channel->work_arr == NULL) {
203 	    return XGE_HAL_ERR_OUT_OF_MEMORY;
204 	}
205 	xge_os_memzero(channel->work_arr,
206 	                   sizeof(void*)*channel->reserve_max);
207 	channel->post_index = 0;
208 	channel->compl_index = 0;
209 	channel->length = channel->reserve_initial;
210 
211 	channel->orig_arr = (void **) xge_os_malloc(hldev->pdev,
212 	                    sizeof(void*)*channel->reserve_max);
213 	if (channel->orig_arr == NULL)
214 	    return XGE_HAL_ERR_OUT_OF_MEMORY;
215 
216 	xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max);
217 
218 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
219 	xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh);
220 #elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
221 	xge_os_spin_lock_init(&channel->free_lock, hldev->pdev);
222 #endif
223 
224 	return XGE_HAL_OK;
225 }
226 
__hal_channel_terminate(xge_hal_channel_h channelh)227 void __hal_channel_terminate(xge_hal_channel_h channelh)
228 {
229 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
230 	xge_hal_device_t *hldev;
231 
232 	hldev = (xge_hal_device_t *)channel->devh;
233 
234 	xge_assert(channel->pdev);
235 	/* undo changes made at channel_initialize() */
236 	if (channel->work_arr) {
237 	    xge_os_free(channel->pdev, channel->work_arr,
238 	              sizeof(void*)*channel->reserve_max);
239 	    channel->work_arr = NULL;
240 	}
241 
242 	if (channel->saved_arr) {
243 	    xge_os_free(channel->pdev, channel->saved_arr,
244 	              sizeof(void*)*channel->reserve_max);
245 	    channel->saved_arr = NULL;
246 	}
247 
248 	if (channel->orig_arr) {
249 	    xge_os_free(channel->pdev, channel->orig_arr,
250 	              sizeof(void*)*channel->reserve_max);
251 	    channel->orig_arr = NULL;
252 	}
253 
254 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
255 	xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh);
256 #elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
257 	xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev);
258 #endif
259 }
260 
261 /**
262  * xge_hal_channel_open - Open communication channel.
263  * @devh: HAL device, pointer to xge_hal_device_t structure.
264  * @attr: Contains attributes required to open
265  *        the channel.
266  * @channelh:  The channel handle. On success (XGE_HAL_OK) HAL fills
267  * this "out" parameter with a valid channel handle.
268  * @reopen: See  xge_hal_channel_reopen_e{}.
269  *
270  * Open communication channel with the device.
271  *
272  * HAL uses (persistent) channel configuration to allocate both channel
273  * and Xframe Tx and Rx descriptors.
274  * Notes:
275  *     1) The channel config data is fed into HAL prior to
276  *        xge_hal_channel_open().
277  *
278  *     2) The corresponding hardware queues must be already configured and
279  *        enabled.
280  *
281  *     3) Either down or up queue may be omitted, in which case the channel
282  *        is treated as _unidirectional_.
283  *
284  *     4) Post and completion queue may be the same, in which case the channel
285  *        is said to have "in-band completions".
286  *
287  * Note that free_channels list is not protected. i.e. caller must provide
288  * safe context.
289  *
290  * Returns: XGE_HAL_OK  - success.
291  * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel.
292  * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed.
293  *
294  * See also: xge_hal_channel_attr_t{}.
295  * Usage: See ex_open{}.
296  */
297 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)298 xge_hal_channel_open(xge_hal_device_h devh,
299 	         xge_hal_channel_attr_t *attr,
300 	         xge_hal_channel_h *channelh,
301 	         xge_hal_channel_reopen_e reopen)
302 {
303 	xge_list_t *item;
304 	int i;
305 	xge_hal_status_e status = XGE_HAL_OK;
306 	xge_hal_channel_t *channel = NULL;
307 	xge_hal_device_t *device = (xge_hal_device_t *)devh;
308 
309 	xge_assert(device);
310 	xge_assert(attr);
311 
312 	*channelh = NULL;
313 
314 	/* find channel */
315 	xge_list_for_each(item, &device->free_channels) {
316 	    xge_hal_channel_t *tmp;
317 
318 	    tmp = xge_container_of(item, xge_hal_channel_t, item);
319 	    if (tmp->type == attr->type &&
320 	    tmp->post_qid == attr->post_qid &&
321 	    tmp->compl_qid == attr->compl_qid) {
322 	        channel = tmp;
323 	        break;
324 	    }
325 	}
326 
327 	if (channel == NULL) {
328 	    return XGE_HAL_ERR_CHANNEL_NOT_FOUND;
329 	}
330 
331 	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
332 	    (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
333 
334 	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
335 	    /* allocate memory, initialize pointers, etc */
336 	    switch(channel->type) {
337 	        case XGE_HAL_CHANNEL_TYPE_FIFO:
338 	            status = __hal_fifo_open(channel, attr);
339 	            break;
340 	        case XGE_HAL_CHANNEL_TYPE_RING:
341 	            status = __hal_ring_open(channel, attr);
342 	            break;
343 	        case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
344 	        case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
345 	        case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
346 	        case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
347 	        case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
348 	            status = XGE_HAL_FAIL;
349 	            break;
350 	        default:
351 	            break;
352 	    }
353 
354 	    if (status == XGE_HAL_OK) {
355 	        for (i = 0; i < channel->reserve_initial; i++) {
356 	            channel->orig_arr[i] =
357 	                channel->reserve_arr[i];
358 	        }
359 	    }
360 	    else
361 	        return status;
362 	} else {
363 	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
364 
365 	    for (i = 0; i < channel->reserve_initial; i++) {
366 	        channel->reserve_arr[i] = channel->orig_arr[i];
367 	        channel->free_arr[i] = NULL;
368 	    }
369 	    channel->free_length = channel->reserve_initial;
370 	    channel->reserve_length = channel->reserve_initial;
371 	    channel->reserve_top = 0;
372 	    channel->post_index = 0;
373 	    channel->compl_index = 0;
374 	            if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
375 	        status = __hal_ring_initial_replenish(channel,
376 	                              reopen);
377 	                    if (status != XGE_HAL_OK)
378 	                            return status;
379 	    }
380 	}
381 
382 	/* move channel to the open state list */
383 
384 	switch(channel->type) {
385 	    case XGE_HAL_CHANNEL_TYPE_FIFO:
386 	        xge_list_remove(&channel->item);
387 	        xge_list_insert(&channel->item, &device->fifo_channels);
388 	        break;
389 	    case XGE_HAL_CHANNEL_TYPE_RING:
390 	        xge_list_remove(&channel->item);
391 	        xge_list_insert(&channel->item, &device->ring_channels);
392 	        break;
393 	    case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
394 	    case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
395 	    case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
396 	    case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
397 	    case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
398 	        xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
399 	               channel->type == XGE_HAL_CHANNEL_TYPE_RING);
400 	        break;
401 	    default:
402 	        break;
403 	}
404 	channel->is_open = 1;
405 	channel->terminating = 0;
406 	/*
407 	 * The magic check the argument validity, has to be
408 	 * removed before 03/01/2005.
409 	 */
410 	channel->magic = XGE_HAL_MAGIC;
411 
412 	*channelh = channel;
413 
414 	return XGE_HAL_OK;
415 }
416 
417 /**
418  * xge_hal_channel_abort - Abort the channel.
419  * @channelh: Channel handle.
420  * @reopen: See  xge_hal_channel_reopen_e{}.
421  *
422  * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors.
423  * Currently used internally only by HAL, as part of its
424  * xge_hal_channel_close() and xge_hal_channel_open() in case
425  * of fatal error.
426  *
427  * See also: xge_hal_channel_dtr_term_f{}.
428  */
xge_hal_channel_abort(xge_hal_channel_h channelh,xge_hal_channel_reopen_e reopen)429 void xge_hal_channel_abort(xge_hal_channel_h channelh,
430 	                       xge_hal_channel_reopen_e reopen)
431 {
432 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
433 	xge_hal_dtr_h dtr;
434 #ifdef XGE_OS_MEMORY_CHECK
435 	int check_cnt = 0;
436 #endif
437 	int free_length_sav;
438 	int reserve_top_sav;
439 
440 	if (channel->dtr_term == NULL) {
441 	    return;
442 	}
443 
444 	free_length_sav = channel->free_length;
445 	while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) {
446 #ifdef XGE_OS_MEMORY_CHECK
447 #ifdef XGE_DEBUG_ASSERT
448 	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
449 	        xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
450 	    } else {
451 	        if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
452 	            xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
453 	        }
454 	    }
455 #endif
456 	    check_cnt++;
457 #endif
458 	    channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED,
459 	              channel->userdata, reopen);
460 	}
461 	channel->free_length = free_length_sav;
462 
463 	while (__hal_channel_dtr_next_not_completed(channelh, &dtr) ==
464 	       XGE_HAL_OK) {
465 #ifdef XGE_OS_MEMORY_CHECK
466 #ifdef XGE_DEBUG_ASSERT
467 	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
468 	        xge_assert(__hal_fifo_txdl_priv(dtr)->allocated);
469 	    } else {
470 	        if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
471 	        xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)
472 	               ->allocated);
473 	        }
474 	    }
475 #endif
476 	    check_cnt++;
477 #endif
478 	    channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED,
479 	              channel->userdata, reopen);
480 
481 	}
482 
483 	reserve_top_sav = channel->reserve_top;
484 	while (__hal_channel_dtr_next_reservelist(channelh, &dtr) ==
485 	                        XGE_HAL_OK) {
486 #ifdef XGE_OS_MEMORY_CHECK
487 #ifdef XGE_DEBUG_ASSERT
488 	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
489 	        xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
490 	    } else {
491 	        if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
492 	        xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
493 	        }
494 	    }
495 #endif
496 	    check_cnt++;
497 #endif
498 	    channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL,
499 	              channel->userdata, reopen);
500 	}
501 	channel->reserve_top = reserve_top_sav;
502 
503 	xge_assert(channel->reserve_length ==
504 	            (channel->free_length + channel->reserve_top));
505 
506 #ifdef XGE_OS_MEMORY_CHECK
507 	xge_assert(check_cnt == channel->reserve_initial);
508 #endif
509 
510 }
511 
512 /**
513  * xge_hal_channel_close - Close communication channel.
514  * @channelh: The channel handle.
515  * @reopen: See  xge_hal_channel_reopen_e{}.
516  *
517  * Will close previously opened channel and deallocate associated resources.
518  * Channel must be opened otherwise assert will be generated.
519  * Note that free_channels list is not protected. i.e. caller must provide
520  * safe context.
521  */
xge_hal_channel_close(xge_hal_channel_h channelh,xge_hal_channel_reopen_e reopen)522 void xge_hal_channel_close(xge_hal_channel_h channelh,
523 	                       xge_hal_channel_reopen_e reopen)
524 {
525 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
526 	xge_hal_device_t *hldev;
527 	xge_list_t *item;
528 	xge_assert(channel);
529 	xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX);
530 
531 	hldev = (xge_hal_device_t *)channel->devh;
532 	channel->is_open = 0;
533 	channel->magic = XGE_HAL_DEAD;
534 
535 	/* sanity check: make sure channel is not in free list */
536 	xge_list_for_each(item, &hldev->free_channels) {
537 	    xge_hal_channel_t *tmp;
538 
539 	    tmp = xge_container_of(item, xge_hal_channel_t, item);
540 	    xge_assert(!tmp->is_open);
541 	    if (channel == tmp) {
542 	        return;
543 	    }
544 	}
545 
546 	xge_hal_channel_abort(channel, reopen);
547 
548 	xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
549 	       (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
550 
551 	if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
552 	    /* de-allocate */
553 	    switch(channel->type) {
554 	        case XGE_HAL_CHANNEL_TYPE_FIFO:
555 	            __hal_fifo_close(channelh);
556 	            break;
557 	        case XGE_HAL_CHANNEL_TYPE_RING:
558 	            __hal_ring_close(channelh);
559 	            break;
560 	        case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
561 	        case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
562 	        case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
563 	        case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
564 	        case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
565 	            xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
566 	                   channel->type == XGE_HAL_CHANNEL_TYPE_RING);
567 	            break;
568 	        default:
569 	            break;
570 	    }
571 	}
572 	else
573 	        xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
574 
575 	/* move channel back to free state list */
576 	xge_list_remove(&channel->item);
577 	xge_list_insert(&channel->item, &hldev->free_channels);
578 
579 	if (xge_list_is_empty(&hldev->fifo_channels) &&
580 	    xge_list_is_empty(&hldev->ring_channels)) {
581 	    /* clear msix_idx in case of following HW reset */
582 	    hldev->reset_needed_after_close = 1;
583 	}
584 }
585