xref: /freebsd-11-stable/sys/dev/vxge/vxgehal/vxgehal-blockpool.c (revision 4ab2e064d7950be84256d671a7ae93f87cc6aa36)
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
__hal_blockpool_create(vxge_hal_device_h devh,__hal_blockpool_t * blockpool,u32 pool_size,u32 pool_incr,u32 pool_min,u32 pool_max)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
__hal_blockpool_destroy(__hal_blockpool_t * blockpool)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
__hal_blockpool_blocks_add(__hal_blockpool_t * blockpool)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
__hal_blockpool_blocks_remove(__hal_blockpool_t * blockpool)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
vxge_hal_blockpool_block_add(vxge_hal_device_h devh,void * block_addr,u32 length,pci_dma_h * dma_h,pci_dma_acc_h * acc_handle)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 *
__hal_blockpool_malloc(vxge_hal_device_h devh,u32 size,dma_addr_t * dma_addr,pci_dma_h * dma_handle,pci_dma_acc_h * acc_handle)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
__hal_blockpool_free(vxge_hal_device_h devh,void * memblock,u32 size,dma_addr_t * dma_addr,pci_dma_h * dma_handle,pci_dma_acc_h * acc_handle)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 *
__hal_blockpool_block_allocate(vxge_hal_device_h devh,u32 size)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
__hal_blockpool_block_free(vxge_hal_device_h devh,__hal_blockpool_entry_t * entry)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
__hal_blockpool_list_allocate(vxge_hal_device_h devh,vxge_list_t * blocklist,u32 count)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
__hal_blockpool_list_free(vxge_hal_device_h devh,vxge_list_t * blocklist)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