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