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