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