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