Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / xge / hal / xgehal / xgehal-channel.c
blob3bb2cf76a389c893200c05522af1a480129a2ab6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
21 * Copyright (c) 2002-2006 Neterion, Inc.
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"
31 * __hal_channel_dtr_next_reservelist
33 * Walking through the all available DTRs.
35 static xge_hal_status_e
36 __hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh,
37 xge_hal_dtr_h *dtrh)
39 xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
41 if (channel->reserve_top >= channel->reserve_length) {
42 return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
45 *dtrh = channel->reserve_arr[channel->reserve_top++];
47 return XGE_HAL_OK;
51 * __hal_channel_dtr_next_freelist
53 * Walking through the "freed" DTRs.
55 static xge_hal_status_e
56 __hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
58 xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
60 if (channel->reserve_initial == channel->free_length) {
61 return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS;
64 *dtrh = channel->free_arr[channel->free_length++];
66 return XGE_HAL_OK;
70 * __hal_channel_dtr_next_not_completed - Get the _next_ posted but
71 * not completed descriptor.
73 * Walking through the "not completed" DTRs.
75 static xge_hal_status_e
76 __hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh,
77 xge_hal_dtr_h *dtrh)
79 /* LINTED E_FUNC_SET_NOT_USED */
80 xge_hal_ring_rxd_1_t *rxdp __unused; /* doesn't matter 1, 3 or 5... */
82 __hal_channel_dtr_try_complete(channelh, dtrh);
83 if (*dtrh == NULL) {
84 return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
87 rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
88 xge_assert(rxdp->host_control!=0);
90 __hal_channel_dtr_complete(channelh);
92 return XGE_HAL_OK;
95 xge_hal_channel_t*
96 __hal_channel_allocate(xge_hal_device_h devh, int post_qid,
97 xge_hal_channel_type_e type)
99 xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
100 xge_hal_channel_t *channel;
101 int size = 0;
103 switch(type) {
104 case XGE_HAL_CHANNEL_TYPE_FIFO:
105 xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM &&
106 post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM);
107 size = sizeof(xge_hal_fifo_t);
108 break;
109 case XGE_HAL_CHANNEL_TYPE_RING:
110 xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM &&
111 post_qid + 1 <= XGE_HAL_MAX_RING_NUM);
112 size = sizeof(xge_hal_ring_t);
113 break;
114 default :
115 xge_assert(size);
116 break;
121 /* allocate FIFO channel */
122 channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size);
123 if (channel == NULL) {
124 return NULL;
126 xge_os_memzero(channel, size);
128 channel->pdev = hldev->pdev;
129 channel->regh0 = hldev->regh0;
130 channel->regh1 = hldev->regh1;
131 channel->type = type;
132 channel->devh = devh;
133 channel->post_qid = post_qid;
134 channel->compl_qid = 0;
136 return channel;
139 void __hal_channel_free(xge_hal_channel_t *channel)
141 int size = 0;
143 xge_assert(channel->pdev);
145 switch(channel->type) {
146 case XGE_HAL_CHANNEL_TYPE_FIFO:
147 size = sizeof(xge_hal_fifo_t);
148 break;
149 case XGE_HAL_CHANNEL_TYPE_RING:
150 size = sizeof(xge_hal_ring_t);
151 break;
152 case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
153 case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
154 case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
155 case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
156 case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
157 xge_assert(size);
158 break;
159 default:
160 break;
163 xge_os_free(channel->pdev, channel, size);
166 xge_hal_status_e
167 __hal_channel_initialize (xge_hal_channel_h channelh,
168 xge_hal_channel_attr_t *attr, void **reserve_arr,
169 int reserve_initial, int reserve_max, int reserve_threshold)
171 xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
172 xge_hal_device_t *hldev;
174 hldev = (xge_hal_device_t *)channel->devh;
176 channel->dtr_term = attr->dtr_term;
177 channel->dtr_init = attr->dtr_init;
178 channel->callback = attr->callback;
179 channel->userdata = attr->userdata;
180 channel->flags = attr->flags;
181 channel->per_dtr_space = attr->per_dtr_space;
183 channel->reserve_arr = reserve_arr;
184 channel->reserve_initial = reserve_initial;
185 channel->reserve_max = reserve_max;
186 channel->reserve_length = channel->reserve_initial;
187 channel->reserve_threshold = reserve_threshold;
188 channel->reserve_top = 0;
189 channel->saved_arr = (void **) xge_os_malloc(hldev->pdev,
190 sizeof(void*)*channel->reserve_max);
191 if (channel->saved_arr == NULL) {
192 return XGE_HAL_ERR_OUT_OF_MEMORY;
194 xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max);
195 channel->free_arr = channel->saved_arr;
196 channel->free_length = channel->reserve_initial;
197 channel->work_arr = (void **) xge_os_malloc(hldev->pdev,
198 sizeof(void*)*channel->reserve_max);
199 if (channel->work_arr == NULL) {
200 return XGE_HAL_ERR_OUT_OF_MEMORY;
202 xge_os_memzero(channel->work_arr,
203 sizeof(void*)*channel->reserve_max);
204 channel->post_index = 0;
205 channel->compl_index = 0;
206 channel->length = channel->reserve_initial;
208 channel->orig_arr = (void **) xge_os_malloc(hldev->pdev,
209 sizeof(void*)*channel->reserve_max);
210 if (channel->orig_arr == NULL)
211 return XGE_HAL_ERR_OUT_OF_MEMORY;
213 xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max);
215 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
216 xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh);
217 #elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
218 xge_os_spin_lock_init(&channel->free_lock, hldev->pdev);
219 #endif
221 return XGE_HAL_OK;
224 void __hal_channel_terminate(xge_hal_channel_h channelh)
226 xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
227 xge_hal_device_t *hldev;
229 hldev = (xge_hal_device_t *)channel->devh;
231 xge_assert(channel->pdev);
232 /* undo changes made at channel_initialize() */
233 if (channel->work_arr) {
234 xge_os_free(channel->pdev, channel->work_arr,
235 sizeof(void*)*channel->reserve_max);
236 channel->work_arr = NULL;
239 if (channel->saved_arr) {
240 xge_os_free(channel->pdev, channel->saved_arr,
241 sizeof(void*)*channel->reserve_max);
242 channel->saved_arr = NULL;
245 if (channel->orig_arr) {
246 xge_os_free(channel->pdev, channel->orig_arr,
247 sizeof(void*)*channel->reserve_max);
248 channel->orig_arr = NULL;
251 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
252 xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh);
253 #elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
254 xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev);
255 #endif
259 * xge_hal_channel_open - Open communication channel.
260 * @devh: HAL device, pointer to xge_hal_device_t structure.
261 * @attr: Contains attributes required to open
262 * the channel.
263 * @channelh: The channel handle. On success (XGE_HAL_OK) HAL fills
264 * this "out" parameter with a valid channel handle.
265 * @reopen: See xge_hal_channel_reopen_e{}.
267 * Open communication channel with the device.
269 * HAL uses (persistent) channel configuration to allocate both channel
270 * and Xframe Tx and Rx descriptors.
271 * Notes:
272 * 1) The channel config data is fed into HAL prior to
273 * xge_hal_channel_open().
275 * 2) The corresponding hardware queues must be already configured and
276 * enabled.
278 * 3) Either down or up queue may be omitted, in which case the channel
279 * is treated as _unidirectional_.
281 * 4) Post and completion queue may be the same, in which case the channel
282 * is said to have "in-band completions".
284 * Note that free_channels list is not protected. i.e. caller must provide
285 * safe context.
287 * Returns: XGE_HAL_OK - success.
288 * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel.
289 * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed.
291 * See also: xge_hal_channel_attr_t{}.
292 * Usage: See ex_open{}.
294 xge_hal_status_e
295 xge_hal_channel_open(xge_hal_device_h devh,
296 xge_hal_channel_attr_t *attr,
297 xge_hal_channel_h *channelh,
298 xge_hal_channel_reopen_e reopen)
300 xge_list_t *item;
301 int i;
302 xge_hal_status_e status = XGE_HAL_OK;
303 xge_hal_channel_t *channel = NULL;
304 xge_hal_device_t *device = (xge_hal_device_t *)devh;
306 xge_assert(device);
307 xge_assert(attr);
309 *channelh = NULL;
311 /* find channel */
312 xge_list_for_each(item, &device->free_channels) {
313 xge_hal_channel_t *tmp;
315 tmp = xge_container_of(item, xge_hal_channel_t, item);
316 if (tmp->type == attr->type &&
317 tmp->post_qid == attr->post_qid &&
318 tmp->compl_qid == attr->compl_qid) {
319 channel = tmp;
320 break;
324 if (channel == NULL) {
325 return XGE_HAL_ERR_CHANNEL_NOT_FOUND;
328 xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
329 (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
331 if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
332 /* allocate memory, initialize pointers, etc */
333 switch(channel->type) {
334 case XGE_HAL_CHANNEL_TYPE_FIFO:
335 status = __hal_fifo_open(channel, attr);
336 break;
337 case XGE_HAL_CHANNEL_TYPE_RING:
338 status = __hal_ring_open(channel, attr);
339 break;
340 case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
341 case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
342 case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
343 case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
344 case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
345 status = XGE_HAL_FAIL;
346 break;
347 default:
348 break;
351 if (status == XGE_HAL_OK) {
352 for (i = 0; i < channel->reserve_initial; i++) {
353 channel->orig_arr[i] =
354 channel->reserve_arr[i];
357 else
358 return status;
359 } else {
360 xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY);
362 for (i = 0; i < channel->reserve_initial; i++) {
363 channel->reserve_arr[i] = channel->orig_arr[i];
364 channel->free_arr[i] = NULL;
366 channel->free_length = channel->reserve_initial;
367 channel->reserve_length = channel->reserve_initial;
368 channel->reserve_top = 0;
369 channel->post_index = 0;
370 channel->compl_index = 0;
371 if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
372 status = __hal_ring_initial_replenish(channel,
373 reopen);
374 if (status != XGE_HAL_OK)
375 return status;
379 /* move channel to the open state list */
381 switch(channel->type) {
382 case XGE_HAL_CHANNEL_TYPE_FIFO:
383 xge_list_remove(&channel->item);
384 xge_list_insert(&channel->item, &device->fifo_channels);
385 break;
386 case XGE_HAL_CHANNEL_TYPE_RING:
387 xge_list_remove(&channel->item);
388 xge_list_insert(&channel->item, &device->ring_channels);
389 break;
390 case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
391 case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
392 case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
393 case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
394 case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
395 xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
396 channel->type == XGE_HAL_CHANNEL_TYPE_RING);
397 break;
398 default:
399 break;
401 channel->is_open = 1;
402 channel->terminating = 0;
404 * The magic check the argument validity, has to be
405 * removed before 03/01/2005.
407 channel->magic = XGE_HAL_MAGIC;
409 *channelh = channel;
411 return XGE_HAL_OK;
415 * xge_hal_channel_abort - Abort the channel.
416 * @channelh: Channel handle.
417 * @reopen: See xge_hal_channel_reopen_e{}.
419 * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors.
420 * Currently used internally only by HAL, as part of its
421 * xge_hal_channel_close() and xge_hal_channel_open() in case
422 * of fatal error.
424 * See also: xge_hal_channel_dtr_term_f{}.
426 void xge_hal_channel_abort(xge_hal_channel_h channelh,
427 xge_hal_channel_reopen_e reopen)
429 xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
430 xge_hal_dtr_h dtr;
431 #ifdef XGE_OS_MEMORY_CHECK
432 int check_cnt = 0;
433 #endif
434 int free_length_sav;
435 int reserve_top_sav;
437 if (channel->dtr_term == NULL) {
438 return;
441 free_length_sav = channel->free_length;
442 while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) {
443 #ifdef XGE_OS_MEMORY_CHECK
444 #ifdef XGE_DEBUG_ASSERT
445 if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
446 xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
447 } else {
448 if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
449 xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
452 #endif
453 check_cnt++;
454 #endif
455 channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED,
456 channel->userdata, reopen);
458 channel->free_length = free_length_sav;
460 while (__hal_channel_dtr_next_not_completed(channelh, &dtr) ==
461 XGE_HAL_OK) {
462 #ifdef XGE_OS_MEMORY_CHECK
463 #ifdef XGE_DEBUG_ASSERT
464 if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
465 xge_assert(__hal_fifo_txdl_priv(dtr)->allocated);
466 } else {
467 if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
468 xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)
469 ->allocated);
472 #endif
473 check_cnt++;
474 #endif
475 channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED,
476 channel->userdata, reopen);
480 reserve_top_sav = channel->reserve_top;
481 while (__hal_channel_dtr_next_reservelist(channelh, &dtr) ==
482 XGE_HAL_OK) {
483 #ifdef XGE_OS_MEMORY_CHECK
484 #ifdef XGE_DEBUG_ASSERT
485 if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
486 xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated);
487 } else {
488 if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
489 xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated);
492 #endif
493 check_cnt++;
494 #endif
495 channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL,
496 channel->userdata, reopen);
498 channel->reserve_top = reserve_top_sav;
500 xge_assert(channel->reserve_length ==
501 (channel->free_length + channel->reserve_top));
503 #ifdef XGE_OS_MEMORY_CHECK
504 xge_assert(check_cnt == channel->reserve_initial);
505 #endif
510 * xge_hal_channel_close - Close communication channel.
511 * @channelh: The channel handle.
512 * @reopen: See xge_hal_channel_reopen_e{}.
514 * Will close previously opened channel and deallocate associated resources.
515 * Channel must be opened otherwise assert will be generated.
516 * Note that free_channels list is not protected. i.e. caller must provide
517 * safe context.
519 void xge_hal_channel_close(xge_hal_channel_h channelh,
520 xge_hal_channel_reopen_e reopen)
522 xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
523 xge_hal_device_t *hldev;
524 xge_list_t *item;
525 xge_assert(channel);
526 xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX);
528 hldev = (xge_hal_device_t *)channel->devh;
529 channel->is_open = 0;
530 channel->magic = XGE_HAL_DEAD;
532 /* sanity check: make sure channel is not in free list */
533 xge_list_for_each(item, &hldev->free_channels) {
534 xge_hal_channel_t *tmp;
536 tmp = xge_container_of(item, xge_hal_channel_t, item);
537 xge_assert(!tmp->is_open);
538 if (channel == tmp) {
539 return;
543 xge_hal_channel_abort(channel, reopen);
545 xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) ||
546 (channel->type == XGE_HAL_CHANNEL_TYPE_RING));
548 if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) {
549 /* de-allocate */
550 switch(channel->type) {
551 case XGE_HAL_CHANNEL_TYPE_FIFO:
552 __hal_fifo_close(channelh);
553 break;
554 case XGE_HAL_CHANNEL_TYPE_RING:
555 __hal_ring_close(channelh);
556 break;
557 case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
558 case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
559 case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
560 case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE:
561 case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE:
562 xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO ||
563 channel->type == XGE_HAL_CHANNEL_TYPE_RING);
564 break;
565 default:
566 break;
570 /* move channel back to free state list */
571 xge_list_remove(&channel->item);
572 xge_list_insert(&channel->item, &hldev->free_channels);
574 if (xge_list_is_empty(&hldev->fifo_channels) &&
575 xge_list_is_empty(&hldev->ring_channels)) {
576 /* clear msix_idx in case of following HW reset */
577 hldev->reset_needed_after_close = 1;