1 /***************************************************************************
2 * Copyright (c) 2005-2009, Broadcom Corporation.
4 * Name: crystalhd_misc . c
7 * BCM70012 Linux driver misc routines.
11 **********************************************************************
12 * This file is part of the crystalhd device driver.
14 * This driver is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, version 2 of the License.
18 * This driver is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this driver. If not, see <http://www.gnu.org/licenses/>.
25 **********************************************************************/
27 #include "crystalhd_misc.h"
28 #include "crystalhd_lnx.h"
30 uint32_t g_linklog_level;
32 static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp, uint32_t mem_off)
34 crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
35 return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF)));
38 static inline void crystalhd_dram_wr(struct crystalhd_adp *adp, uint32_t mem_off, uint32_t val)
40 crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
41 bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val);
44 static inline BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp, uint32_t start_off, uint32_t cnt)
46 return BC_STS_SUCCESS;
49 static crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp)
51 unsigned long flags = 0;
52 crystalhd_dio_req *temp = NULL;
55 BCMLOG_ERR("Invalid Arg!!\n");
59 spin_lock_irqsave(&adp->lock, flags);
60 temp = adp->ua_map_free_head;
62 adp->ua_map_free_head = adp->ua_map_free_head->next;
63 spin_unlock_irqrestore(&adp->lock, flags);
68 static void crystalhd_free_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
70 unsigned long flags = 0;
74 spin_lock_irqsave(&adp->lock, flags);
75 dio->sig = crystalhd_dio_inv;
78 memset(&dio->uinfo, 0, sizeof(dio->uinfo));
79 dio->next = adp->ua_map_free_head;
80 adp->ua_map_free_head = dio;
81 spin_unlock_irqrestore(&adp->lock, flags);
84 static crystalhd_elem_t *crystalhd_alloc_elem(struct crystalhd_adp *adp)
86 unsigned long flags = 0;
87 crystalhd_elem_t *temp = NULL;
91 spin_lock_irqsave(&adp->lock, flags);
92 temp = adp->elem_pool_head;
94 adp->elem_pool_head = adp->elem_pool_head->flink;
95 memset(temp, 0, sizeof(*temp));
97 spin_unlock_irqrestore(&adp->lock, flags);
101 static void crystalhd_free_elem(struct crystalhd_adp *adp, crystalhd_elem_t *elem)
103 unsigned long flags = 0;
107 spin_lock_irqsave(&adp->lock, flags);
108 elem->flink = adp->elem_pool_head;
109 adp->elem_pool_head = elem;
110 spin_unlock_irqrestore(&adp->lock, flags);
113 static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page,
114 unsigned int len, unsigned int offset)
116 sg_set_page(sg, page, len, offset);
118 sg->dma_length = len;
122 static inline void crystalhd_init_sg(struct scatterlist *sg, unsigned int entries)
124 /* http://lkml.org/lkml/2007/11/27/68 */
125 sg_init_table(sg, entries);
128 /*========================== Extern ========================================*/
130 * bc_dec_reg_rd - Read 7412's device register.
131 * @adp: Adapter instance
132 * @reg_off: Register offset.
137 * 7412's device register read routine. This interface use
138 * 7412's device access range mapped from BAR-2 (4M) of PCIe
139 * configuration space.
141 uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
143 if (!adp || (reg_off > adp->pci_mem_len)) {
144 BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off);
148 return readl(adp->addr + reg_off);
152 * bc_dec_reg_wr - Write 7412's device register
153 * @adp: Adapter instance
154 * @reg_off: Register offset.
155 * @val: Dword value to be written.
160 * 7412's device register write routine. This interface use
161 * 7412's device access range mapped from BAR-2 (4M) of PCIe
162 * configuration space.
164 void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
166 if (!adp || (reg_off > adp->pci_mem_len)) {
167 BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off);
170 writel(val, adp->addr + reg_off);
175 * crystalhd_reg_rd - Read Link's device register.
176 * @adp: Adapter instance
177 * @reg_off: Register offset.
182 * Link device register read routine. This interface use
183 * Link's device access range mapped from BAR-1 (64K) of PCIe
184 * configuration space.
187 uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
189 if (!adp || (reg_off > adp->pci_i2o_len)) {
190 BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off);
193 return readl(adp->i2o_addr + reg_off);
197 * crystalhd_reg_wr - Write Link's device register
198 * @adp: Adapter instance
199 * @reg_off: Register offset.
200 * @val: Dword value to be written.
205 * Link device register write routine. This interface use
206 * Link's device access range mapped from BAR-1 (64K) of PCIe
207 * configuration space.
210 void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
212 if (!adp || (reg_off > adp->pci_i2o_len)) {
213 BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off);
216 writel(val, adp->i2o_addr + reg_off);
220 * crystalhd_mem_rd - Read data from 7412's DRAM area.
221 * @adp: Adapter instance
222 * @start_off: Start offset.
223 * @dw_cnt: Count in dwords.
224 * @rd_buff: Buffer to copy the data from dram.
229 * 7412's Dram read routine.
231 BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off,
232 uint32_t dw_cnt, uint32_t *rd_buff)
236 if (!adp || !rd_buff ||
237 (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
238 BCMLOG_ERR("Invalid arg \n");
239 return BC_STS_INV_ARG;
241 for (ix = 0; ix < dw_cnt; ix++)
242 rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4)));
244 return BC_STS_SUCCESS;
248 * crystalhd_mem_wr - Write data to 7412's DRAM area.
249 * @adp: Adapter instance
250 * @start_off: Start offset.
251 * @dw_cnt: Count in dwords.
252 * @wr_buff: Data Buffer to be written.
257 * 7412's Dram write routine.
259 BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off,
260 uint32_t dw_cnt, uint32_t *wr_buff)
264 if (!adp || !wr_buff ||
265 (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
266 BCMLOG_ERR("Invalid arg \n");
267 return BC_STS_INV_ARG;
270 for (ix = 0; ix < dw_cnt; ix++)
271 crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]);
273 return BC_STS_SUCCESS;
276 * crystalhd_pci_cfg_rd - PCIe config read
277 * @adp: Adapter instance
278 * @off: PCI config space offset.
279 * @len: Size -- Byte, Word & dword.
285 * Get value from Link's PCIe config space.
287 BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off,
288 uint32_t len, uint32_t *val)
290 BC_STATUS sts = BC_STS_SUCCESS;
294 BCMLOG_ERR("Invalid arg \n");
295 return BC_STS_INV_ARG;
300 rc = pci_read_config_byte(adp->pdev, off, (u8 *)val);
303 rc = pci_read_config_word(adp->pdev, off, (u16 *)val);
306 rc = pci_read_config_dword(adp->pdev, off, (u32 *)val);
310 sts = BC_STS_INV_ARG;
311 BCMLOG_ERR("Invalid len:%d\n", len);
314 if (rc && (sts == BC_STS_SUCCESS))
321 * crystalhd_pci_cfg_wr - PCIe config write
322 * @adp: Adapter instance
323 * @off: PCI config space offset.
324 * @len: Size -- Byte, Word & dword.
325 * @val: Value to be written
330 * Set value to Link's PCIe config space.
332 BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off,
333 uint32_t len, uint32_t val)
335 BC_STATUS sts = BC_STS_SUCCESS;
339 BCMLOG_ERR("Invalid arg \n");
340 return BC_STS_INV_ARG;
345 rc = pci_write_config_byte(adp->pdev, off, (u8)val);
348 rc = pci_write_config_word(adp->pdev, off, (u16)val);
351 rc = pci_write_config_dword(adp->pdev, off, val);
355 sts = BC_STS_INV_ARG;
356 BCMLOG_ERR("Invalid len:%d\n", len);
359 if (rc && (sts == BC_STS_SUCCESS))
366 * bc_kern_dma_alloc - Allocate memory for Dma rings
367 * @adp: Adapter instance
368 * @sz: Size of the memory to allocate.
369 * @phy_addr: Physical address of the memory allocated.
370 * Typedef to system's dma_addr_t (u64)
373 * Pointer to allocated memory..
375 * Wrapper to Linux kernel interface.
378 void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz,
379 dma_addr_t *phy_addr)
383 if (!adp || !sz || !phy_addr) {
384 BCMLOG_ERR("Invalide Arg..\n");
388 temp = pci_alloc_consistent(adp->pdev, sz, phy_addr);
396 * bc_kern_dma_free - Release Dma ring memory.
397 * @adp: Adapter instance
398 * @sz: Size of the memory to allocate.
399 * @ka: Kernel virtual address returned during _dio_alloc()
400 * @phy_addr: Physical address of the memory allocated.
401 * Typedef to system's dma_addr_t (u64)
406 void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka,
409 if (!adp || !ka || !sz || !phy_addr) {
410 BCMLOG_ERR("Invalide Arg..\n");
414 pci_free_consistent(adp->pdev, sz, ka, phy_addr);
418 * crystalhd_create_dioq - Create Generic DIO queue
419 * @adp: Adapter instance
420 * @dioq_hnd: Handle to the dio queue created
421 * @cb : Optional - Call back To free the element.
422 * @cbctx: Context to pass to callback.
427 * Initialize Generic DIO queue to hold any data. Callback
428 * will be used to free elements while deleting the queue.
430 BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp,
431 crystalhd_dioq_t **dioq_hnd,
432 crystalhd_data_free_cb cb, void *cbctx)
434 crystalhd_dioq_t *dioq = NULL;
436 if (!adp || !dioq_hnd) {
437 BCMLOG_ERR("Invalid arg!!\n");
438 return BC_STS_INV_ARG;
441 dioq = kzalloc(sizeof(*dioq), GFP_KERNEL);
443 return BC_STS_INSUFF_RES;
445 spin_lock_init(&dioq->lock);
446 dioq->sig = BC_LINK_DIOQ_SIG;
447 dioq->head = (crystalhd_elem_t *)&dioq->head;
448 dioq->tail = (crystalhd_elem_t *)&dioq->head;
449 crystalhd_create_event(&dioq->event);
451 dioq->data_rel_cb = cb;
452 dioq->cb_context = cbctx;
455 return BC_STS_SUCCESS;
459 * crystalhd_delete_dioq - Delete Generic DIO queue
460 * @adp: Adapter instance
461 * @dioq: DIOQ instance..
466 * Release Generic DIO queue. This function will remove
467 * all the entries from the Queue and will release data
468 * by calling the call back provided during creation.
471 void crystalhd_delete_dioq(struct crystalhd_adp *adp, crystalhd_dioq_t *dioq)
475 if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG))
479 temp = crystalhd_dioq_fetch(dioq);
480 if (temp && dioq->data_rel_cb)
481 dioq->data_rel_cb(dioq->cb_context, temp);
488 * crystalhd_dioq_add - Add new DIO request element.
489 * @ioq: DIO queue instance
490 * @t: DIO request to be added.
491 * @wake: True - Wake up suspended process.
492 * @tag: Special tag to assign - For search and get.
497 * Insert new element to Q tail.
499 BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data,
500 bool wake, uint32_t tag)
502 unsigned long flags = 0;
503 crystalhd_elem_t *tmp;
505 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) {
506 BCMLOG_ERR("Invalid arg!!\n");
507 return BC_STS_INV_ARG;
510 tmp = crystalhd_alloc_elem(ioq->adp);
512 BCMLOG_ERR("No free elements.\n");
513 return BC_STS_INSUFF_RES;
518 spin_lock_irqsave(&ioq->lock, flags);
519 tmp->flink = (crystalhd_elem_t *)&ioq->head;
520 tmp->blink = ioq->tail;
521 tmp->flink->blink = tmp;
522 tmp->blink->flink = tmp;
524 spin_unlock_irqrestore(&ioq->lock, flags);
527 crystalhd_set_event(&ioq->event);
529 return BC_STS_SUCCESS;
533 * crystalhd_dioq_fetch - Fetch element from head.
534 * @ioq: DIO queue instance
537 * data element from the head..
539 * Remove an element from Queue.
541 void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq)
543 unsigned long flags = 0;
544 crystalhd_elem_t *tmp;
545 crystalhd_elem_t *ret = NULL;
548 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
549 BCMLOG_ERR("Invalid arg!!\n");
553 spin_lock_irqsave(&ioq->lock, flags);
555 if (tmp != (crystalhd_elem_t *)&ioq->head) {
557 tmp->flink->blink = tmp->blink;
558 tmp->blink->flink = tmp->flink;
561 spin_unlock_irqrestore(&ioq->lock, flags);
564 crystalhd_free_elem(ioq->adp, ret);
570 * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element
571 * @ioq: DIO queue instance
572 * @tag: Tag to search for.
575 * element from the head..
577 * Search TAG and remove the element.
579 void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag)
581 unsigned long flags = 0;
582 crystalhd_elem_t *tmp;
583 crystalhd_elem_t *ret = NULL;
586 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
587 BCMLOG_ERR("Invalid arg!!\n");
591 spin_lock_irqsave(&ioq->lock, flags);
593 while (tmp != (crystalhd_elem_t *)&ioq->head) {
594 if (tmp->tag == tag) {
596 tmp->flink->blink = tmp->blink;
597 tmp->blink->flink = tmp->flink;
603 spin_unlock_irqrestore(&ioq->lock, flags);
607 crystalhd_free_elem(ioq->adp, ret);
614 * crystalhd_dioq_fetch_wait - Fetch element from Head.
615 * @ioq: DIO queue instance
616 * @to_secs: Wait timeout in seconds..
619 * element from the head..
621 * Return element from head if Q is not empty. Wait for new element
622 * if Q is empty for Timeout seconds.
624 void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs,
627 unsigned long flags = 0;
631 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) {
632 BCMLOG_ERR("Invalid arg!!\n");
637 spin_lock_irqsave(&ioq->lock, flags);
638 while ((ioq->count == 0) && count) {
639 spin_unlock_irqrestore(&ioq->lock, flags);
641 crystalhd_wait_on_event(&ioq->event, (ioq->count > 0), 1000, rc, 0);
644 } else if (rc == -EINTR) {
645 BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n");
649 spin_lock_irqsave(&ioq->lock, flags);
652 spin_unlock_irqrestore(&ioq->lock, flags);
655 return crystalhd_dioq_fetch(ioq);
659 * crystalhd_map_dio - Map user address for DMA
660 * @adp: Adapter instance
661 * @ubuff: User buffer to map.
662 * @ubuff_sz: User buffer size.
663 * @uv_offset: UV buffer offset.
664 * @en_422mode: TRUE:422 FALSE:420 Capture mode.
665 * @dir_tx: TRUE for Tx (To device from host)
666 * @dio_hnd: Handle to mapped DIO request.
671 * This routine maps user address and lock pages for DMA.
674 BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff,
675 uint32_t ubuff_sz, uint32_t uv_offset,
676 bool en_422mode, bool dir_tx,
677 crystalhd_dio_req **dio_hnd)
679 crystalhd_dio_req *dio;
680 /* FIXME: jarod: should some of these unsigned longs be uint32_t or uintptr_t? */
681 unsigned long start = 0, end = 0, uaddr = 0, count = 0;
682 unsigned long spsz = 0, uv_start = 0;
683 int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0;
685 if (!adp || !ubuff || !ubuff_sz || !dio_hnd) {
686 BCMLOG_ERR("Invalid arg \n");
687 return BC_STS_INV_ARG;
690 uaddr = (unsigned long)ubuff;
691 count = (unsigned long)ubuff_sz;
692 end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
693 start = uaddr >> PAGE_SHIFT;
694 nr_pages = end - start;
696 if (!count || ((uaddr + count) < uaddr)) {
697 BCMLOG_ERR("User addr overflow!!\n");
698 return BC_STS_INV_ARG;
701 dio = crystalhd_alloc_dio(adp);
703 BCMLOG_ERR("dio pool empty..\n");
704 return BC_STS_INSUFF_RES;
709 dio->direction = DMA_TO_DEVICE;
712 dio->direction = DMA_FROM_DEVICE;
715 if (nr_pages > dio->max_pages) {
716 BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
717 dio->max_pages, nr_pages);
718 crystalhd_unmap_dio(adp, dio);
719 return BC_STS_INSUFF_RES;
723 uv_start = (uaddr + (unsigned long)uv_offset) >> PAGE_SHIFT;
724 dio->uinfo.uv_sg_ix = uv_start - start;
725 dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) & ~PAGE_MASK);
728 dio->fb_size = ubuff_sz & 0x03;
730 res = copy_from_user(dio->fb_va,
731 (void *)(uaddr + count - dio->fb_size),
734 BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
736 (void *)(uaddr + count-dio->fb_size));
737 crystalhd_unmap_dio(adp, dio);
738 return BC_STS_INSUFF_RES;
742 down_read(¤t->mm->mmap_sem);
743 res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ,
744 0, dio->pages, NULL);
745 up_read(¤t->mm->mmap_sem);
747 /* Save for release..*/
748 dio->sig = crystalhd_dio_locked;
749 if (res < nr_pages) {
750 BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res);
752 crystalhd_unmap_dio(adp, dio);
756 dio->page_cnt = nr_pages;
757 /* Get scatter/gather */
758 crystalhd_init_sg(dio->sg, dio->page_cnt);
759 crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK);
761 dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset;
764 dio->sg[0].dma_length = dio->sg[0].length;
766 count -= dio->sg[0].length;
767 for (i = 1; i < nr_pages; i++) {
772 spsz = (count < PAGE_SIZE) ?
773 (count & ~0x03) : PAGE_SIZE;
775 crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0);
780 dio->sg[0].length = count;
783 dio->sg[0].length = count - dio->fb_size;
786 dio->sg[0].dma_length = dio->sg[0].length;
789 dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg,
790 dio->page_cnt, dio->direction);
791 if (dio->sg_cnt <= 0) {
792 BCMLOG_ERR("sg map %d-%d \n", dio->sg_cnt, dio->page_cnt);
793 crystalhd_unmap_dio(adp, dio);
796 if (dio->sg_cnt && skip_fb_sg)
798 dio->sig = crystalhd_dio_sg_mapped;
799 /* Fill in User info.. */
800 dio->uinfo.xfr_len = ubuff_sz;
801 dio->uinfo.xfr_buff = ubuff;
802 dio->uinfo.uv_offset = uv_offset;
803 dio->uinfo.b422mode = en_422mode;
804 dio->uinfo.dir_tx = dir_tx;
808 return BC_STS_SUCCESS;
812 * crystalhd_unmap_sgl - Release mapped resources
813 * @adp: Adapter instance
814 * @dio: DIO request instance
819 * This routine is to unmap the user buffer pages.
821 BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
823 struct page *page = NULL;
827 BCMLOG_ERR("Invalid arg \n");
828 return BC_STS_INV_ARG;
831 if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) {
832 for (j = 0; j < dio->page_cnt; j++) {
833 page = dio->pages[j];
835 if (!PageReserved(page) &&
836 (dio->direction == DMA_FROM_DEVICE))
838 page_cache_release(page);
842 if (dio->sig == crystalhd_dio_sg_mapped)
843 pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt, dio->direction);
845 crystalhd_free_dio(adp, dio);
847 return BC_STS_SUCCESS;
851 * crystalhd_create_dio_pool - Allocate mem pool for DIO management.
852 * @adp: Adapter instance
853 * @max_pages: Max pages for size calculation.
858 * This routine creates a memory pool to hold dio context for
859 * for HW Direct IO operation.
861 int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages)
863 uint32_t asz = 0, i = 0;
865 crystalhd_dio_req *dio;
867 if (!adp || !max_pages) {
868 BCMLOG_ERR("Invalid Arg!!\n");
872 /* Get dma memory for fill byte handling..*/
873 adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte",
875 if (!adp->fill_byte_pool) {
876 BCMLOG_ERR("failed to create fill byte pool\n");
880 /* Get the max size from user based on 420/422 modes */
881 asz = (sizeof(*dio->pages) * max_pages) +
882 (sizeof(*dio->sg) * max_pages) + sizeof(*dio);
884 BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n",
885 BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool);
887 for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) {
888 temp = (uint8_t *)kzalloc(asz, GFP_KERNEL);
889 if ((temp) == NULL) {
890 BCMLOG_ERR("Failed to alloc %d mem\n", asz);
894 dio = (crystalhd_dio_req *)temp;
895 temp += sizeof(*dio);
896 dio->pages = (struct page **)temp;
897 temp += (sizeof(*dio->pages) * max_pages);
898 dio->sg = (struct scatterlist *)temp;
899 dio->max_pages = max_pages;
900 dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL,
903 BCMLOG_ERR("fill byte alloc failed.\n");
907 crystalhd_free_dio(adp, dio);
914 * crystalhd_destroy_dio_pool - Release DIO mem pool.
915 * @adp: Adapter instance
920 * This routine releases dio memory pool during close.
922 void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
924 crystalhd_dio_req *dio;
928 BCMLOG_ERR("Invalid Arg!!\n");
933 dio = crystalhd_alloc_dio(adp);
936 pci_pool_free(adp->fill_byte_pool,
937 dio->fb_va, dio->fb_pa);
943 if (adp->fill_byte_pool) {
944 pci_pool_destroy(adp->fill_byte_pool);
945 adp->fill_byte_pool = NULL;
948 BCMLOG(BCMLOG_DBG, "Released dio pool %d \n", count);
952 * crystalhd_create_elem_pool - List element pool creation.
953 * @adp: Adapter instance
954 * @pool_size: Number of elements in the pool.
957 * 0 - success, <0 error
959 * Create general purpose list element pool to hold pending,
960 * and active requests.
962 int crystalhd_create_elem_pool(struct crystalhd_adp *adp, uint32_t pool_size)
965 crystalhd_elem_t *temp;
967 if (!adp || !pool_size)
970 for (i = 0; i < pool_size; i++) {
971 temp = kzalloc(sizeof(*temp), GFP_KERNEL);
973 BCMLOG_ERR("kalloc failed \n");
976 crystalhd_free_elem(adp, temp);
978 BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size);
983 * crystalhd_delete_elem_pool - List element pool deletion.
984 * @adp: Adapter instance
989 * Delete general purpose list element pool.
991 void crystalhd_delete_elem_pool(struct crystalhd_adp *adp)
993 crystalhd_elem_t *temp;
1000 temp = crystalhd_alloc_elem(adp);
1007 BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt);
1010 /*================ Debug support routines.. ================================*/
1011 void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount)
1015 for (i = 0; i < dwcount; i++) {
1017 BCMLOG(BCMLOG_DATA, "0x%08X : ", off);
1019 BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff));
1021 buff += sizeof(uint32_t);
1022 off += sizeof(uint32_t);
1024 if ((i == dwcount - 1) || (k > 4)) {
1025 BCMLOG(BCMLOG_DATA, "\n");