]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/vxge/vxgehal/vxgehal-blockpool.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / vxge / vxgehal / vxgehal-blockpool.c
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
47 vxge_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
216 void
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  */
292 static 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  */
344 static 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  */
414 void
415 vxge_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  */
551 void *
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  */
672 void
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  */
826 void
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  */
878 vxge_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  */
972 void
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 }