1/*- 2 * Copyright(c) 2002-2011 Exar Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification are permitted provided the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Exar Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31/*$FreeBSD$*/ 32 33#include <dev/vxge/vxgehal/vxgehal.h> 34 35/* 36 * __hal_blockpool_create - Create block pool 37 * @devh: Pointer to HAL Device object. 38 * @blockpool: Block pool to be created. 39 * @pool_size: Number of blocks in the pool. 40 * @pool_incr: Number of blocks to be request from OS at a time 41 * @pool_min: Number of blocks below which new blocks to be requested. 42 * @pool_max: Number of blocks above which block to be freed. 43 * 44 * This function creates block pool 45 */ 46 47vxge_hal_status_e 48__hal_blockpool_create(vxge_hal_device_h devh, 49 __hal_blockpool_t *blockpool, 50 u32 pool_size, 51 u32 pool_incr, 52 u32 pool_min, 53 u32 pool_max) 54{ 55 u32 i; 56 __hal_device_t *hldev = (__hal_device_t *) devh; 57 __hal_blockpool_entry_t *entry; 58 void *memblock; 59 dma_addr_t dma_addr; 60 pci_dma_h dma_handle; 61 pci_dma_acc_h acc_handle; 62 vxge_hal_status_e status = VXGE_HAL_OK; 63 64 vxge_assert(devh != NULL); 65 vxge_os_memzero(&dma_handle, sizeof(pci_dma_h)); 66 vxge_os_memzero(&acc_handle, sizeof(pci_dma_acc_h)); 67 68 vxge_hal_trace_log_pool("==> %s:%s:%d", 69 __FILE__, __func__, __LINE__); 70 71 vxge_hal_trace_log_pool("devh = 0x"VXGE_OS_STXFMT", " 72 "blockpool = 0x"VXGE_OS_STXFMT", pool_size = %d, pool_incr = %d, " 73 "pool_min = %d, pool_max = %d", (ptr_t) devh, (ptr_t) blockpool, 74 pool_size, pool_incr, pool_min, pool_max); 75 76 if (blockpool == NULL) { 77 vxge_hal_err_log_pool( 78 "%s:%d null pointer passed. blockpool is null", 79 __FILE__, __LINE__); 80 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 81 __FILE__, __func__, __LINE__, VXGE_HAL_FAIL); 82 return (VXGE_HAL_FAIL); 83 } 84 85 blockpool->hldev = devh; 86 blockpool->block_size = VXGE_OS_HOST_PAGE_SIZE; 87 blockpool->pool_size = 0; 88 blockpool->pool_incr = pool_incr; 89 blockpool->pool_min = pool_min; 90 blockpool->pool_max = pool_max; 91 blockpool->req_out = 0; 92 93#if defined(VXGE_HAL_DMA_CONSISTENT) 94 blockpool->dma_flags = VXGE_OS_DMA_CONSISTENT; 95#else 96 blockpool->dma_flags = VXGE_OS_DMA_STREAMING; 97#endif 98 99 vxge_list_init(&blockpool->free_block_list); 100 101 vxge_list_init(&blockpool->free_entry_list); 102 103#if defined(VXGE_HAL_BP_POST) 104 vxge_os_spin_lock_init(&blockpool->pool_lock, hldev->header.pdev); 105#elif defined(VXGE_HAL_BP_POST_IRQ) 106 vxge_os_spin_lock_init_irq(&blockpool->pool_lock, hldev->header.irqh); 107#endif 108 109 for (i = 0; i < pool_size + pool_max; i++) { 110 111 entry = (__hal_blockpool_entry_t *) vxge_os_malloc( 112 hldev->header.pdev, 113 sizeof(__hal_blockpool_entry_t)); 114 if (entry == NULL) { 115 __hal_blockpool_destroy(blockpool); 116 117 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 118 __FILE__, __func__, __LINE__, 119 VXGE_HAL_ERR_OUT_OF_MEMORY); 120 121 return (VXGE_HAL_ERR_OUT_OF_MEMORY); 122 } 123 124 vxge_list_insert(&entry->item, &blockpool->free_entry_list); 125 } 126 127 for (i = 0; i < pool_size; i++) { 128 129 memblock = vxge_os_dma_malloc( 130 hldev->header.pdev, 131 VXGE_OS_HOST_PAGE_SIZE, 132 blockpool->dma_flags, 133 &dma_handle, 134 &acc_handle); 135 136 if (memblock == NULL) { 137 __hal_blockpool_destroy(blockpool); 138 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 139 __FILE__, __func__, __LINE__, 140 VXGE_HAL_ERR_OUT_OF_MEMORY); 141 142 return (VXGE_HAL_ERR_OUT_OF_MEMORY); 143 } 144 145 dma_addr = vxge_os_dma_map( 146 hldev->header.pdev, 147 dma_handle, 148 memblock, 149 VXGE_OS_HOST_PAGE_SIZE, 150 VXGE_OS_DMA_DIR_BIDIRECTIONAL, 151 blockpool->dma_flags); 152 153 if (dma_addr == VXGE_OS_INVALID_DMA_ADDR) { 154 vxge_os_dma_free(hldev->header.pdev, 155 memblock, 156 VXGE_OS_HOST_PAGE_SIZE, 157 blockpool->dma_flags, 158 &dma_handle, 159 &acc_handle); 160 __hal_blockpool_destroy(blockpool); 161 162 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 163 __FILE__, __func__, __LINE__, 164 VXGE_HAL_ERR_OUT_OF_MEMORY); 165 166 return (VXGE_HAL_ERR_OUT_OF_MEMORY); 167 } 168 169 entry = (__hal_blockpool_entry_t *) 170 vxge_list_first_get(&blockpool->free_entry_list); 171 172 if (entry == NULL) { 173 entry = (__hal_blockpool_entry_t *) vxge_os_malloc( 174 hldev->header.pdev, 175 sizeof(__hal_blockpool_entry_t)); 176 } 177 178 if (entry != NULL) { 179 vxge_list_remove(&entry->item); 180 entry->length = VXGE_OS_HOST_PAGE_SIZE; 181 entry->memblock = memblock; 182 entry->dma_addr = dma_addr; 183 entry->acc_handle = acc_handle; 184 entry->dma_handle = dma_handle; 185 vxge_list_insert(&entry->item, 186 &blockpool->free_block_list); 187 blockpool->pool_size++; 188 } else { 189 __hal_blockpool_destroy(blockpool); 190 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 191 __FILE__, __func__, __LINE__, 192 VXGE_HAL_ERR_OUT_OF_MEMORY); 193 194 return (VXGE_HAL_ERR_OUT_OF_MEMORY); 195 } 196 } 197 198 vxge_hal_info_log_pool( 199 "Blockpool block size:%d block pool size: %d", 200 blockpool->block_size, blockpool->pool_size); 201 202 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 203 __FILE__, __func__, __LINE__, status); 204 205 return (status); 206} 207 208/* 209 * __hal_blockpool_destroy - Deallocates the block pool 210 * @blockpool: blockpool to be deallocated 211 * 212 * This function freeup the memory pool and removes the 213 * block pool. 214 */ 215 216void 217__hal_blockpool_destroy( 218 __hal_blockpool_t *blockpool) 219{ 220 __hal_device_t *hldev; 221 vxge_list_t *p, *n; 222 223 vxge_assert(blockpool != NULL); 224 225 hldev = (__hal_device_t *) blockpool->hldev; 226 227 vxge_hal_trace_log_pool("==> %s:%s:%d", 228 __FILE__, __func__, __LINE__); 229 230 vxge_hal_trace_log_pool("blockpool = 0x"VXGE_OS_STXFMT, 231 (ptr_t) blockpool); 232 233 if (blockpool == NULL) { 234 vxge_hal_err_log_pool( 235 "%s:%d null pointer passed blockpool = null", 236 __FILE__, __LINE__); 237 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 1", 238 __FILE__, __func__, __LINE__); 239 return; 240 } 241 242 vxge_list_for_each_safe(p, n, &blockpool->free_block_list) { 243 244 vxge_os_dma_unmap(hldev->header.pdev, 245 ((__hal_blockpool_entry_t *) p)->dma_handle, 246 ((__hal_blockpool_entry_t *) p)->dma_addr, 247 ((__hal_blockpool_entry_t *) p)->length, 248 VXGE_OS_DMA_DIR_BIDIRECTIONAL); 249 250 vxge_os_dma_free(hldev->header.pdev, 251 ((__hal_blockpool_entry_t *) p)->memblock, 252 ((__hal_blockpool_entry_t *) p)->length, 253 blockpool->dma_flags, 254 &((__hal_blockpool_entry_t *) p)->dma_handle, 255 &((__hal_blockpool_entry_t *) p)->acc_handle); 256 257 vxge_list_remove(&((__hal_blockpool_entry_t *) p)->item); 258 259 vxge_os_free(hldev->header.pdev, 260 (void *)p, sizeof(__hal_blockpool_entry_t)); 261 262 blockpool->pool_size--; 263 } 264 265 vxge_list_for_each_safe(p, n, &blockpool->free_entry_list) { 266 267 vxge_list_remove(&((__hal_blockpool_entry_t *) p)->item); 268 269 vxge_os_free(hldev->header.pdev, 270 (void *)p, sizeof(__hal_blockpool_entry_t)); 271 272 } 273 274#if defined(VXGE_HAL_BP_POST) 275 vxge_os_spin_lock_destroy(&blockpool->pool_lock, 276 hldev->header.pdev); 277#elif defined(VXGE_HAL_BP_POST_IRQ) 278 vxge_os_spin_lock_destroy_irq(&blockpool->pool_lock, 279 hldev->header.pdev); 280#endif 281 282 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 0", 283 __FILE__, __func__, __LINE__); 284} 285 286/* 287 * __hal_blockpool_blocks_add - Request additional blocks 288 * @blockpool: Block pool. 289 * 290 * Requests additional blocks to block pool 291 */ 292static inline void 293__hal_blockpool_blocks_add( 294 __hal_blockpool_t * blockpool) 295{ 296 u32 nreq = 0, i; 297 __hal_device_t *hldev; 298 299 vxge_assert(blockpool != NULL); 300 301 hldev = (__hal_device_t *) blockpool->hldev; 302 303 vxge_hal_trace_log_pool("==> %s:%s:%d", 304 __FILE__, __func__, __LINE__); 305 306 vxge_hal_trace_log_pool("blockpool = 0x"VXGE_OS_STXFMT, 307 (ptr_t) blockpool); 308 309#if defined(VXGE_HAL_BP_POST) 310 vxge_os_spin_lock(&blockpool->pool_lock); 311#elif defined(VXGE_HAL_BP_POST_IRQ) 312 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 313#endif 314 if ((blockpool->pool_size + blockpool->req_out) < 315 blockpool->pool_min) { 316 nreq = blockpool->pool_incr; 317 blockpool->req_out += nreq; 318 } 319 320#if defined(VXGE_HAL_BP_POST) 321 vxge_os_spin_unlock(&blockpool->pool_lock); 322#elif defined(VXGE_HAL_BP_POST_IRQ) 323 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 324#endif 325 326 for (i = 0; i < nreq; i++) { 327 vxge_os_dma_malloc_async( 328 ((__hal_device_t *) blockpool->hldev)->header.pdev, 329 blockpool->hldev, 330 VXGE_OS_HOST_PAGE_SIZE, 331 blockpool->dma_flags); 332 } 333 334 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 0", 335 __FILE__, __func__, __LINE__); 336} 337 338/* 339 * __hal_blockpool_blocks_remove - Free additional blocks 340 * @blockpool: Block pool. 341 * 342 * Frees additional blocks over maximum from the block pool 343 */ 344static inline void 345__hal_blockpool_blocks_remove( 346 __hal_blockpool_t * blockpool) 347{ 348 vxge_list_t *p, *n; 349 __hal_device_t *hldev; 350 351 vxge_assert(blockpool != NULL); 352 353 hldev = (__hal_device_t *) blockpool->hldev; 354 355 vxge_hal_trace_log_pool("==> %s:%s:%d", 356 __FILE__, __func__, __LINE__); 357 358 vxge_hal_trace_log_pool("blockpool = 0x"VXGE_OS_STXFMT, 359 (ptr_t) blockpool); 360 361#if defined(VXGE_HAL_BP_POST) 362 vxge_os_spin_lock(&blockpool->pool_lock); 363#elif defined(VXGE_HAL_BP_POST_IRQ) 364 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 365#endif 366 vxge_list_for_each_safe(p, n, &blockpool->free_block_list) { 367 368 if (blockpool->pool_size < blockpool->pool_max) 369 break; 370 371 vxge_os_dma_unmap( 372 ((__hal_device_t *) blockpool->hldev)->header.pdev, 373 ((__hal_blockpool_entry_t *) p)->dma_handle, 374 ((__hal_blockpool_entry_t *) p)->dma_addr, 375 ((__hal_blockpool_entry_t *) p)->length, 376 VXGE_OS_DMA_DIR_BIDIRECTIONAL); 377 378 vxge_os_dma_free( 379 ((__hal_device_t *) blockpool->hldev)->header.pdev, 380 ((__hal_blockpool_entry_t *) p)->memblock, 381 ((__hal_blockpool_entry_t *) p)->length, 382 blockpool->dma_flags, 383 &((__hal_blockpool_entry_t *) p)->dma_handle, 384 &((__hal_blockpool_entry_t *) p)->acc_handle); 385 386 vxge_list_remove(&((__hal_blockpool_entry_t *) p)->item); 387 388 vxge_list_insert(p, &blockpool->free_entry_list); 389 390 blockpool->pool_size--; 391 392 } 393 394#if defined(VXGE_HAL_BP_POST) 395 vxge_os_spin_unlock(&blockpool->pool_lock); 396#elif defined(VXGE_HAL_BP_POST_IRQ) 397 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 398#endif 399 400 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 0", 401 __FILE__, __func__, __LINE__); 402} 403 404/* 405 * vxge_hal_blockpool_block_add - callback for vxge_os_dma_malloc_async 406 * @devh: HAL device handle. 407 * @block_addr: Virtual address of the block 408 * @length: Length of the block. 409 * @p_dma_h: Physical address of the block 410 * @acc_handle: DMA acc handle 411 * 412 * Adds a block to block pool 413 */ 414void 415vxge_hal_blockpool_block_add( 416 vxge_hal_device_h devh, 417 void *block_addr, 418 u32 length, 419 pci_dma_h * dma_h, 420 pci_dma_acc_h * acc_handle) 421{ 422 __hal_blockpool_t *blockpool; 423 __hal_blockpool_entry_t *entry; 424 __hal_device_t *hldev; 425 dma_addr_t dma_addr; 426 vxge_hal_status_e status; 427 u32 req_out; 428 429 vxge_assert(devh != NULL); 430 431 hldev = (__hal_device_t *) devh; 432 433 vxge_hal_trace_log_pool("==> %s:%s:%d", 434 __FILE__, __func__, __LINE__); 435 436 vxge_hal_trace_log_pool("devh = 0x"VXGE_OS_STXFMT", length = %d, " 437 "block_addr = 0x"VXGE_OS_STXFMT", dma_h = 0x"VXGE_OS_STXFMT", " 438 "acc_handle = 0x"VXGE_OS_STXFMT, (ptr_t) devh, length, 439 (ptr_t) block_addr, (ptr_t) dma_h, (ptr_t) acc_handle); 440 441 blockpool = &hldev->block_pool; 442 443 if (block_addr == NULL) { 444#if defined(VXGE_HAL_BP_POST) 445 vxge_os_spin_lock(&blockpool->pool_lock); 446#elif defined(VXGE_HAL_BP_POST_IRQ) 447 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 448#endif 449 blockpool->req_out--; 450 451#if defined(VXGE_HAL_BP_POST) 452 vxge_os_spin_unlock(&blockpool->pool_lock); 453#elif defined(VXGE_HAL_BP_POST_IRQ) 454 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 455#endif 456 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 1", 457 __FILE__, __func__, __LINE__); 458 return; 459 } 460 461 dma_addr = vxge_os_dma_map(hldev->header.pdev, 462 *dma_h, 463 block_addr, 464 length, 465 VXGE_OS_DMA_DIR_BIDIRECTIONAL, 466 blockpool->dma_flags); 467 468 if (dma_addr == VXGE_OS_INVALID_DMA_ADDR) { 469 vxge_os_dma_free(hldev->header.pdev, 470 block_addr, 471 length, 472 blockpool->dma_flags, 473 dma_h, 474 acc_handle); 475#if defined(VXGE_HAL_BP_POST) 476 vxge_os_spin_lock(&blockpool->pool_lock); 477#elif defined(VXGE_HAL_BP_POST_IRQ) 478 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 479#endif 480 blockpool->req_out--; 481 482#if defined(VXGE_HAL_BP_POST) 483 vxge_os_spin_unlock(&blockpool->pool_lock); 484#elif defined(VXGE_HAL_BP_POST_IRQ) 485 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 486#endif 487 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 1", 488 __FILE__, __func__, __LINE__); 489 return; 490 } 491 492#if defined(VXGE_HAL_BP_POST) 493 vxge_os_spin_lock(&blockpool->pool_lock); 494#elif defined(VXGE_HAL_BP_POST_IRQ) 495 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 496#endif 497 498 entry = (__hal_blockpool_entry_t *) 499 vxge_list_first_get(&blockpool->free_entry_list); 500 501 if (entry == NULL) { 502 entry = (__hal_blockpool_entry_t *) vxge_os_malloc( 503 hldev->header.pdev, 504 sizeof(__hal_blockpool_entry_t)); 505 } else { 506 vxge_list_remove(&entry->item); 507 } 508 509 if (entry != NULL) { 510 entry->length = length; 511 entry->memblock = block_addr; 512 entry->dma_addr = dma_addr; 513 entry->acc_handle = *acc_handle; 514 entry->dma_handle = *dma_h; 515 vxge_list_insert(&entry->item, &blockpool->free_block_list); 516 blockpool->pool_size++; 517 status = VXGE_HAL_OK; 518 } else { 519 status = VXGE_HAL_ERR_OUT_OF_MEMORY; 520 } 521 522 blockpool->req_out--; 523 524 req_out = blockpool->req_out; 525 526#if defined(VXGE_HAL_BP_POST) 527 vxge_os_spin_unlock(&blockpool->pool_lock); 528#elif defined(VXGE_HAL_BP_POST_IRQ) 529 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 530#endif 531 532 if (req_out == 0) 533 __hal_channel_process_pending_list(devh); 534 535 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 536 __FILE__, __func__, __LINE__, status); 537} 538 539/* 540 * __hal_blockpool_malloc - Allocate a memory block from pool 541 * @devh: HAL device handle. 542 * @size: Length of the block. 543 * @dma_addr: Buffer to return DMA Address of the block. 544 * @dma_handle: Buffer to return DMA handle of the block. 545 * @acc_handle: Buffer to return DMA acc handle 546 * 547 * 548 * Allocates a block of memory of given size, either from block pool 549 * or by calling vxge_os_dma_malloc() 550 */ 551void * 552__hal_blockpool_malloc(vxge_hal_device_h devh, 553 u32 size, 554 dma_addr_t *dma_addr, 555 pci_dma_h *dma_handle, 556 pci_dma_acc_h *acc_handle) 557{ 558 __hal_blockpool_entry_t *entry; 559 __hal_blockpool_t *blockpool; 560 __hal_device_t *hldev; 561 void *memblock = NULL; 562 563 vxge_assert(devh != NULL); 564 565 hldev = (__hal_device_t *) devh; 566 567 vxge_hal_trace_log_pool("==> %s:%s:%d", 568 __FILE__, __func__, __LINE__); 569 570 vxge_hal_trace_log_pool( 571 "devh = 0x"VXGE_OS_STXFMT", size = %d, " 572 "dma_addr = 0x"VXGE_OS_STXFMT", dma_handle = 0x"VXGE_OS_STXFMT", " 573 "acc_handle = 0x"VXGE_OS_STXFMT, (ptr_t) devh, size, 574 (ptr_t) dma_addr, (ptr_t) dma_handle, (ptr_t) acc_handle); 575 576 blockpool = &((__hal_device_t *) devh)->block_pool; 577 578 if (size != blockpool->block_size) { 579 580 memblock = vxge_os_dma_malloc( 581 ((__hal_device_t *) devh)->header.pdev, 582 size, 583 blockpool->dma_flags | 584 VXGE_OS_DMA_CACHELINE_ALIGNED, 585 dma_handle, 586 acc_handle); 587 588 if (memblock == NULL) { 589 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 590 __FILE__, __func__, __LINE__, 591 VXGE_HAL_ERR_OUT_OF_MEMORY); 592 return (NULL); 593 } 594 595 *dma_addr = vxge_os_dma_map( 596 ((__hal_device_t *) devh)->header.pdev, 597 *dma_handle, 598 memblock, 599 size, 600 VXGE_OS_DMA_DIR_BIDIRECTIONAL, 601 blockpool->dma_flags); 602 603 if (*dma_addr == VXGE_OS_INVALID_DMA_ADDR) { 604 vxge_os_dma_free(((__hal_device_t *) devh)->header.pdev, 605 memblock, 606 size, 607 blockpool->dma_flags | 608 VXGE_OS_DMA_CACHELINE_ALIGNED, 609 dma_handle, 610 acc_handle); 611 612 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 613 __FILE__, __func__, __LINE__, 614 VXGE_HAL_ERR_OUT_OF_MEMORY); 615 616 return (NULL); 617 } 618 619 } else { 620 621#if defined(VXGE_HAL_BP_POST) 622 vxge_os_spin_lock(&blockpool->pool_lock); 623#elif defined(VXGE_HAL_BP_POST_IRQ) 624 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 625#endif 626 627 entry = (__hal_blockpool_entry_t *) 628 vxge_list_first_get(&blockpool->free_block_list); 629 630 if (entry != NULL) { 631 vxge_list_remove(&entry->item); 632 *dma_addr = entry->dma_addr; 633 *dma_handle = entry->dma_handle; 634 *acc_handle = entry->acc_handle; 635 memblock = entry->memblock; 636 637 vxge_list_insert(&entry->item, 638 &blockpool->free_entry_list); 639 blockpool->pool_size--; 640 } 641 642#if defined(VXGE_HAL_BP_POST) 643 vxge_os_spin_unlock(&blockpool->pool_lock); 644#elif defined(VXGE_HAL_BP_POST_IRQ) 645 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 646#endif 647 648 if (memblock != NULL) 649 __hal_blockpool_blocks_add(blockpool); 650 651 } 652 653 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 654 __FILE__, __func__, __LINE__, !memblock); 655 656 return (memblock); 657 658} 659 660/* 661 * __hal_blockpool_free - Frees the memory allcoated with __hal_blockpool_malloc 662 * @devh: HAL device handle. 663 * @memblock: Virtual address block 664 * @size: Length of the block. 665 * @dma_addr: DMA Address of the block. 666 * @dma_handle: DMA handle of the block. 667 * @acc_handle: DMA acc handle 668 * 669 * 670 * Frees the memory allocated with __hal_blockpool_malloc to blockpool or system 671 */ 672void 673__hal_blockpool_free(vxge_hal_device_h devh, 674 void *memblock, 675 u32 size, 676 dma_addr_t *dma_addr, 677 pci_dma_h *dma_handle, 678 pci_dma_acc_h *acc_handle) 679{ 680 __hal_blockpool_entry_t *entry; 681 __hal_blockpool_t *blockpool; 682 __hal_device_t *hldev; 683 vxge_hal_status_e status = VXGE_HAL_OK; 684 685 vxge_assert(devh != NULL); 686 687 hldev = (__hal_device_t *) devh; 688 689 vxge_hal_trace_log_pool("==> %s:%s:%d", 690 __FILE__, __func__, __LINE__); 691 692 vxge_hal_trace_log_pool("devh = 0x"VXGE_OS_STXFMT", size = %d, " 693 "dma_addr = 0x"VXGE_OS_STXFMT", dma_handle = 0x"VXGE_OS_STXFMT", " 694 "acc_handle = 0x"VXGE_OS_STXFMT, (ptr_t) devh, size, 695 (ptr_t) dma_addr, (ptr_t) dma_handle, (ptr_t) acc_handle); 696 697 blockpool = &((__hal_device_t *) devh)->block_pool; 698 699 if (size != blockpool->block_size) { 700 701 vxge_os_dma_unmap(((__hal_device_t *) devh)->header.pdev, 702 *dma_handle, 703 *dma_addr, 704 size, 705 VXGE_OS_DMA_DIR_BIDIRECTIONAL); 706 707 vxge_os_dma_free(((__hal_device_t *) devh)->header.pdev, 708 memblock, 709 size, 710 blockpool->dma_flags | 711 VXGE_OS_DMA_CACHELINE_ALIGNED, 712 dma_handle, 713 acc_handle); 714 } else { 715#if defined(VXGE_HAL_BP_POST) 716 vxge_os_spin_lock(&blockpool->pool_lock); 717#elif defined(VXGE_HAL_BP_POST_IRQ) 718 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 719#endif 720 721 entry = (__hal_blockpool_entry_t *) 722 vxge_list_first_get(&blockpool->free_entry_list); 723 724 if (entry == NULL) { 725 entry = (__hal_blockpool_entry_t *) vxge_os_malloc( 726 ((__hal_device_t *) devh)->header.pdev, 727 sizeof(__hal_blockpool_entry_t)); 728 } else { 729 vxge_list_remove(&entry->item); 730 } 731 732 if (entry != NULL) { 733 entry->length = size; 734 entry->memblock = memblock; 735 entry->dma_addr = *dma_addr; 736 entry->acc_handle = *acc_handle; 737 entry->dma_handle = *dma_handle; 738 vxge_list_insert(&entry->item, 739 &blockpool->free_block_list); 740 blockpool->pool_size++; 741 status = VXGE_HAL_OK; 742 } else { 743 status = VXGE_HAL_ERR_OUT_OF_MEMORY; 744 } 745 746#if defined(VXGE_HAL_BP_POST) 747 vxge_os_spin_unlock(&blockpool->pool_lock); 748#elif defined(VXGE_HAL_BP_POST_IRQ) 749 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 750#endif 751 if (status == VXGE_HAL_OK) 752 __hal_blockpool_blocks_remove(blockpool); 753 754 } 755 756 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 757 __FILE__, __func__, __LINE__, status); 758} 759 760/* 761 * __hal_blockpool_block_allocate - Allocates a block from block pool 762 * @hldev: Hal device 763 * @size: Size of the block to be allocated 764 * 765 * This function allocates a block from block pool or from the system 766 */ 767__hal_blockpool_entry_t * 768__hal_blockpool_block_allocate(vxge_hal_device_h devh, 769 u32 size) 770{ 771 __hal_blockpool_entry_t *entry = NULL; 772 __hal_device_t *hldev; 773 __hal_blockpool_t *blockpool; 774 775 vxge_assert(devh != NULL); 776 777 hldev = (__hal_device_t *) devh; 778 779 vxge_hal_trace_log_pool("==> %s:%s:%d", 780 __FILE__, __func__, __LINE__); 781 782 vxge_hal_trace_log_pool("devh = 0x"VXGE_OS_STXFMT", size = %d", 783 (ptr_t) devh, size); 784 785 blockpool = &((__hal_device_t *) devh)->block_pool; 786 787 if (size == blockpool->block_size) { 788#if defined(VXGE_HAL_BP_POST) 789 vxge_os_spin_lock(&blockpool->pool_lock); 790#elif defined(VXGE_HAL_BP_POST_IRQ) 791 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 792#endif 793 794 entry = (__hal_blockpool_entry_t *) 795 vxge_list_first_get(&blockpool->free_block_list); 796 797 if (entry != NULL) { 798 vxge_list_remove(&entry->item); 799 blockpool->pool_size--; 800 } 801 802#if defined(VXGE_HAL_BP_POST) 803 vxge_os_spin_unlock(&blockpool->pool_lock); 804#elif defined(VXGE_HAL_BP_POST_IRQ) 805 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 806#endif 807 } 808 809 if (entry != NULL) 810 __hal_blockpool_blocks_add(blockpool); 811 812 813 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 814 __FILE__, __func__, __LINE__, !entry); 815 816 return (entry); 817} 818 819/* 820 * __hal_blockpool_block_free - Frees a block from block pool 821 * @devh: Hal device 822 * @entry: Entry of block to be freed 823 * 824 * This function frees a block from block pool 825 */ 826void 827__hal_blockpool_block_free(vxge_hal_device_h devh, 828 __hal_blockpool_entry_t *entry) 829{ 830 __hal_device_t *hldev; 831 __hal_blockpool_t *blockpool; 832 833 vxge_assert(devh != NULL); 834 835 hldev = (__hal_device_t *) devh; 836 837 vxge_hal_trace_log_pool("==> %s:%s:%d", 838 __FILE__, __func__, __LINE__); 839 840 vxge_hal_trace_log_pool( 841 "devh = 0x"VXGE_OS_STXFMT", entry = 0x"VXGE_OS_STXFMT, 842 (ptr_t) devh, (ptr_t) entry); 843 844 blockpool = &((__hal_device_t *) devh)->block_pool; 845 846 if (entry->length == blockpool->block_size) { 847#if defined(VXGE_HAL_BP_POST) 848 vxge_os_spin_lock(&blockpool->pool_lock); 849#elif defined(VXGE_HAL_BP_POST_IRQ) 850 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 851#endif 852 853 vxge_list_insert(&entry->item, &blockpool->free_block_list); 854 blockpool->pool_size++; 855 856#if defined(VXGE_HAL_BP_POST) 857 vxge_os_spin_unlock(&blockpool->pool_lock); 858#elif defined(VXGE_HAL_BP_POST_IRQ) 859 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 860#endif 861 } 862 863 __hal_blockpool_blocks_remove(blockpool); 864 865 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 0", 866 __FILE__, __func__, __LINE__); 867} 868 869 870/* 871 * __hal_blockpool_list_allocate - Allocate blocks from block pool 872 * @devh: Hal device 873 * @blocklist: List into which the allocated blocks to be inserted 874 * @count: Number of blocks to be allocated 875 * 876 * This function allocates a register from the register pool 877 */ 878vxge_hal_status_e 879__hal_blockpool_list_allocate( 880 vxge_hal_device_h devh, 881 vxge_list_t *blocklist, 882 u32 count) 883{ 884 u32 i; 885 __hal_device_t *hldev; 886 __hal_blockpool_t *blockpool; 887 __hal_blockpool_entry_t *block_entry; 888 vxge_hal_status_e status = VXGE_HAL_OK; 889 890 vxge_assert(devh != NULL); 891 892 hldev = (__hal_device_t *) devh; 893 894 vxge_hal_trace_log_pool("==> %s:%s:%d", 895 __FILE__, __func__, __LINE__); 896 897 vxge_hal_trace_log_pool("devh = 0x"VXGE_OS_STXFMT", blocklist = " 898 "0x"VXGE_OS_STXFMT", count = %d", (ptr_t) devh, 899 (ptr_t) blocklist, count); 900 901 blockpool = &((__hal_device_t *) devh)->block_pool; 902 903 if (blocklist == NULL) { 904 vxge_hal_err_log_pool( 905 "null pointer passed blockpool = 0x"VXGE_OS_STXFMT", " 906 "blocklist = 0x"VXGE_OS_STXFMT, (ptr_t) blockpool, 907 (ptr_t) blocklist); 908 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 1", 909 __FILE__, __func__, __LINE__); 910 return (VXGE_HAL_FAIL); 911 } 912 913#if defined(VXGE_HAL_BP_POST) 914 vxge_os_spin_lock(&blockpool->pool_lock); 915#elif defined(VXGE_HAL_BP_POST_IRQ) 916 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 917#endif 918 919 vxge_list_init(blocklist); 920 921 for (i = 0; i < count; i++) { 922 923 block_entry = (__hal_blockpool_entry_t *) 924 vxge_list_first_get(&blockpool->free_block_list); 925 926 if (block_entry == NULL) 927 break; 928 929 vxge_list_remove(&block_entry->item); 930 931 vxge_os_memzero(block_entry->memblock, blockpool->block_size); 932 933 vxge_list_insert(&block_entry->item, blocklist); 934 935 blockpool->pool_size++; 936 } 937 938#if defined(VXGE_HAL_BP_POST) 939 vxge_os_spin_unlock(&blockpool->pool_lock); 940#elif defined(VXGE_HAL_BP_POST_IRQ) 941 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 942#endif 943 944 if (i < count) { 945 946 vxge_hal_err_log_pool("%s:%d Blockpool out of blocks", 947 __FILE__, __LINE__); 948 949 vxge_assert(FALSE); 950 951 __hal_blockpool_list_free(blockpool, blocklist); 952 953 status = VXGE_HAL_ERR_OUT_OF_MEMORY; 954 955 } 956 957 __hal_blockpool_blocks_add(blockpool); 958 959 vxge_hal_trace_log_pool("<== %s:%s:%d Result: %d", 960 __FILE__, __func__, __LINE__, status); 961 962 return (status); 963} 964 965/* 966 * __hal_blockpool_list_free - Free a list of blocks from block pool 967 * @devh: Hal device 968 * @blocklist: List of blocks to be freed 969 * 970 * This function frees a list of blocks to the block pool 971 */ 972void 973__hal_blockpool_list_free( 974 vxge_hal_device_h devh, 975 vxge_list_t *blocklist) 976{ 977 __hal_device_t *hldev; 978 __hal_blockpool_t *blockpool; 979 __hal_blockpool_entry_t *block_entry; 980 981 vxge_assert(devh != NULL); 982 983 hldev = (__hal_device_t *) devh; 984 985 vxge_hal_trace_log_pool("==> %s:%s:%d", 986 __FILE__, __func__, __LINE__); 987 988 vxge_hal_trace_log_pool( 989 "devh = 0x"VXGE_OS_STXFMT", blocklist = 0x"VXGE_OS_STXFMT, 990 (ptr_t) devh, (ptr_t) blocklist); 991 992 blockpool = &((__hal_device_t *) devh)->block_pool; 993 994 if (blocklist == NULL) { 995 vxge_hal_err_log_pool( 996 "null pointer passed blockpool = 0x"VXGE_OS_STXFMT", " 997 "blocklist = 0x"VXGE_OS_STXFMT, (ptr_t) blockpool, 998 (ptr_t) blocklist); 999 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 1", 1000 __FILE__, __func__, __LINE__); 1001 return; 1002 } 1003 1004#if defined(VXGE_HAL_BP_POST) 1005 vxge_os_spin_lock(&blockpool->pool_lock); 1006#elif defined(VXGE_HAL_BP_POST_IRQ) 1007 vxge_os_spin_lock_irq(&blockpool->pool_lock, flags); 1008#endif 1009 1010 while ((block_entry = (__hal_blockpool_entry_t *) 1011 vxge_list_first_get(blocklist)) != NULL) { 1012 1013 vxge_list_remove(&block_entry->item); 1014 1015 vxge_list_insert(&block_entry->item, 1016 &blockpool->free_block_list); 1017 1018 blockpool->pool_size++; 1019 } 1020 1021#if defined(VXGE_HAL_BP_POST) 1022 vxge_os_spin_unlock(&blockpool->pool_lock); 1023#elif defined(VXGE_HAL_BP_POST_IRQ) 1024 vxge_os_spin_unlock_irq(&blockpool->pool_lock, flags); 1025#endif 1026 1027 __hal_blockpool_blocks_remove(blockpool); 1028 1029 vxge_hal_trace_log_pool("<== %s:%s:%d Result: 0", 1030 __FILE__, __func__, __LINE__); 1031} 1032