1171095Ssam/*- 2171095Ssam * Copyright (c) 2002-2007 Neterion, Inc. 3171095Ssam * All rights reserved. 4171095Ssam * 5171095Ssam * Redistribution and use in source and binary forms, with or without 6171095Ssam * modification, are permitted provided that the following conditions 7171095Ssam * are met: 8171095Ssam * 1. Redistributions of source code must retain the above copyright 9171095Ssam * notice, this list of conditions and the following disclaimer. 10171095Ssam * 2. Redistributions in binary form must reproduce the above copyright 11171095Ssam * notice, this list of conditions and the following disclaimer in the 12171095Ssam * documentation and/or other materials provided with the distribution. 13171095Ssam * 14171095Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15171095Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16171095Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17171095Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18171095Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19171095Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20171095Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21171095Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22171095Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23171095Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24171095Ssam * SUCH DAMAGE. 25171095Ssam * 26171095Ssam * $FreeBSD: releng/11.0/sys/dev/nxge/xgehal/xgehal-channel.c 173139 2007-10-29 14:19:32Z rwatson $ 27171095Ssam */ 28171095Ssam 29171095Ssam#include <dev/nxge/include/xgehal-channel.h> 30171095Ssam#include <dev/nxge/include/xgehal-fifo.h> 31171095Ssam#include <dev/nxge/include/xgehal-ring.h> 32171095Ssam#include <dev/nxge/include/xgehal-device.h> 33171095Ssam#include <dev/nxge/include/xgehal-regs.h> 34171095Ssam 35171095Ssam/* 36171095Ssam * __hal_channel_dtr_next_reservelist 37171095Ssam * 38171095Ssam * Walking through the all available DTRs. 39171095Ssam */ 40171095Ssamstatic xge_hal_status_e 41171095Ssam__hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh, 42173139Srwatson xge_hal_dtr_h *dtrh) 43171095Ssam{ 44171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 45171095Ssam 46171095Ssam if (channel->reserve_top >= channel->reserve_length) { 47173139Srwatson return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS; 48171095Ssam } 49171095Ssam 50171095Ssam *dtrh = channel->reserve_arr[channel->reserve_top++]; 51171095Ssam 52171095Ssam return XGE_HAL_OK; 53171095Ssam} 54171095Ssam 55171095Ssam/* 56171095Ssam * __hal_channel_dtr_next_freelist 57171095Ssam * 58171095Ssam * Walking through the "freed" DTRs. 59171095Ssam */ 60171095Ssamstatic xge_hal_status_e 61171095Ssam__hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh) 62171095Ssam{ 63171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 64171095Ssam 65171095Ssam if (channel->reserve_initial == channel->free_length) { 66173139Srwatson return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS; 67171095Ssam } 68171095Ssam 69171095Ssam *dtrh = channel->free_arr[channel->free_length++]; 70171095Ssam 71171095Ssam return XGE_HAL_OK; 72171095Ssam} 73171095Ssam 74171095Ssam/* 75171095Ssam * __hal_channel_dtr_next_not_completed - Get the _next_ posted but 76171095Ssam * not completed descriptor. 77171095Ssam * 78171095Ssam * Walking through the "not completed" DTRs. 79171095Ssam */ 80171095Ssamstatic xge_hal_status_e 81171095Ssam__hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh, 82173139Srwatson xge_hal_dtr_h *dtrh) 83171095Ssam{ 84171095Ssam xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */ 85171095Ssam __hal_channel_dtr_try_complete(channelh, dtrh); 86171095Ssam if (*dtrh == NULL) { 87173139Srwatson return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; 88171095Ssam } 89171095Ssam 90171095Ssam rxdp = (xge_hal_ring_rxd_1_t *)*dtrh; 91171095Ssam xge_assert(rxdp->host_control!=0); 92171095Ssam 93171095Ssam __hal_channel_dtr_complete(channelh); 94171095Ssam 95171095Ssam return XGE_HAL_OK; 96171095Ssam} 97171095Ssam 98171095Ssamxge_hal_channel_t* 99171095Ssam__hal_channel_allocate(xge_hal_device_h devh, int post_qid, 100173139Srwatson xge_hal_channel_type_e type) 101171095Ssam{ 102171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 103171095Ssam xge_hal_channel_t *channel; 104171095Ssam int size = 0; 105171095Ssam 106171095Ssam switch(type) { 107173139Srwatson case XGE_HAL_CHANNEL_TYPE_FIFO: 108173139Srwatson xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM && 109173139Srwatson post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM); 110173139Srwatson size = sizeof(xge_hal_fifo_t); 111173139Srwatson break; 112173139Srwatson case XGE_HAL_CHANNEL_TYPE_RING: 113173139Srwatson xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM && 114173139Srwatson post_qid + 1 <= XGE_HAL_MAX_RING_NUM); 115173139Srwatson size = sizeof(xge_hal_ring_t); 116173139Srwatson break; 117173139Srwatson default : 118173139Srwatson xge_assert(size); 119173139Srwatson break; 120171095Ssam 121171095Ssam } 122171095Ssam 123171095Ssam 124171095Ssam /* allocate FIFO channel */ 125171095Ssam channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size); 126171095Ssam if (channel == NULL) { 127173139Srwatson return NULL; 128171095Ssam } 129171095Ssam xge_os_memzero(channel, size); 130171095Ssam 131173139Srwatson channel->pdev = hldev->pdev; 132173139Srwatson channel->regh0 = hldev->regh0; 133173139Srwatson channel->regh1 = hldev->regh1; 134173139Srwatson channel->type = type; 135173139Srwatson channel->devh = devh; 136173139Srwatson channel->post_qid = post_qid; 137173139Srwatson channel->compl_qid = 0; 138171095Ssam 139171095Ssam return channel; 140171095Ssam} 141171095Ssam 142171095Ssamvoid __hal_channel_free(xge_hal_channel_t *channel) 143171095Ssam{ 144171095Ssam int size = 0; 145171095Ssam 146171095Ssam xge_assert(channel->pdev); 147171095Ssam 148171095Ssam switch(channel->type) { 149173139Srwatson case XGE_HAL_CHANNEL_TYPE_FIFO: 150173139Srwatson size = sizeof(xge_hal_fifo_t); 151173139Srwatson break; 152173139Srwatson case XGE_HAL_CHANNEL_TYPE_RING: 153173139Srwatson size = sizeof(xge_hal_ring_t); 154173139Srwatson break; 155173139Srwatson case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: 156173139Srwatson case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: 157173139Srwatson case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: 158173139Srwatson case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: 159173139Srwatson case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: 160173139Srwatson xge_assert(size); 161173139Srwatson break; 162173139Srwatson default: 163173139Srwatson break; 164171095Ssam } 165171095Ssam 166171095Ssam xge_os_free(channel->pdev, channel, size); 167171095Ssam} 168171095Ssam 169171095Ssamxge_hal_status_e 170171095Ssam__hal_channel_initialize (xge_hal_channel_h channelh, 171173139Srwatson xge_hal_channel_attr_t *attr, void **reserve_arr, 172173139Srwatson int reserve_initial, int reserve_max, int reserve_threshold) 173171095Ssam{ 174171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 175171095Ssam xge_hal_device_t *hldev; 176171095Ssam 177171095Ssam hldev = (xge_hal_device_t *)channel->devh; 178171095Ssam 179171095Ssam channel->dtr_term = attr->dtr_term; 180171095Ssam channel->dtr_init = attr->dtr_init; 181171095Ssam channel->callback = attr->callback; 182171095Ssam channel->userdata = attr->userdata; 183171095Ssam channel->flags = attr->flags; 184171095Ssam channel->per_dtr_space = attr->per_dtr_space; 185171095Ssam 186171095Ssam channel->reserve_arr = reserve_arr; 187171095Ssam channel->reserve_initial = reserve_initial; 188171095Ssam channel->reserve_max = reserve_max; 189171095Ssam channel->reserve_length = channel->reserve_initial; 190171095Ssam channel->reserve_threshold = reserve_threshold; 191171095Ssam channel->reserve_top = 0; 192171095Ssam channel->saved_arr = (void **) xge_os_malloc(hldev->pdev, 193173139Srwatson sizeof(void*)*channel->reserve_max); 194171095Ssam if (channel->saved_arr == NULL) { 195173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 196171095Ssam } 197171095Ssam xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max); 198171095Ssam channel->free_arr = channel->saved_arr; 199171095Ssam channel->free_length = channel->reserve_initial; 200171095Ssam channel->work_arr = (void **) xge_os_malloc(hldev->pdev, 201173139Srwatson sizeof(void*)*channel->reserve_max); 202171095Ssam if (channel->work_arr == NULL) { 203173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 204171095Ssam } 205171095Ssam xge_os_memzero(channel->work_arr, 206173139Srwatson sizeof(void*)*channel->reserve_max); 207171095Ssam channel->post_index = 0; 208171095Ssam channel->compl_index = 0; 209171095Ssam channel->length = channel->reserve_initial; 210171095Ssam 211171095Ssam channel->orig_arr = (void **) xge_os_malloc(hldev->pdev, 212173139Srwatson sizeof(void*)*channel->reserve_max); 213171095Ssam if (channel->orig_arr == NULL) 214173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 215171095Ssam 216171095Ssam xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max); 217171095Ssam 218171095Ssam#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) 219171095Ssam xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh); 220171095Ssam#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) 221171095Ssam xge_os_spin_lock_init(&channel->free_lock, hldev->pdev); 222171095Ssam#endif 223171095Ssam 224171095Ssam return XGE_HAL_OK; 225171095Ssam} 226171095Ssam 227171095Ssamvoid __hal_channel_terminate(xge_hal_channel_h channelh) 228171095Ssam{ 229171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 230171095Ssam xge_hal_device_t *hldev; 231171095Ssam 232171095Ssam hldev = (xge_hal_device_t *)channel->devh; 233171095Ssam 234171095Ssam xge_assert(channel->pdev); 235171095Ssam /* undo changes made at channel_initialize() */ 236171095Ssam if (channel->work_arr) { 237173139Srwatson xge_os_free(channel->pdev, channel->work_arr, 238173139Srwatson sizeof(void*)*channel->reserve_max); 239173139Srwatson channel->work_arr = NULL; 240171095Ssam } 241171095Ssam 242171095Ssam if (channel->saved_arr) { 243173139Srwatson xge_os_free(channel->pdev, channel->saved_arr, 244173139Srwatson sizeof(void*)*channel->reserve_max); 245173139Srwatson channel->saved_arr = NULL; 246171095Ssam } 247171095Ssam 248171095Ssam if (channel->orig_arr) { 249173139Srwatson xge_os_free(channel->pdev, channel->orig_arr, 250173139Srwatson sizeof(void*)*channel->reserve_max); 251173139Srwatson channel->orig_arr = NULL; 252171095Ssam } 253171095Ssam 254171095Ssam#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) 255171095Ssam xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh); 256171095Ssam#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) 257171095Ssam xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev); 258171095Ssam#endif 259171095Ssam} 260171095Ssam 261171095Ssam/** 262171095Ssam * xge_hal_channel_open - Open communication channel. 263171095Ssam * @devh: HAL device, pointer to xge_hal_device_t structure. 264171095Ssam * @attr: Contains attributes required to open 265171095Ssam * the channel. 266171095Ssam * @channelh: The channel handle. On success (XGE_HAL_OK) HAL fills 267171095Ssam * this "out" parameter with a valid channel handle. 268171095Ssam * @reopen: See xge_hal_channel_reopen_e{}. 269171095Ssam * 270171095Ssam * Open communication channel with the device. 271171095Ssam * 272171095Ssam * HAL uses (persistent) channel configuration to allocate both channel 273171095Ssam * and Xframe Tx and Rx descriptors. 274171095Ssam * Notes: 275171095Ssam * 1) The channel config data is fed into HAL prior to 276171095Ssam * xge_hal_channel_open(). 277171095Ssam * 278171095Ssam * 2) The corresponding hardware queues must be already configured and 279171095Ssam * enabled. 280171095Ssam * 281171095Ssam * 3) Either down or up queue may be omitted, in which case the channel 282171095Ssam * is treated as _unidirectional_. 283171095Ssam * 284171095Ssam * 4) Post and completion queue may be the same, in which case the channel 285171095Ssam * is said to have "in-band completions". 286171095Ssam * 287171095Ssam * Note that free_channels list is not protected. i.e. caller must provide 288171095Ssam * safe context. 289171095Ssam * 290171095Ssam * Returns: XGE_HAL_OK - success. 291171095Ssam * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel. 292171095Ssam * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed. 293171095Ssam * 294171095Ssam * See also: xge_hal_channel_attr_t{}. 295171095Ssam * Usage: See ex_open{}. 296171095Ssam */ 297171095Ssamxge_hal_status_e 298171095Ssamxge_hal_channel_open(xge_hal_device_h devh, 299173139Srwatson xge_hal_channel_attr_t *attr, 300173139Srwatson xge_hal_channel_h *channelh, 301173139Srwatson xge_hal_channel_reopen_e reopen) 302171095Ssam{ 303171095Ssam xge_list_t *item; 304171095Ssam int i; 305171095Ssam xge_hal_status_e status = XGE_HAL_OK; 306171095Ssam xge_hal_channel_t *channel = NULL; 307171095Ssam xge_hal_device_t *device = (xge_hal_device_t *)devh; 308171095Ssam 309171095Ssam xge_assert(device); 310171095Ssam xge_assert(attr); 311171095Ssam 312171095Ssam *channelh = NULL; 313171095Ssam 314171095Ssam /* find channel */ 315173139Srwatson xge_list_for_each(item, &device->free_channels) { 316173139Srwatson xge_hal_channel_t *tmp; 317171095Ssam 318173139Srwatson tmp = xge_container_of(item, xge_hal_channel_t, item); 319173139Srwatson if (tmp->type == attr->type && 320173139Srwatson tmp->post_qid == attr->post_qid && 321173139Srwatson tmp->compl_qid == attr->compl_qid) { 322173139Srwatson channel = tmp; 323173139Srwatson break; 324173139Srwatson } 325173139Srwatson } 326171095Ssam 327173139Srwatson if (channel == NULL) { 328173139Srwatson return XGE_HAL_ERR_CHANNEL_NOT_FOUND; 329171095Ssam } 330171095Ssam 331171095Ssam xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) || 332173139Srwatson (channel->type == XGE_HAL_CHANNEL_TYPE_RING)); 333171095Ssam 334171095Ssam if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) { 335173139Srwatson /* allocate memory, initialize pointers, etc */ 336173139Srwatson switch(channel->type) { 337173139Srwatson case XGE_HAL_CHANNEL_TYPE_FIFO: 338173139Srwatson status = __hal_fifo_open(channel, attr); 339173139Srwatson break; 340173139Srwatson case XGE_HAL_CHANNEL_TYPE_RING: 341173139Srwatson status = __hal_ring_open(channel, attr); 342173139Srwatson break; 343173139Srwatson case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: 344173139Srwatson case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: 345173139Srwatson case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: 346173139Srwatson case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: 347173139Srwatson case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: 348173139Srwatson status = XGE_HAL_FAIL; 349173139Srwatson break; 350173139Srwatson default: 351173139Srwatson break; 352173139Srwatson } 353171095Ssam 354173139Srwatson if (status == XGE_HAL_OK) { 355173139Srwatson for (i = 0; i < channel->reserve_initial; i++) { 356173139Srwatson channel->orig_arr[i] = 357173139Srwatson channel->reserve_arr[i]; 358173139Srwatson } 359173139Srwatson } 360173139Srwatson else 361173139Srwatson return status; 362171095Ssam } else { 363171095Ssam xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY); 364171095Ssam 365173139Srwatson for (i = 0; i < channel->reserve_initial; i++) { 366173139Srwatson channel->reserve_arr[i] = channel->orig_arr[i]; 367173139Srwatson channel->free_arr[i] = NULL; 368173139Srwatson } 369173139Srwatson channel->free_length = channel->reserve_initial; 370173139Srwatson channel->reserve_length = channel->reserve_initial; 371173139Srwatson channel->reserve_top = 0; 372173139Srwatson channel->post_index = 0; 373173139Srwatson channel->compl_index = 0; 374173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 375173139Srwatson status = __hal_ring_initial_replenish(channel, 376173139Srwatson reopen); 377173139Srwatson if (status != XGE_HAL_OK) 378173139Srwatson return status; 379173139Srwatson } 380171095Ssam } 381171095Ssam 382171095Ssam /* move channel to the open state list */ 383171095Ssam 384171095Ssam switch(channel->type) { 385173139Srwatson case XGE_HAL_CHANNEL_TYPE_FIFO: 386173139Srwatson xge_list_remove(&channel->item); 387173139Srwatson xge_list_insert(&channel->item, &device->fifo_channels); 388173139Srwatson break; 389173139Srwatson case XGE_HAL_CHANNEL_TYPE_RING: 390173139Srwatson xge_list_remove(&channel->item); 391173139Srwatson xge_list_insert(&channel->item, &device->ring_channels); 392173139Srwatson break; 393173139Srwatson case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: 394173139Srwatson case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: 395173139Srwatson case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: 396173139Srwatson case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: 397173139Srwatson case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: 398173139Srwatson xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO || 399173139Srwatson channel->type == XGE_HAL_CHANNEL_TYPE_RING); 400173139Srwatson break; 401173139Srwatson default: 402173139Srwatson break; 403171095Ssam } 404171095Ssam channel->is_open = 1; 405173139Srwatson channel->terminating = 0; 406171095Ssam /* 407171095Ssam * The magic check the argument validity, has to be 408171095Ssam * removed before 03/01/2005. 409171095Ssam */ 410171095Ssam channel->magic = XGE_HAL_MAGIC; 411171095Ssam 412171095Ssam *channelh = channel; 413171095Ssam 414171095Ssam return XGE_HAL_OK; 415171095Ssam} 416171095Ssam 417171095Ssam/** 418171095Ssam * xge_hal_channel_abort - Abort the channel. 419171095Ssam * @channelh: Channel handle. 420171095Ssam * @reopen: See xge_hal_channel_reopen_e{}. 421171095Ssam * 422171095Ssam * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors. 423171095Ssam * Currently used internally only by HAL, as part of its 424171095Ssam * xge_hal_channel_close() and xge_hal_channel_open() in case 425171095Ssam * of fatal error. 426171095Ssam * 427171095Ssam * See also: xge_hal_channel_dtr_term_f{}. 428171095Ssam */ 429171095Ssamvoid xge_hal_channel_abort(xge_hal_channel_h channelh, 430173139Srwatson xge_hal_channel_reopen_e reopen) 431171095Ssam{ 432171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 433171095Ssam xge_hal_dtr_h dtr; 434171095Ssam#ifdef XGE_OS_MEMORY_CHECK 435171095Ssam int check_cnt = 0; 436171095Ssam#endif 437171095Ssam int free_length_sav; 438171095Ssam int reserve_top_sav; 439171095Ssam 440171095Ssam if (channel->dtr_term == NULL) { 441173139Srwatson return; 442171095Ssam } 443171095Ssam 444171095Ssam free_length_sav = channel->free_length; 445171095Ssam while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) { 446171095Ssam#ifdef XGE_OS_MEMORY_CHECK 447171095Ssam#ifdef XGE_DEBUG_ASSERT 448173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 449173139Srwatson xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated); 450173139Srwatson } else { 451173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 452173139Srwatson xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated); 453173139Srwatson } 454173139Srwatson } 455171095Ssam#endif 456173139Srwatson check_cnt++; 457171095Ssam#endif 458173139Srwatson channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED, 459173139Srwatson channel->userdata, reopen); 460171095Ssam } 461171095Ssam channel->free_length = free_length_sav; 462171095Ssam 463171095Ssam while (__hal_channel_dtr_next_not_completed(channelh, &dtr) == 464171095Ssam XGE_HAL_OK) { 465171095Ssam#ifdef XGE_OS_MEMORY_CHECK 466171095Ssam#ifdef XGE_DEBUG_ASSERT 467173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 468173139Srwatson xge_assert(__hal_fifo_txdl_priv(dtr)->allocated); 469173139Srwatson } else { 470173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 471173139Srwatson xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr) 472173139Srwatson ->allocated); 473173139Srwatson } 474173139Srwatson } 475171095Ssam#endif 476173139Srwatson check_cnt++; 477171095Ssam#endif 478173139Srwatson channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED, 479173139Srwatson channel->userdata, reopen); 480171095Ssam 481171095Ssam } 482171095Ssam 483171095Ssam reserve_top_sav = channel->reserve_top; 484171095Ssam while (__hal_channel_dtr_next_reservelist(channelh, &dtr) == 485173139Srwatson XGE_HAL_OK) { 486171095Ssam#ifdef XGE_OS_MEMORY_CHECK 487171095Ssam#ifdef XGE_DEBUG_ASSERT 488173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 489173139Srwatson xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated); 490173139Srwatson } else { 491173139Srwatson if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 492173139Srwatson xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated); 493173139Srwatson } 494173139Srwatson } 495171095Ssam#endif 496173139Srwatson check_cnt++; 497171095Ssam#endif 498173139Srwatson channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL, 499173139Srwatson channel->userdata, reopen); 500171095Ssam } 501171095Ssam channel->reserve_top = reserve_top_sav; 502171095Ssam 503171095Ssam xge_assert(channel->reserve_length == 504173139Srwatson (channel->free_length + channel->reserve_top)); 505171095Ssam 506171095Ssam#ifdef XGE_OS_MEMORY_CHECK 507171095Ssam xge_assert(check_cnt == channel->reserve_initial); 508171095Ssam#endif 509171095Ssam 510171095Ssam} 511171095Ssam 512171095Ssam/** 513171095Ssam * xge_hal_channel_close - Close communication channel. 514171095Ssam * @channelh: The channel handle. 515171095Ssam * @reopen: See xge_hal_channel_reopen_e{}. 516171095Ssam * 517171095Ssam * Will close previously opened channel and deallocate associated resources. 518171095Ssam * Channel must be opened otherwise assert will be generated. 519171095Ssam * Note that free_channels list is not protected. i.e. caller must provide 520171095Ssam * safe context. 521171095Ssam */ 522171095Ssamvoid xge_hal_channel_close(xge_hal_channel_h channelh, 523173139Srwatson xge_hal_channel_reopen_e reopen) 524171095Ssam{ 525171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 526171095Ssam xge_hal_device_t *hldev; 527171095Ssam xge_list_t *item; 528171095Ssam xge_assert(channel); 529171095Ssam xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX); 530171095Ssam 531171095Ssam hldev = (xge_hal_device_t *)channel->devh; 532171095Ssam channel->is_open = 0; 533171095Ssam channel->magic = XGE_HAL_DEAD; 534171095Ssam 535173139Srwatson /* sanity check: make sure channel is not in free list */ 536173139Srwatson xge_list_for_each(item, &hldev->free_channels) { 537173139Srwatson xge_hal_channel_t *tmp; 538171095Ssam 539173139Srwatson tmp = xge_container_of(item, xge_hal_channel_t, item); 540173139Srwatson xge_assert(!tmp->is_open); 541173139Srwatson if (channel == tmp) { 542173139Srwatson return; 543173139Srwatson } 544171095Ssam } 545171095Ssam 546171095Ssam xge_hal_channel_abort(channel, reopen); 547171095Ssam 548171095Ssam xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) || 549173139Srwatson (channel->type == XGE_HAL_CHANNEL_TYPE_RING)); 550171095Ssam 551171095Ssam if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) { 552173139Srwatson /* de-allocate */ 553173139Srwatson switch(channel->type) { 554173139Srwatson case XGE_HAL_CHANNEL_TYPE_FIFO: 555173139Srwatson __hal_fifo_close(channelh); 556173139Srwatson break; 557173139Srwatson case XGE_HAL_CHANNEL_TYPE_RING: 558173139Srwatson __hal_ring_close(channelh); 559173139Srwatson break; 560173139Srwatson case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: 561173139Srwatson case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: 562173139Srwatson case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: 563173139Srwatson case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: 564173139Srwatson case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: 565173139Srwatson xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO || 566173139Srwatson channel->type == XGE_HAL_CHANNEL_TYPE_RING); 567173139Srwatson break; 568173139Srwatson default: 569173139Srwatson break; 570173139Srwatson } 571171095Ssam } 572171095Ssam else 573171095Ssam xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY); 574171095Ssam 575171095Ssam /* move channel back to free state list */ 576171095Ssam xge_list_remove(&channel->item); 577173139Srwatson xge_list_insert(&channel->item, &hldev->free_channels); 578171095Ssam 579173139Srwatson if (xge_list_is_empty(&hldev->fifo_channels) && 580173139Srwatson xge_list_is_empty(&hldev->ring_channels)) { 581173139Srwatson /* clear msix_idx in case of following HW reset */ 582173139Srwatson hldev->reset_needed_after_close = 1; 583171095Ssam } 584171095Ssam} 585