1221167Sgnn/*- 2221167Sgnn * Copyright(c) 2002-2011 Exar Corp. 3221167Sgnn * All rights reserved. 4221167Sgnn * 5221167Sgnn * Redistribution and use in source and binary forms, with or without 6221167Sgnn * modification are permitted provided the following conditions are met: 7221167Sgnn * 8221167Sgnn * 1. Redistributions of source code must retain the above copyright notice, 9221167Sgnn * this list of conditions and the following disclaimer. 10221167Sgnn * 11221167Sgnn * 2. Redistributions in binary form must reproduce the above copyright 12221167Sgnn * notice, this list of conditions and the following disclaimer in the 13221167Sgnn * documentation and/or other materials provided with the distribution. 14221167Sgnn * 15221167Sgnn * 3. Neither the name of the Exar Corporation nor the names of its 16221167Sgnn * contributors may be used to endorse or promote products derived from 17221167Sgnn * this software without specific prior written permission. 18221167Sgnn * 19221167Sgnn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20221167Sgnn * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21221167Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22221167Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23221167Sgnn * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24221167Sgnn * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25221167Sgnn * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26221167Sgnn * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27221167Sgnn * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28221167Sgnn * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29221167Sgnn * POSSIBILITY OF SUCH DAMAGE. 30221167Sgnn */ 31221167Sgnn/*$FreeBSD$*/ 32221167Sgnn 33221167Sgnn#include <dev/vxge/vxgehal/vxgehal.h> 34221167Sgnn 35221167Sgnn/* 36221167Sgnn * __hal_mempool_grow 37221167Sgnn * 38221167Sgnn * Will resize mempool up to %num_allocate value. 39221167Sgnn */ 40221167Sgnnstatic vxge_hal_status_e 41221167Sgnn__hal_mempool_grow( 42221167Sgnn vxge_hal_mempool_t *mempool, 43221167Sgnn u32 num_allocate, 44221167Sgnn u32 *num_allocated) 45221167Sgnn{ 46221167Sgnn u32 i, j, k, item_index, is_last; 47221167Sgnn u32 first_time = mempool->memblocks_allocated == 0 ? 1 : 0; 48221167Sgnn u32 n_items = mempool->items_per_memblock; 49221167Sgnn u32 start_block_idx = mempool->memblocks_allocated; 50221167Sgnn u32 end_block_idx = mempool->memblocks_allocated + num_allocate; 51221167Sgnn __hal_device_t *hldev; 52221167Sgnn 53221167Sgnn vxge_assert(mempool != NULL); 54221167Sgnn 55221167Sgnn hldev = (__hal_device_t *) mempool->devh; 56221167Sgnn 57221167Sgnn vxge_hal_trace_log_mm("==> %s:%s:%d", 58221167Sgnn __FILE__, __func__, __LINE__); 59221167Sgnn 60221167Sgnn vxge_hal_trace_log_mm( 61221167Sgnn "mempool = 0x"VXGE_OS_STXFMT", num_allocate = %d, " 62221167Sgnn "num_allocated = 0x"VXGE_OS_STXFMT, (ptr_t) mempool, 63221167Sgnn num_allocate, (ptr_t) num_allocated); 64221167Sgnn 65221167Sgnn *num_allocated = 0; 66221167Sgnn 67221167Sgnn if (end_block_idx > mempool->memblocks_max) { 68221167Sgnn vxge_hal_err_log_mm("%s", 69221167Sgnn "__hal_mempool_grow: can grow anymore"); 70221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 71221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 72221167Sgnn return (VXGE_HAL_ERR_OUT_OF_MEMORY); 73221167Sgnn } 74221167Sgnn 75221167Sgnn for (i = start_block_idx; i < end_block_idx; i++) { 76221167Sgnn 77221167Sgnn void *the_memblock; 78221167Sgnn vxge_hal_mempool_dma_t *dma_object; 79221167Sgnn 80221167Sgnn is_last = ((end_block_idx - 1) == i); 81221167Sgnn dma_object = mempool->memblocks_dma_arr + i; 82221167Sgnn 83221167Sgnn /* 84221167Sgnn * allocate memblock's private part. Each DMA memblock 85221167Sgnn * has a space allocated for item's private usage upon 86221167Sgnn * mempool's user request. Each time mempool grows, it will 87221167Sgnn * allocate new memblock and its private part at once. 88221167Sgnn * This helps to minimize memory usage a lot. 89221167Sgnn */ 90221167Sgnn mempool->memblocks_priv_arr[i] = vxge_os_malloc( 91221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 92221167Sgnn mempool->items_priv_size * n_items); 93221167Sgnn if (mempool->memblocks_priv_arr[i] == NULL) { 94221167Sgnn 95221167Sgnn vxge_hal_err_log_mm("memblock_priv[%d]: \ 96221167Sgnn out of virtual memory, " 97221167Sgnn "requested %d(%d:%d) bytes", i, 98221167Sgnn mempool->items_priv_size * n_items, 99221167Sgnn mempool->items_priv_size, n_items); 100221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 101221167Sgnn __FILE__, __func__, __LINE__, 102221167Sgnn VXGE_HAL_ERR_OUT_OF_MEMORY); 103221167Sgnn return (VXGE_HAL_ERR_OUT_OF_MEMORY); 104221167Sgnn 105221167Sgnn } 106221167Sgnn 107221167Sgnn vxge_os_memzero(mempool->memblocks_priv_arr[i], 108221167Sgnn mempool->items_priv_size * n_items); 109221167Sgnn 110221167Sgnn /* allocate DMA-capable memblock */ 111221167Sgnn mempool->memblocks_arr[i] = 112221167Sgnn __hal_blockpool_malloc(mempool->devh, 113221167Sgnn mempool->memblock_size, 114221167Sgnn &dma_object->addr, 115221167Sgnn &dma_object->handle, 116221167Sgnn &dma_object->acc_handle); 117221167Sgnn if (mempool->memblocks_arr[i] == NULL) { 118221167Sgnn vxge_os_free( 119221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 120221167Sgnn mempool->memblocks_priv_arr[i], 121221167Sgnn mempool->items_priv_size * n_items); 122221167Sgnn vxge_hal_err_log_mm("memblock[%d]: \ 123221167Sgnn out of DMA memory", i); 124221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 125221167Sgnn __FILE__, __func__, __LINE__, 126221167Sgnn VXGE_HAL_ERR_OUT_OF_MEMORY); 127221167Sgnn return (VXGE_HAL_ERR_OUT_OF_MEMORY); 128221167Sgnn } 129221167Sgnn 130221167Sgnn (*num_allocated)++; 131221167Sgnn mempool->memblocks_allocated++; 132221167Sgnn 133221167Sgnn vxge_os_memzero(mempool->memblocks_arr[i], 134221167Sgnn mempool->memblock_size); 135221167Sgnn 136221167Sgnn the_memblock = mempool->memblocks_arr[i]; 137221167Sgnn 138221167Sgnn /* fill the items hash array */ 139221167Sgnn for (j = 0; j < n_items; j++) { 140221167Sgnn item_index = i * n_items + j; 141221167Sgnn 142221167Sgnn if (first_time && (item_index >= mempool->items_initial)) 143221167Sgnn break; 144221167Sgnn 145221167Sgnn mempool->items_arr[item_index] = 146221167Sgnn ((char *) the_memblock + j *mempool->item_size); 147221167Sgnn 148221167Sgnn /* let caller to do more job on each item */ 149221167Sgnn if (mempool->item_func_alloc != NULL) { 150221167Sgnn vxge_hal_status_e status; 151221167Sgnn 152221167Sgnn if ((status = mempool->item_func_alloc( 153221167Sgnn mempool, 154221167Sgnn the_memblock, 155221167Sgnn i, 156221167Sgnn dma_object, 157221167Sgnn mempool->items_arr[item_index], 158221167Sgnn item_index, 159221167Sgnn is_last, 160221167Sgnn mempool->userdata)) != VXGE_HAL_OK) { 161221167Sgnn 162221167Sgnn if (mempool->item_func_free != NULL) { 163221167Sgnn 164221167Sgnn for (k = 0; k < j; k++) { 165221167Sgnn 166221167Sgnn item_index = i * n_items + k; 167221167Sgnn 168221167Sgnn (void) mempool->item_func_free( 169221167Sgnn mempool, 170221167Sgnn the_memblock, 171221167Sgnn i, dma_object, 172221167Sgnn mempool->items_arr[item_index], 173221167Sgnn item_index, is_last, 174221167Sgnn mempool->userdata); 175221167Sgnn } 176221167Sgnn } 177221167Sgnn 178221167Sgnn vxge_os_free(((__hal_device_t *) 179221167Sgnn mempool->devh)->header.pdev, 180221167Sgnn mempool->memblocks_priv_arr[i], 181221167Sgnn mempool->items_priv_size * 182221167Sgnn n_items); 183221167Sgnn 184221167Sgnn __hal_blockpool_free(mempool->devh, 185221167Sgnn the_memblock, 186221167Sgnn mempool->memblock_size, 187221167Sgnn &dma_object->addr, 188221167Sgnn &dma_object->handle, 189221167Sgnn &dma_object->acc_handle); 190221167Sgnn 191221167Sgnn (*num_allocated)--; 192221167Sgnn mempool->memblocks_allocated--; 193221167Sgnn return (status); 194221167Sgnn } 195221167Sgnn } 196221167Sgnn 197221167Sgnn mempool->items_current = item_index + 1; 198221167Sgnn } 199221167Sgnn 200221167Sgnn vxge_hal_info_log_mm( 201221167Sgnn "memblock%d: allocated %dk, vaddr 0x"VXGE_OS_STXFMT", " 202221167Sgnn "dma_addr 0x"VXGE_OS_STXFMT, 203221167Sgnn i, mempool->memblock_size / 1024, 204221167Sgnn (ptr_t) mempool->memblocks_arr[i], dma_object->addr); 205221167Sgnn 206221167Sgnn if (first_time && mempool->items_current == 207221167Sgnn mempool->items_initial) { 208221167Sgnn break; 209221167Sgnn } 210221167Sgnn } 211221167Sgnn 212221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: 0", 213221167Sgnn __FILE__, __func__, __LINE__); 214221167Sgnn 215221167Sgnn return (VXGE_HAL_OK); 216221167Sgnn} 217221167Sgnn 218221167Sgnn/* 219221167Sgnn * vxge_hal_mempool_create 220221167Sgnn * @memblock_size: 221221167Sgnn * @items_initial: 222221167Sgnn * @items_max: 223221167Sgnn * @item_size: 224221167Sgnn * @item_func: 225221167Sgnn * 226221167Sgnn * This function will create memory pool object. Pool may grow but will 227221167Sgnn * never shrink. Pool consists of number of dynamically allocated blocks 228221167Sgnn * with size enough to hold %items_initial number of items. Memory is 229221167Sgnn * DMA-able but client must map/unmap before interoperating with the device. 230221167Sgnn * See also: vxge_os_dma_map(), vxge_hal_dma_unmap(), vxge_hal_status_e {}. 231221167Sgnn */ 232221167Sgnnvxge_hal_mempool_t * 233221167Sgnnvxge_hal_mempool_create( 234221167Sgnn vxge_hal_device_h devh, 235221167Sgnn u32 memblock_size, 236221167Sgnn u32 item_size, 237221167Sgnn u32 items_priv_size, 238221167Sgnn u32 items_initial, 239221167Sgnn u32 items_max, 240221167Sgnn vxge_hal_mempool_item_f item_func_alloc, 241221167Sgnn vxge_hal_mempool_item_f item_func_free, 242221167Sgnn void *userdata) 243221167Sgnn{ 244221167Sgnn vxge_hal_status_e status; 245221167Sgnn u32 memblocks_to_allocate; 246221167Sgnn vxge_hal_mempool_t *mempool; 247221167Sgnn __hal_device_t *hldev; 248221167Sgnn u32 allocated; 249221167Sgnn 250221167Sgnn vxge_assert(devh != NULL); 251221167Sgnn 252221167Sgnn hldev = (__hal_device_t *) devh; 253221167Sgnn 254221167Sgnn vxge_hal_trace_log_mm("==> %s:%s:%d", 255221167Sgnn __FILE__, __func__, __LINE__); 256221167Sgnn 257221167Sgnn vxge_hal_trace_log_mm( 258221167Sgnn "devh = 0x"VXGE_OS_STXFMT", memblock_size = %d, item_size = %d, " 259221167Sgnn "items_priv_size = %d, items_initial = %d, items_max = %d, " 260221167Sgnn "item_func_alloc = 0x"VXGE_OS_STXFMT", " 261221167Sgnn "item_func_free = 0x"VXGE_OS_STXFMT", " 262221167Sgnn "userdata = 0x"VXGE_OS_STXFMT, (ptr_t) devh, 263221167Sgnn memblock_size, item_size, items_priv_size, 264221167Sgnn items_initial, items_max, (ptr_t) item_func_alloc, 265221167Sgnn (ptr_t) item_func_free, (ptr_t) userdata); 266221167Sgnn 267221167Sgnn if (memblock_size < item_size) { 268221167Sgnn vxge_hal_err_log_mm( 269221167Sgnn "memblock_size %d < item_size %d: misconfiguration", 270221167Sgnn memblock_size, item_size); 271221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 272221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_FAIL); 273221167Sgnn return (NULL); 274221167Sgnn } 275221167Sgnn 276221167Sgnn mempool = (vxge_hal_mempool_t *) vxge_os_malloc( 277221167Sgnn ((__hal_device_t *) devh)->header.pdev, sizeof(vxge_hal_mempool_t)); 278221167Sgnn if (mempool == NULL) { 279221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 280221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 281221167Sgnn return (NULL); 282221167Sgnn } 283221167Sgnn vxge_os_memzero(mempool, sizeof(vxge_hal_mempool_t)); 284221167Sgnn 285221167Sgnn mempool->devh = devh; 286221167Sgnn mempool->memblock_size = memblock_size; 287221167Sgnn mempool->items_max = items_max; 288221167Sgnn mempool->items_initial = items_initial; 289221167Sgnn mempool->item_size = item_size; 290221167Sgnn mempool->items_priv_size = items_priv_size; 291221167Sgnn mempool->item_func_alloc = item_func_alloc; 292221167Sgnn mempool->item_func_free = item_func_free; 293221167Sgnn mempool->userdata = userdata; 294221167Sgnn 295221167Sgnn mempool->memblocks_allocated = 0; 296221167Sgnn 297221167Sgnn if (memblock_size != VXGE_OS_HOST_PAGE_SIZE) 298221167Sgnn mempool->dma_flags = VXGE_OS_DMA_CACHELINE_ALIGNED; 299221167Sgnn 300221167Sgnn#if defined(VXGE_HAL_DMA_CONSISTENT) 301221167Sgnn mempool->dma_flags |= VXGE_OS_DMA_CONSISTENT; 302221167Sgnn#else 303221167Sgnn mempool->dma_flags |= VXGE_OS_DMA_STREAMING; 304221167Sgnn#endif 305221167Sgnn 306221167Sgnn mempool->items_per_memblock = memblock_size / item_size; 307221167Sgnn 308221167Sgnn mempool->memblocks_max = (items_max + mempool->items_per_memblock - 1) / 309221167Sgnn mempool->items_per_memblock; 310221167Sgnn 311221167Sgnn /* allocate array of memblocks */ 312221167Sgnn mempool->memblocks_arr = (void **)vxge_os_malloc( 313221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 314221167Sgnn sizeof(void *) * mempool->memblocks_max); 315221167Sgnn if (mempool->memblocks_arr == NULL) { 316221167Sgnn vxge_hal_mempool_destroy(mempool); 317221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 318221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 319221167Sgnn return (NULL); 320221167Sgnn } 321221167Sgnn vxge_os_memzero(mempool->memblocks_arr, 322221167Sgnn sizeof(void *) * mempool->memblocks_max); 323221167Sgnn 324221167Sgnn /* allocate array of private parts of items per memblocks */ 325221167Sgnn mempool->memblocks_priv_arr = (void **)vxge_os_malloc( 326221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 327221167Sgnn sizeof(void *) * mempool->memblocks_max); 328221167Sgnn if (mempool->memblocks_priv_arr == NULL) { 329221167Sgnn vxge_hal_mempool_destroy(mempool); 330221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 331221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 332221167Sgnn return (NULL); 333221167Sgnn } 334221167Sgnn vxge_os_memzero(mempool->memblocks_priv_arr, 335221167Sgnn sizeof(void *) * mempool->memblocks_max); 336221167Sgnn 337221167Sgnn /* allocate array of memblocks DMA objects */ 338221167Sgnn mempool->memblocks_dma_arr = 339221167Sgnn (vxge_hal_mempool_dma_t *) vxge_os_malloc( 340221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 341221167Sgnn sizeof(vxge_hal_mempool_dma_t) * mempool->memblocks_max); 342221167Sgnn 343221167Sgnn if (mempool->memblocks_dma_arr == NULL) { 344221167Sgnn vxge_hal_mempool_destroy(mempool); 345221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 346221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 347221167Sgnn return (NULL); 348221167Sgnn } 349221167Sgnn vxge_os_memzero(mempool->memblocks_dma_arr, 350221167Sgnn sizeof(vxge_hal_mempool_dma_t) * mempool->memblocks_max); 351221167Sgnn 352221167Sgnn /* allocate hash array of items */ 353221167Sgnn mempool->items_arr = (void **)vxge_os_malloc( 354221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 355221167Sgnn sizeof(void *) * mempool->items_max); 356221167Sgnn if (mempool->items_arr == NULL) { 357221167Sgnn vxge_hal_mempool_destroy(mempool); 358221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 359221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 360221167Sgnn return (NULL); 361221167Sgnn } 362221167Sgnn vxge_os_memzero(mempool->items_arr, 363221167Sgnn sizeof(void *) * mempool->items_max); 364221167Sgnn 365221167Sgnn mempool->shadow_items_arr = (void **)vxge_os_malloc( 366221167Sgnn ((__hal_device_t *) mempool->devh)->header.pdev, 367221167Sgnn sizeof(void *) * mempool->items_max); 368221167Sgnn if (mempool->shadow_items_arr == NULL) { 369221167Sgnn vxge_hal_mempool_destroy(mempool); 370221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 371221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 372221167Sgnn return (NULL); 373221167Sgnn } 374221167Sgnn vxge_os_memzero(mempool->shadow_items_arr, 375221167Sgnn sizeof(void *) * mempool->items_max); 376221167Sgnn 377221167Sgnn /* calculate initial number of memblocks */ 378221167Sgnn memblocks_to_allocate = (mempool->items_initial + 379221167Sgnn mempool->items_per_memblock - 1) / 380221167Sgnn mempool->items_per_memblock; 381221167Sgnn 382221167Sgnn vxge_hal_info_log_mm("allocating %d memblocks, " 383221167Sgnn "%d items per memblock", memblocks_to_allocate, 384221167Sgnn mempool->items_per_memblock); 385221167Sgnn 386221167Sgnn /* pre-allocate the mempool */ 387221167Sgnn status = __hal_mempool_grow(mempool, memblocks_to_allocate, &allocated); 388221167Sgnn vxge_os_memcpy(mempool->shadow_items_arr, mempool->items_arr, 389221167Sgnn sizeof(void *) * mempool->items_max); 390221167Sgnn if (status != VXGE_HAL_OK) { 391221167Sgnn vxge_hal_mempool_destroy(mempool); 392221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: %d", 393221167Sgnn __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 394221167Sgnn return (NULL); 395221167Sgnn } 396221167Sgnn 397221167Sgnn vxge_hal_info_log_mm( 398221167Sgnn "total: allocated %dk of DMA-capable memory", 399221167Sgnn mempool->memblock_size * allocated / 1024); 400221167Sgnn 401221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: 0", 402221167Sgnn __FILE__, __func__, __LINE__); 403221167Sgnn 404221167Sgnn return (mempool); 405221167Sgnn} 406221167Sgnn 407221167Sgnn/* 408221167Sgnn * vxge_hal_mempool_destroy 409221167Sgnn */ 410221167Sgnnvoid 411221167Sgnnvxge_hal_mempool_destroy( 412221167Sgnn vxge_hal_mempool_t *mempool) 413221167Sgnn{ 414221167Sgnn u32 i, j, item_index; 415221167Sgnn __hal_device_t *hldev; 416221167Sgnn 417221167Sgnn vxge_assert(mempool != NULL); 418221167Sgnn 419221167Sgnn hldev = (__hal_device_t *) mempool->devh; 420221167Sgnn 421221167Sgnn vxge_hal_trace_log_mm("==> %s:%s:%d", 422221167Sgnn __FILE__, __func__, __LINE__); 423221167Sgnn 424221167Sgnn vxge_hal_trace_log_mm("mempool = 0x"VXGE_OS_STXFMT, 425221167Sgnn (ptr_t) mempool); 426221167Sgnn 427221167Sgnn for (i = 0; i < mempool->memblocks_allocated; i++) { 428221167Sgnn vxge_hal_mempool_dma_t *dma_object; 429221167Sgnn 430221167Sgnn vxge_assert(mempool->memblocks_arr[i]); 431221167Sgnn vxge_assert(mempool->memblocks_dma_arr + i); 432221167Sgnn 433221167Sgnn dma_object = mempool->memblocks_dma_arr + i; 434221167Sgnn 435221167Sgnn for (j = 0; j < mempool->items_per_memblock; j++) { 436221167Sgnn item_index = i * mempool->items_per_memblock + j; 437221167Sgnn 438221167Sgnn /* to skip last partially filled(if any) memblock */ 439221167Sgnn if (item_index >= mempool->items_current) 440221167Sgnn break; 441221167Sgnn 442221167Sgnn /* let caller to do more job on each item */ 443221167Sgnn if (mempool->item_func_free != NULL) { 444221167Sgnn 445221167Sgnn mempool->item_func_free(mempool, 446221167Sgnn mempool->memblocks_arr[i], 447221167Sgnn i, dma_object, 448221167Sgnn mempool->shadow_items_arr[item_index], 449221167Sgnn item_index, /* unused */ -1, 450221167Sgnn mempool->userdata); 451221167Sgnn } 452221167Sgnn } 453221167Sgnn 454221167Sgnn vxge_os_free(hldev->header.pdev, 455221167Sgnn mempool->memblocks_priv_arr[i], 456221167Sgnn mempool->items_priv_size * mempool->items_per_memblock); 457221167Sgnn 458221167Sgnn __hal_blockpool_free(hldev, 459221167Sgnn mempool->memblocks_arr[i], 460221167Sgnn mempool->memblock_size, 461221167Sgnn &dma_object->addr, 462221167Sgnn &dma_object->handle, 463221167Sgnn &dma_object->acc_handle); 464221167Sgnn } 465221167Sgnn 466221167Sgnn if (mempool->items_arr) { 467221167Sgnn vxge_os_free(hldev->header.pdev, 468221167Sgnn mempool->items_arr, sizeof(void *) * mempool->items_max); 469221167Sgnn } 470221167Sgnn 471221167Sgnn if (mempool->shadow_items_arr) { 472221167Sgnn vxge_os_free(hldev->header.pdev, 473221167Sgnn mempool->shadow_items_arr, 474221167Sgnn sizeof(void *) * mempool->items_max); 475221167Sgnn } 476221167Sgnn 477221167Sgnn if (mempool->memblocks_dma_arr) { 478221167Sgnn vxge_os_free(hldev->header.pdev, 479221167Sgnn mempool->memblocks_dma_arr, 480221167Sgnn sizeof(vxge_hal_mempool_dma_t) * 481221167Sgnn mempool->memblocks_max); 482221167Sgnn } 483221167Sgnn 484221167Sgnn if (mempool->memblocks_priv_arr) { 485221167Sgnn vxge_os_free(hldev->header.pdev, 486221167Sgnn mempool->memblocks_priv_arr, 487221167Sgnn sizeof(void *) * mempool->memblocks_max); 488221167Sgnn } 489221167Sgnn 490221167Sgnn if (mempool->memblocks_arr) { 491221167Sgnn vxge_os_free(hldev->header.pdev, 492221167Sgnn mempool->memblocks_arr, 493221167Sgnn sizeof(void *) * mempool->memblocks_max); 494221167Sgnn } 495221167Sgnn 496221167Sgnn vxge_os_free(hldev->header.pdev, 497221167Sgnn mempool, sizeof(vxge_hal_mempool_t)); 498221167Sgnn 499221167Sgnn vxge_hal_trace_log_mm("<== %s:%s:%d Result: 0", 500221167Sgnn __FILE__, __func__, __LINE__); 501221167Sgnn} 502221167Sgnn 503221167Sgnn/* 504221167Sgnn * vxge_hal_check_alignment - Check buffer alignment and calculate the 505221167Sgnn * "misaligned" portion. 506221167Sgnn * @dma_pointer: DMA address of the buffer. 507221167Sgnn * @size: Buffer size, in bytes. 508221167Sgnn * @alignment: Alignment "granularity" (see below), in bytes. 509221167Sgnn * @copy_size: Maximum number of bytes to "extract" from the buffer 510221167Sgnn * (in order to spost it as a separate scatter-gather entry). See below. 511221167Sgnn * 512221167Sgnn * Check buffer alignment and calculate "misaligned" portion, if exists. 513221167Sgnn * The buffer is considered aligned if its address is multiple of 514221167Sgnn * the specified @alignment. If this is the case, 515221167Sgnn * vxge_hal_check_alignment() returns zero. 516221167Sgnn * Otherwise, vxge_hal_check_alignment() uses the last argument, 517221167Sgnn * @copy_size, 518221167Sgnn * to calculate the size to "extract" from the buffer. The @copy_size 519221167Sgnn * may or may not be equal @alignment. The difference between these two 520221167Sgnn * arguments is that the @alignment is used to make the decision: aligned 521221167Sgnn * or not aligned. While the @copy_size is used to calculate the portion 522221167Sgnn * of the buffer to "extract", i.e. to post as a separate entry in the 523221167Sgnn * transmit descriptor. For example, the combination 524221167Sgnn * @alignment = 8 and @copy_size = 64 will work okay on AMD Opteron boxes. 525221167Sgnn * 526221167Sgnn * Note: @copy_size should be a multiple of @alignment. In many practical 527221167Sgnn * cases @copy_size and @alignment will probably be equal. 528221167Sgnn * 529221167Sgnn * See also: vxge_hal_fifo_txdl_buffer_set_aligned(). 530221167Sgnn */ 531221167Sgnnu32 532221167Sgnnvxge_hal_check_alignment( 533221167Sgnn dma_addr_t dma_pointer, 534221167Sgnn u32 size, 535221167Sgnn u32 alignment, 536221167Sgnn u32 copy_size) 537221167Sgnn{ 538221167Sgnn u32 misaligned_size; 539221167Sgnn 540221167Sgnn misaligned_size = (int)(dma_pointer & (alignment - 1)); 541221167Sgnn if (!misaligned_size) { 542221167Sgnn return (0); 543221167Sgnn } 544221167Sgnn 545221167Sgnn if (size > copy_size) { 546221167Sgnn misaligned_size = (int)(dma_pointer & (copy_size - 1)); 547221167Sgnn misaligned_size = copy_size - misaligned_size; 548221167Sgnn } else { 549221167Sgnn misaligned_size = size; 550221167Sgnn } 551221167Sgnn 552221167Sgnn return (misaligned_size); 553221167Sgnn} 554