xgehal-channel.c revision 173139
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: head/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 */ 40static xge_hal_status_e 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 */ 60static xge_hal_status_e 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 */ 80static xge_hal_status_e 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 98xge_hal_channel_t* 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 142void __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 169xge_hal_status_e 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 227void __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 */ 297xge_hal_status_e 298xge_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 */ 429void 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 */ 522void 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