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 <linux/slab.h>
29 #include "crystalhd_misc.h"
30 #include "crystalhd_lnx.h"
32 uint32_t g_linklog_level
;
34 static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp
*adp
, uint32_t mem_off
)
36 crystalhd_reg_wr(adp
, DCI_DRAM_BASE_ADDR
, (mem_off
>> 19));
37 return bc_dec_reg_rd(adp
, (0x00380000 | (mem_off
& 0x0007FFFF)));
40 static inline void crystalhd_dram_wr(struct crystalhd_adp
*adp
, uint32_t mem_off
, uint32_t val
)
42 crystalhd_reg_wr(adp
, DCI_DRAM_BASE_ADDR
, (mem_off
>> 19));
43 bc_dec_reg_wr(adp
, (0x00380000 | (mem_off
& 0x0007FFFF)), val
);
46 static inline enum BC_STATUS
bc_chk_dram_range(struct crystalhd_adp
*adp
, uint32_t start_off
, uint32_t cnt
)
48 return BC_STS_SUCCESS
;
51 static struct crystalhd_dio_req
*crystalhd_alloc_dio(struct crystalhd_adp
*adp
)
53 unsigned long flags
= 0;
54 struct crystalhd_dio_req
*temp
= NULL
;
57 BCMLOG_ERR("Invalid Arg!!\n");
61 spin_lock_irqsave(&adp
->lock
, flags
);
62 temp
= adp
->ua_map_free_head
;
64 adp
->ua_map_free_head
= adp
->ua_map_free_head
->next
;
65 spin_unlock_irqrestore(&adp
->lock
, flags
);
70 static void crystalhd_free_dio(struct crystalhd_adp
*adp
, struct crystalhd_dio_req
*dio
)
72 unsigned long flags
= 0;
76 spin_lock_irqsave(&adp
->lock
, flags
);
77 dio
->sig
= crystalhd_dio_inv
;
80 memset(&dio
->uinfo
, 0, sizeof(dio
->uinfo
));
81 dio
->next
= adp
->ua_map_free_head
;
82 adp
->ua_map_free_head
= dio
;
83 spin_unlock_irqrestore(&adp
->lock
, flags
);
86 static struct crystalhd_elem
*crystalhd_alloc_elem(struct crystalhd_adp
*adp
)
88 unsigned long flags
= 0;
89 struct crystalhd_elem
*temp
= NULL
;
93 spin_lock_irqsave(&adp
->lock
, flags
);
94 temp
= adp
->elem_pool_head
;
96 adp
->elem_pool_head
= adp
->elem_pool_head
->flink
;
97 memset(temp
, 0, sizeof(*temp
));
99 spin_unlock_irqrestore(&adp
->lock
, flags
);
103 static void crystalhd_free_elem(struct crystalhd_adp
*adp
, struct crystalhd_elem
*elem
)
105 unsigned long flags
= 0;
109 spin_lock_irqsave(&adp
->lock
, flags
);
110 elem
->flink
= adp
->elem_pool_head
;
111 adp
->elem_pool_head
= elem
;
112 spin_unlock_irqrestore(&adp
->lock
, flags
);
115 static inline void crystalhd_set_sg(struct scatterlist
*sg
, struct page
*page
,
116 unsigned int len
, unsigned int offset
)
118 sg_set_page(sg
, page
, len
, offset
);
120 sg
->dma_length
= len
;
124 static inline void crystalhd_init_sg(struct scatterlist
*sg
, unsigned int entries
)
126 /* http://lkml.org/lkml/2007/11/27/68 */
127 sg_init_table(sg
, entries
);
130 /*========================== Extern ========================================*/
132 * bc_dec_reg_rd - Read 7412's device register.
133 * @adp: Adapter instance
134 * @reg_off: Register offset.
139 * 7412's device register read routine. This interface use
140 * 7412's device access range mapped from BAR-2 (4M) of PCIe
141 * configuration space.
143 uint32_t bc_dec_reg_rd(struct crystalhd_adp
*adp
, uint32_t reg_off
)
145 if (!adp
|| (reg_off
> adp
->pci_mem_len
)) {
146 BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off
);
150 return readl(adp
->addr
+ reg_off
);
154 * bc_dec_reg_wr - Write 7412's device register
155 * @adp: Adapter instance
156 * @reg_off: Register offset.
157 * @val: Dword value to be written.
162 * 7412's device register write routine. This interface use
163 * 7412's device access range mapped from BAR-2 (4M) of PCIe
164 * configuration space.
166 void bc_dec_reg_wr(struct crystalhd_adp
*adp
, uint32_t reg_off
, uint32_t val
)
168 if (!adp
|| (reg_off
> adp
->pci_mem_len
)) {
169 BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off
);
172 writel(val
, adp
->addr
+ reg_off
);
177 * crystalhd_reg_rd - Read Link's device register.
178 * @adp: Adapter instance
179 * @reg_off: Register offset.
184 * Link device register read routine. This interface use
185 * Link's device access range mapped from BAR-1 (64K) of PCIe
186 * configuration space.
189 uint32_t crystalhd_reg_rd(struct crystalhd_adp
*adp
, uint32_t reg_off
)
191 if (!adp
|| (reg_off
> adp
->pci_i2o_len
)) {
192 BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off
);
195 return readl(adp
->i2o_addr
+ reg_off
);
199 * crystalhd_reg_wr - Write Link's device register
200 * @adp: Adapter instance
201 * @reg_off: Register offset.
202 * @val: Dword value to be written.
207 * Link device register write routine. This interface use
208 * Link's device access range mapped from BAR-1 (64K) of PCIe
209 * configuration space.
212 void crystalhd_reg_wr(struct crystalhd_adp
*adp
, uint32_t reg_off
, uint32_t val
)
214 if (!adp
|| (reg_off
> adp
->pci_i2o_len
)) {
215 BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off
);
218 writel(val
, adp
->i2o_addr
+ reg_off
);
222 * crystalhd_mem_rd - Read data from 7412's DRAM area.
223 * @adp: Adapter instance
224 * @start_off: Start offset.
225 * @dw_cnt: Count in dwords.
226 * @rd_buff: Buffer to copy the data from dram.
231 * 7412's Dram read routine.
233 enum BC_STATUS
crystalhd_mem_rd(struct crystalhd_adp
*adp
, uint32_t start_off
,
234 uint32_t dw_cnt
, uint32_t *rd_buff
)
238 if (!adp
|| !rd_buff
||
239 (bc_chk_dram_range(adp
, start_off
, dw_cnt
) != BC_STS_SUCCESS
)) {
240 BCMLOG_ERR("Invalid arg\n");
241 return BC_STS_INV_ARG
;
243 for (ix
= 0; ix
< dw_cnt
; ix
++)
244 rd_buff
[ix
] = crystalhd_dram_rd(adp
, (start_off
+ (ix
* 4)));
246 return BC_STS_SUCCESS
;
250 * crystalhd_mem_wr - Write data to 7412's DRAM area.
251 * @adp: Adapter instance
252 * @start_off: Start offset.
253 * @dw_cnt: Count in dwords.
254 * @wr_buff: Data Buffer to be written.
259 * 7412's Dram write routine.
261 enum BC_STATUS
crystalhd_mem_wr(struct crystalhd_adp
*adp
, uint32_t start_off
,
262 uint32_t dw_cnt
, uint32_t *wr_buff
)
266 if (!adp
|| !wr_buff
||
267 (bc_chk_dram_range(adp
, start_off
, dw_cnt
) != BC_STS_SUCCESS
)) {
268 BCMLOG_ERR("Invalid arg\n");
269 return BC_STS_INV_ARG
;
272 for (ix
= 0; ix
< dw_cnt
; ix
++)
273 crystalhd_dram_wr(adp
, (start_off
+ (ix
* 4)), wr_buff
[ix
]);
275 return BC_STS_SUCCESS
;
278 * crystalhd_pci_cfg_rd - PCIe config read
279 * @adp: Adapter instance
280 * @off: PCI config space offset.
281 * @len: Size -- Byte, Word & dword.
287 * Get value from Link's PCIe config space.
289 enum BC_STATUS
crystalhd_pci_cfg_rd(struct crystalhd_adp
*adp
, uint32_t off
,
290 uint32_t len
, uint32_t *val
)
292 enum BC_STATUS sts
= BC_STS_SUCCESS
;
296 BCMLOG_ERR("Invalid arg\n");
297 return BC_STS_INV_ARG
;
302 rc
= pci_read_config_byte(adp
->pdev
, off
, (u8
*)val
);
305 rc
= pci_read_config_word(adp
->pdev
, off
, (u16
*)val
);
308 rc
= pci_read_config_dword(adp
->pdev
, off
, (u32
*)val
);
312 sts
= BC_STS_INV_ARG
;
313 BCMLOG_ERR("Invalid len:%d\n", len
);
316 if (rc
&& (sts
== BC_STS_SUCCESS
))
323 * crystalhd_pci_cfg_wr - PCIe config write
324 * @adp: Adapter instance
325 * @off: PCI config space offset.
326 * @len: Size -- Byte, Word & dword.
327 * @val: Value to be written
332 * Set value to Link's PCIe config space.
334 enum BC_STATUS
crystalhd_pci_cfg_wr(struct crystalhd_adp
*adp
, uint32_t off
,
335 uint32_t len
, uint32_t val
)
337 enum BC_STATUS sts
= BC_STS_SUCCESS
;
341 BCMLOG_ERR("Invalid arg\n");
342 return BC_STS_INV_ARG
;
347 rc
= pci_write_config_byte(adp
->pdev
, off
, (u8
)val
);
350 rc
= pci_write_config_word(adp
->pdev
, off
, (u16
)val
);
353 rc
= pci_write_config_dword(adp
->pdev
, off
, val
);
357 sts
= BC_STS_INV_ARG
;
358 BCMLOG_ERR("Invalid len:%d\n", len
);
361 if (rc
&& (sts
== BC_STS_SUCCESS
))
368 * bc_kern_dma_alloc - Allocate memory for Dma rings
369 * @adp: Adapter instance
370 * @sz: Size of the memory to allocate.
371 * @phy_addr: Physical address of the memory allocated.
372 * Typedef to system's dma_addr_t (u64)
375 * Pointer to allocated memory..
377 * Wrapper to Linux kernel interface.
380 void *bc_kern_dma_alloc(struct crystalhd_adp
*adp
, uint32_t sz
,
381 dma_addr_t
*phy_addr
)
385 if (!adp
|| !sz
|| !phy_addr
) {
386 BCMLOG_ERR("Invalide Arg..\n");
390 temp
= pci_alloc_consistent(adp
->pdev
, sz
, phy_addr
);
398 * bc_kern_dma_free - Release Dma ring memory.
399 * @adp: Adapter instance
400 * @sz: Size of the memory to allocate.
401 * @ka: Kernel virtual address returned during _dio_alloc()
402 * @phy_addr: Physical address of the memory allocated.
403 * Typedef to system's dma_addr_t (u64)
408 void bc_kern_dma_free(struct crystalhd_adp
*adp
, uint32_t sz
, void *ka
,
411 if (!adp
|| !ka
|| !sz
|| !phy_addr
) {
412 BCMLOG_ERR("Invalide Arg..\n");
416 pci_free_consistent(adp
->pdev
, sz
, ka
, phy_addr
);
420 * crystalhd_create_dioq - Create Generic DIO queue
421 * @adp: Adapter instance
422 * @dioq_hnd: Handle to the dio queue created
423 * @cb : Optional - Call back To free the element.
424 * @cbctx: Context to pass to callback.
429 * Initialize Generic DIO queue to hold any data. Callback
430 * will be used to free elements while deleting the queue.
432 enum BC_STATUS
crystalhd_create_dioq(struct crystalhd_adp
*adp
,
433 struct crystalhd_dioq
**dioq_hnd
,
434 crystalhd_data_free_cb cb
, void *cbctx
)
436 struct crystalhd_dioq
*dioq
= NULL
;
438 if (!adp
|| !dioq_hnd
) {
439 BCMLOG_ERR("Invalid arg!!\n");
440 return BC_STS_INV_ARG
;
443 dioq
= kzalloc(sizeof(*dioq
), GFP_KERNEL
);
445 return BC_STS_INSUFF_RES
;
447 spin_lock_init(&dioq
->lock
);
448 dioq
->sig
= BC_LINK_DIOQ_SIG
;
449 dioq
->head
= (struct crystalhd_elem
*)&dioq
->head
;
450 dioq
->tail
= (struct crystalhd_elem
*)&dioq
->head
;
451 crystalhd_create_event(&dioq
->event
);
453 dioq
->data_rel_cb
= cb
;
454 dioq
->cb_context
= cbctx
;
457 return BC_STS_SUCCESS
;
461 * crystalhd_delete_dioq - Delete Generic DIO queue
462 * @adp: Adapter instance
463 * @dioq: DIOQ instance..
468 * Release Generic DIO queue. This function will remove
469 * all the entries from the Queue and will release data
470 * by calling the call back provided during creation.
473 void crystalhd_delete_dioq(struct crystalhd_adp
*adp
, struct crystalhd_dioq
*dioq
)
477 if (!dioq
|| (dioq
->sig
!= BC_LINK_DIOQ_SIG
))
481 temp
= crystalhd_dioq_fetch(dioq
);
482 if (temp
&& dioq
->data_rel_cb
)
483 dioq
->data_rel_cb(dioq
->cb_context
, temp
);
490 * crystalhd_dioq_add - Add new DIO request element.
491 * @ioq: DIO queue instance
492 * @t: DIO request to be added.
493 * @wake: True - Wake up suspended process.
494 * @tag: Special tag to assign - For search and get.
499 * Insert new element to Q tail.
501 enum BC_STATUS
crystalhd_dioq_add(struct crystalhd_dioq
*ioq
, void *data
,
502 bool wake
, uint32_t tag
)
504 unsigned long flags
= 0;
505 struct crystalhd_elem
*tmp
;
507 if (!ioq
|| (ioq
->sig
!= BC_LINK_DIOQ_SIG
) || !data
) {
508 BCMLOG_ERR("Invalid arg!!\n");
509 return BC_STS_INV_ARG
;
512 tmp
= crystalhd_alloc_elem(ioq
->adp
);
514 BCMLOG_ERR("No free elements.\n");
515 return BC_STS_INSUFF_RES
;
520 spin_lock_irqsave(&ioq
->lock
, flags
);
521 tmp
->flink
= (struct crystalhd_elem
*)&ioq
->head
;
522 tmp
->blink
= ioq
->tail
;
523 tmp
->flink
->blink
= tmp
;
524 tmp
->blink
->flink
= tmp
;
526 spin_unlock_irqrestore(&ioq
->lock
, flags
);
529 crystalhd_set_event(&ioq
->event
);
531 return BC_STS_SUCCESS
;
535 * crystalhd_dioq_fetch - Fetch element from head.
536 * @ioq: DIO queue instance
539 * data element from the head..
541 * Remove an element from Queue.
543 void *crystalhd_dioq_fetch(struct crystalhd_dioq
*ioq
)
545 unsigned long flags
= 0;
546 struct crystalhd_elem
*tmp
;
547 struct crystalhd_elem
*ret
= NULL
;
550 if (!ioq
|| (ioq
->sig
!= BC_LINK_DIOQ_SIG
)) {
551 BCMLOG_ERR("Invalid arg!!\n");
555 spin_lock_irqsave(&ioq
->lock
, flags
);
557 if (tmp
!= (struct crystalhd_elem
*)&ioq
->head
) {
559 tmp
->flink
->blink
= tmp
->blink
;
560 tmp
->blink
->flink
= tmp
->flink
;
563 spin_unlock_irqrestore(&ioq
->lock
, flags
);
566 crystalhd_free_elem(ioq
->adp
, ret
);
572 * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element
573 * @ioq: DIO queue instance
574 * @tag: Tag to search for.
577 * element from the head..
579 * Search TAG and remove the element.
581 void *crystalhd_dioq_find_and_fetch(struct crystalhd_dioq
*ioq
, uint32_t tag
)
583 unsigned long flags
= 0;
584 struct crystalhd_elem
*tmp
;
585 struct crystalhd_elem
*ret
= NULL
;
588 if (!ioq
|| (ioq
->sig
!= BC_LINK_DIOQ_SIG
)) {
589 BCMLOG_ERR("Invalid arg!!\n");
593 spin_lock_irqsave(&ioq
->lock
, flags
);
595 while (tmp
!= (struct crystalhd_elem
*)&ioq
->head
) {
596 if (tmp
->tag
== tag
) {
598 tmp
->flink
->blink
= tmp
->blink
;
599 tmp
->blink
->flink
= tmp
->flink
;
605 spin_unlock_irqrestore(&ioq
->lock
, flags
);
609 crystalhd_free_elem(ioq
->adp
, ret
);
616 * crystalhd_dioq_fetch_wait - Fetch element from Head.
617 * @ioq: DIO queue instance
618 * @to_secs: Wait timeout in seconds..
621 * element from the head..
623 * Return element from head if Q is not empty. Wait for new element
624 * if Q is empty for Timeout seconds.
626 void *crystalhd_dioq_fetch_wait(struct crystalhd_dioq
*ioq
, uint32_t to_secs
,
629 unsigned long flags
= 0;
633 if (!ioq
|| (ioq
->sig
!= BC_LINK_DIOQ_SIG
) || !to_secs
|| !sig_pend
) {
634 BCMLOG_ERR("Invalid arg!!\n");
639 spin_lock_irqsave(&ioq
->lock
, flags
);
640 while ((ioq
->count
== 0) && count
) {
641 spin_unlock_irqrestore(&ioq
->lock
, flags
);
643 crystalhd_wait_on_event(&ioq
->event
, (ioq
->count
> 0), 1000, rc
, 0);
646 } else if (rc
== -EINTR
) {
647 BCMLOG(BCMLOG_INFO
, "Cancelling fetch wait\n");
651 spin_lock_irqsave(&ioq
->lock
, flags
);
654 spin_unlock_irqrestore(&ioq
->lock
, flags
);
657 return crystalhd_dioq_fetch(ioq
);
661 * crystalhd_map_dio - Map user address for DMA
662 * @adp: Adapter instance
663 * @ubuff: User buffer to map.
664 * @ubuff_sz: User buffer size.
665 * @uv_offset: UV buffer offset.
666 * @en_422mode: TRUE:422 FALSE:420 Capture mode.
667 * @dir_tx: TRUE for Tx (To device from host)
668 * @dio_hnd: Handle to mapped DIO request.
673 * This routine maps user address and lock pages for DMA.
676 enum BC_STATUS
crystalhd_map_dio(struct crystalhd_adp
*adp
, void *ubuff
,
677 uint32_t ubuff_sz
, uint32_t uv_offset
,
678 bool en_422mode
, bool dir_tx
,
679 struct crystalhd_dio_req
**dio_hnd
)
681 struct crystalhd_dio_req
*dio
;
682 /* FIXME: jarod: should some of these unsigned longs be uint32_t or uintptr_t? */
683 unsigned long start
= 0, end
= 0, uaddr
= 0, count
= 0;
684 unsigned long spsz
= 0, uv_start
= 0;
685 int i
= 0, rw
= 0, res
= 0, nr_pages
= 0, skip_fb_sg
= 0;
687 if (!adp
|| !ubuff
|| !ubuff_sz
|| !dio_hnd
) {
688 BCMLOG_ERR("Invalid arg\n");
689 return BC_STS_INV_ARG
;
692 uaddr
= (unsigned long)ubuff
;
693 count
= (unsigned long)ubuff_sz
;
694 end
= (uaddr
+ count
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
;
695 start
= uaddr
>> PAGE_SHIFT
;
696 nr_pages
= end
- start
;
698 if (!count
|| ((uaddr
+ count
) < uaddr
)) {
699 BCMLOG_ERR("User addr overflow!!\n");
700 return BC_STS_INV_ARG
;
703 dio
= crystalhd_alloc_dio(adp
);
705 BCMLOG_ERR("dio pool empty..\n");
706 return BC_STS_INSUFF_RES
;
711 dio
->direction
= DMA_TO_DEVICE
;
714 dio
->direction
= DMA_FROM_DEVICE
;
717 if (nr_pages
> dio
->max_pages
) {
718 BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
719 dio
->max_pages
, nr_pages
);
720 crystalhd_unmap_dio(adp
, dio
);
721 return BC_STS_INSUFF_RES
;
725 uv_start
= (uaddr
+ (unsigned long)uv_offset
) >> PAGE_SHIFT
;
726 dio
->uinfo
.uv_sg_ix
= uv_start
- start
;
727 dio
->uinfo
.uv_sg_off
= ((uaddr
+ (unsigned long)uv_offset
) & ~PAGE_MASK
);
730 dio
->fb_size
= ubuff_sz
& 0x03;
732 res
= copy_from_user(dio
->fb_va
,
733 (void *)(uaddr
+ count
- dio
->fb_size
),
736 BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
738 (void *)(uaddr
+ count
-dio
->fb_size
));
739 crystalhd_unmap_dio(adp
, dio
);
740 return BC_STS_INSUFF_RES
;
744 down_read(¤t
->mm
->mmap_sem
);
745 res
= get_user_pages(current
, current
->mm
, uaddr
, nr_pages
, rw
== READ
,
746 0, dio
->pages
, NULL
);
747 up_read(¤t
->mm
->mmap_sem
);
749 /* Save for release..*/
750 dio
->sig
= crystalhd_dio_locked
;
751 if (res
< nr_pages
) {
752 BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages
, res
);
754 crystalhd_unmap_dio(adp
, dio
);
758 dio
->page_cnt
= nr_pages
;
759 /* Get scatter/gather */
760 crystalhd_init_sg(dio
->sg
, dio
->page_cnt
);
761 crystalhd_set_sg(&dio
->sg
[0], dio
->pages
[0], 0, uaddr
& ~PAGE_MASK
);
763 dio
->sg
[0].length
= PAGE_SIZE
- dio
->sg
[0].offset
;
766 dio
->sg
[0].dma_length
= dio
->sg
[0].length
;
768 count
-= dio
->sg
[0].length
;
769 for (i
= 1; i
< nr_pages
; i
++) {
774 spsz
= (count
< PAGE_SIZE
) ?
775 (count
& ~0x03) : PAGE_SIZE
;
777 crystalhd_set_sg(&dio
->sg
[i
], dio
->pages
[i
], spsz
, 0);
782 dio
->sg
[0].length
= count
;
785 dio
->sg
[0].length
= count
- dio
->fb_size
;
788 dio
->sg
[0].dma_length
= dio
->sg
[0].length
;
791 dio
->sg_cnt
= pci_map_sg(adp
->pdev
, dio
->sg
,
792 dio
->page_cnt
, dio
->direction
);
793 if (dio
->sg_cnt
<= 0) {
794 BCMLOG_ERR("sg map %d-%d\n", dio
->sg_cnt
, dio
->page_cnt
);
795 crystalhd_unmap_dio(adp
, dio
);
798 if (dio
->sg_cnt
&& skip_fb_sg
)
800 dio
->sig
= crystalhd_dio_sg_mapped
;
801 /* Fill in User info.. */
802 dio
->uinfo
.xfr_len
= ubuff_sz
;
803 dio
->uinfo
.xfr_buff
= ubuff
;
804 dio
->uinfo
.uv_offset
= uv_offset
;
805 dio
->uinfo
.b422mode
= en_422mode
;
806 dio
->uinfo
.dir_tx
= dir_tx
;
810 return BC_STS_SUCCESS
;
814 * crystalhd_unmap_sgl - Release mapped resources
815 * @adp: Adapter instance
816 * @dio: DIO request instance
821 * This routine is to unmap the user buffer pages.
823 enum BC_STATUS
crystalhd_unmap_dio(struct crystalhd_adp
*adp
, struct crystalhd_dio_req
*dio
)
825 struct page
*page
= NULL
;
829 BCMLOG_ERR("Invalid arg\n");
830 return BC_STS_INV_ARG
;
833 if ((dio
->page_cnt
> 0) && (dio
->sig
!= crystalhd_dio_inv
)) {
834 for (j
= 0; j
< dio
->page_cnt
; j
++) {
835 page
= dio
->pages
[j
];
837 if (!PageReserved(page
) &&
838 (dio
->direction
== DMA_FROM_DEVICE
))
840 page_cache_release(page
);
844 if (dio
->sig
== crystalhd_dio_sg_mapped
)
845 pci_unmap_sg(adp
->pdev
, dio
->sg
, dio
->page_cnt
, dio
->direction
);
847 crystalhd_free_dio(adp
, dio
);
849 return BC_STS_SUCCESS
;
853 * crystalhd_create_dio_pool - Allocate mem pool for DIO management.
854 * @adp: Adapter instance
855 * @max_pages: Max pages for size calculation.
860 * This routine creates a memory pool to hold dio context for
861 * for HW Direct IO operation.
863 int crystalhd_create_dio_pool(struct crystalhd_adp
*adp
, uint32_t max_pages
)
865 uint32_t asz
= 0, i
= 0;
867 struct crystalhd_dio_req
*dio
;
869 if (!adp
|| !max_pages
) {
870 BCMLOG_ERR("Invalid Arg!!\n");
874 /* Get dma memory for fill byte handling..*/
875 adp
->fill_byte_pool
= pci_pool_create("crystalhd_fbyte",
877 if (!adp
->fill_byte_pool
) {
878 BCMLOG_ERR("failed to create fill byte pool\n");
882 /* Get the max size from user based on 420/422 modes */
883 asz
= (sizeof(*dio
->pages
) * max_pages
) +
884 (sizeof(*dio
->sg
) * max_pages
) + sizeof(*dio
);
886 BCMLOG(BCMLOG_DBG
, "Initializing Dio pool %d %d %x %p\n",
887 BC_LINK_SG_POOL_SZ
, max_pages
, asz
, adp
->fill_byte_pool
);
889 for (i
= 0; i
< BC_LINK_SG_POOL_SZ
; i
++) {
890 temp
= kzalloc(asz
, GFP_KERNEL
);
891 if ((temp
) == NULL
) {
892 BCMLOG_ERR("Failed to alloc %d mem\n", asz
);
896 dio
= (struct crystalhd_dio_req
*)temp
;
897 temp
+= sizeof(*dio
);
898 dio
->pages
= (struct page
**)temp
;
899 temp
+= (sizeof(*dio
->pages
) * max_pages
);
900 dio
->sg
= (struct scatterlist
*)temp
;
901 dio
->max_pages
= max_pages
;
902 dio
->fb_va
= pci_pool_alloc(adp
->fill_byte_pool
, GFP_KERNEL
,
905 BCMLOG_ERR("fill byte alloc failed.\n");
909 crystalhd_free_dio(adp
, dio
);
916 * crystalhd_destroy_dio_pool - Release DIO mem pool.
917 * @adp: Adapter instance
922 * This routine releases dio memory pool during close.
924 void crystalhd_destroy_dio_pool(struct crystalhd_adp
*adp
)
926 struct crystalhd_dio_req
*dio
;
930 BCMLOG_ERR("Invalid Arg!!\n");
935 dio
= crystalhd_alloc_dio(adp
);
938 pci_pool_free(adp
->fill_byte_pool
,
939 dio
->fb_va
, dio
->fb_pa
);
945 if (adp
->fill_byte_pool
) {
946 pci_pool_destroy(adp
->fill_byte_pool
);
947 adp
->fill_byte_pool
= NULL
;
950 BCMLOG(BCMLOG_DBG
, "Released dio pool %d\n", count
);
954 * crystalhd_create_elem_pool - List element pool creation.
955 * @adp: Adapter instance
956 * @pool_size: Number of elements in the pool.
959 * 0 - success, <0 error
961 * Create general purpose list element pool to hold pending,
962 * and active requests.
964 int __devinit
crystalhd_create_elem_pool(struct crystalhd_adp
*adp
,
968 struct crystalhd_elem
*temp
;
970 if (!adp
|| !pool_size
)
973 for (i
= 0; i
< pool_size
; i
++) {
974 temp
= kzalloc(sizeof(*temp
), GFP_KERNEL
);
976 BCMLOG_ERR("kalloc failed\n");
979 crystalhd_free_elem(adp
, temp
);
981 BCMLOG(BCMLOG_DBG
, "allocated %d elem\n", pool_size
);
986 * crystalhd_delete_elem_pool - List element pool deletion.
987 * @adp: Adapter instance
992 * Delete general purpose list element pool.
994 void crystalhd_delete_elem_pool(struct crystalhd_adp
*adp
)
996 struct crystalhd_elem
*temp
;
1003 temp
= crystalhd_alloc_elem(adp
);
1010 BCMLOG(BCMLOG_DBG
, "released %d elem\n", dbg_cnt
);
1013 /*================ Debug support routines.. ================================*/
1014 void crystalhd_show_buffer(uint32_t off
, uint8_t *buff
, uint32_t dwcount
)
1018 for (i
= 0; i
< dwcount
; i
++) {
1020 BCMLOG(BCMLOG_DATA
, "0x%08X : ", off
);
1022 BCMLOG(BCMLOG_DATA
, " 0x%08X ", *((uint32_t *)buff
));
1024 buff
+= sizeof(uint32_t);
1025 off
+= sizeof(uint32_t);
1027 if ((i
== dwcount
- 1) || (k
> 4)) {
1028 BCMLOG(BCMLOG_DATA
, "\n");