diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/staging/crystalhd/crystalhd_misc.c | 1044 |
1 files changed, 0 insertions, 1044 deletions
diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c deleted file mode 100644 index 3aabf75b7d97..000000000000 --- a/drivers/staging/crystalhd/crystalhd_misc.c +++ /dev/null @@ -1,1044 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2005-2009, Broadcom Corporation. - * - * Name: crystalhd_misc . c - * - * Description: - * BCM70012 Linux driver misc routines. - * - * HISTORY: - * - ********************************************************************** - * This file is part of the crystalhd device driver. - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This driver is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this driver. If not, see <http://www.gnu.org/licenses/>. - **********************************************************************/ - -#include "crystalhd.h" - -#include <linux/slab.h> - -uint32_t g_linklog_level; - -static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp, - uint32_t mem_off) -{ - crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19)); - return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF))); -} - -static inline void crystalhd_dram_wr(struct crystalhd_adp *adp, - uint32_t mem_off, uint32_t val) -{ - crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19)); - bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val); -} - -static inline enum BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp, - uint32_t start_off, uint32_t cnt) -{ - return BC_STS_SUCCESS; -} - -static struct crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp) -{ - unsigned long flags = 0; - struct crystalhd_dio_req *temp = NULL; - - if (!adp) { - BCMLOG_ERR("Invalid Arg!!\n"); - return temp; - } - - spin_lock_irqsave(&adp->lock, flags); - temp = adp->ua_map_free_head; - if (temp) - adp->ua_map_free_head = adp->ua_map_free_head->next; - spin_unlock_irqrestore(&adp->lock, flags); - - return temp; -} - -static void crystalhd_free_dio(struct crystalhd_adp *adp, - struct crystalhd_dio_req *dio) -{ - unsigned long flags = 0; - - if (!adp || !dio) - return; - spin_lock_irqsave(&adp->lock, flags); - dio->sig = crystalhd_dio_inv; - dio->page_cnt = 0; - dio->fb_size = 0; - memset(&dio->uinfo, 0, sizeof(dio->uinfo)); - dio->next = adp->ua_map_free_head; - adp->ua_map_free_head = dio; - spin_unlock_irqrestore(&adp->lock, flags); -} - -static struct crystalhd_elem *crystalhd_alloc_elem(struct crystalhd_adp *adp) -{ - unsigned long flags = 0; - struct crystalhd_elem *temp = NULL; - - if (!adp) - return temp; - spin_lock_irqsave(&adp->lock, flags); - temp = adp->elem_pool_head; - if (temp) { - adp->elem_pool_head = adp->elem_pool_head->flink; - memset(temp, 0, sizeof(*temp)); - } - spin_unlock_irqrestore(&adp->lock, flags); - - return temp; -} -static void crystalhd_free_elem(struct crystalhd_adp *adp, - struct crystalhd_elem *elem) -{ - unsigned long flags = 0; - - if (!adp || !elem) - return; - spin_lock_irqsave(&adp->lock, flags); - elem->flink = adp->elem_pool_head; - adp->elem_pool_head = elem; - spin_unlock_irqrestore(&adp->lock, flags); -} - -static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page, - unsigned int len, unsigned int offset) -{ - sg_set_page(sg, page, len, offset); -#ifdef CONFIG_X86_64 - sg->dma_length = len; -#endif -} - -static inline void crystalhd_init_sg(struct scatterlist *sg, - unsigned int entries) -{ - /* http://lkml.org/lkml/2007/11/27/68 */ - sg_init_table(sg, entries); -} - -/*========================== Extern ========================================*/ -/** - * bc_dec_reg_rd - Read 7412's device register. - * @adp: Adapter instance - * @reg_off: Register offset. - * - * Return: - * 32bit value read - * - * 7412's device register read routine. This interface use - * 7412's device access range mapped from BAR-2 (4M) of PCIe - * configuration space. - */ -uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off) -{ - if (!adp || (reg_off > adp->pci_mem_len)) { - BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off); - return 0; - } - - return readl(adp->addr + reg_off); -} - -/** - * bc_dec_reg_wr - Write 7412's device register - * @adp: Adapter instance - * @reg_off: Register offset. - * @val: Dword value to be written. - * - * Return: - * none. - * - * 7412's device register write routine. This interface use - * 7412's device access range mapped from BAR-2 (4M) of PCIe - * configuration space. - */ -void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val) -{ - if (!adp || (reg_off > adp->pci_mem_len)) { - BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off); - return; - } - writel(val, adp->addr + reg_off); - udelay(8); -} - -/** - * crystalhd_reg_rd - Read Link's device register. - * @adp: Adapter instance - * @reg_off: Register offset. - * - * Return: - * 32bit value read - * - * Link device register read routine. This interface use - * Link's device access range mapped from BAR-1 (64K) of PCIe - * configuration space. - * - */ -uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off) -{ - if (!adp || (reg_off > adp->pci_i2o_len)) { - BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off); - return 0; - } - return readl(adp->i2o_addr + reg_off); -} - -/** - * crystalhd_reg_wr - Write Link's device register - * @adp: Adapter instance - * @reg_off: Register offset. - * @val: Dword value to be written. - * - * Return: - * none. - * - * Link device register write routine. This interface use - * Link's device access range mapped from BAR-1 (64K) of PCIe - * configuration space. - * - */ -void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, - uint32_t val) -{ - if (!adp || (reg_off > adp->pci_i2o_len)) { - BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off); - return; - } - writel(val, adp->i2o_addr + reg_off); -} - -/** - * crystalhd_mem_rd - Read data from 7412's DRAM area. - * @adp: Adapter instance - * @start_off: Start offset. - * @dw_cnt: Count in dwords. - * @rd_buff: Buffer to copy the data from dram. - * - * Return: - * Status. - * - * 7412's Dram read routine. - */ -enum BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off, - uint32_t dw_cnt, uint32_t *rd_buff) -{ - uint32_t ix = 0; - - if (!adp || !rd_buff || - (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) { - BCMLOG_ERR("Invalid arg\n"); - return BC_STS_INV_ARG; - } - for (ix = 0; ix < dw_cnt; ix++) - rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4))); - - return BC_STS_SUCCESS; -} - -/** - * crystalhd_mem_wr - Write data to 7412's DRAM area. - * @adp: Adapter instance - * @start_off: Start offset. - * @dw_cnt: Count in dwords. - * @wr_buff: Data Buffer to be written. - * - * Return: - * Status. - * - * 7412's Dram write routine. - */ -enum BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off, - uint32_t dw_cnt, uint32_t *wr_buff) -{ - uint32_t ix = 0; - - if (!adp || !wr_buff || - (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) { - BCMLOG_ERR("Invalid arg\n"); - return BC_STS_INV_ARG; - } - - for (ix = 0; ix < dw_cnt; ix++) - crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]); - - return BC_STS_SUCCESS; -} -/** - * crystalhd_pci_cfg_rd - PCIe config read - * @adp: Adapter instance - * @off: PCI config space offset. - * @len: Size -- Byte, Word & dword. - * @val: Value read - * - * Return: - * Status. - * - * Get value from Link's PCIe config space. - */ -enum BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off, - uint32_t len, uint32_t *val) -{ - enum BC_STATUS sts = BC_STS_SUCCESS; - int rc = 0; - - if (!adp || !val) { - BCMLOG_ERR("Invalid arg\n"); - return BC_STS_INV_ARG; - } - - switch (len) { - case 1: - rc = pci_read_config_byte(adp->pdev, off, (u8 *)val); - break; - case 2: - rc = pci_read_config_word(adp->pdev, off, (u16 *)val); - break; - case 4: - rc = pci_read_config_dword(adp->pdev, off, (u32 *)val); - break; - default: - rc = -EINVAL; - sts = BC_STS_INV_ARG; - BCMLOG_ERR("Invalid len:%d\n", len); - } - - if (rc && (sts == BC_STS_SUCCESS)) - sts = BC_STS_ERROR; - - return sts; -} - -/** - * crystalhd_pci_cfg_wr - PCIe config write - * @adp: Adapter instance - * @off: PCI config space offset. - * @len: Size -- Byte, Word & dword. - * @val: Value to be written - * - * Return: - * Status. - * - * Set value to Link's PCIe config space. - */ -enum BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off, - uint32_t len, uint32_t val) -{ - enum BC_STATUS sts = BC_STS_SUCCESS; - int rc = 0; - - if (!adp || !val) { - BCMLOG_ERR("Invalid arg\n"); - return BC_STS_INV_ARG; - } - - switch (len) { - case 1: - rc = pci_write_config_byte(adp->pdev, off, (u8)val); - break; - case 2: - rc = pci_write_config_word(adp->pdev, off, (u16)val); - break; - case 4: - rc = pci_write_config_dword(adp->pdev, off, val); - break; - default: - rc = -EINVAL; - sts = BC_STS_INV_ARG; - BCMLOG_ERR("Invalid len:%d\n", len); - } - - if (rc && (sts == BC_STS_SUCCESS)) - sts = BC_STS_ERROR; - - return sts; -} - -/** - * bc_kern_dma_alloc - Allocate memory for Dma rings - * @adp: Adapter instance - * @sz: Size of the memory to allocate. - * @phy_addr: Physical address of the memory allocated. - * Typedef to system's dma_addr_t (u64) - * - * Return: - * Pointer to allocated memory.. - * - * Wrapper to Linux kernel interface. - * - */ -void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz, - dma_addr_t *phy_addr) -{ - void *temp = NULL; - - if (!adp || !sz || !phy_addr) { - BCMLOG_ERR("Invalid Arg..\n"); - return temp; - } - - temp = pci_alloc_consistent(adp->pdev, sz, phy_addr); - if (temp) - memset(temp, 0, sz); - - return temp; -} - -/** - * bc_kern_dma_free - Release Dma ring memory. - * @adp: Adapter instance - * @sz: Size of the memory to allocate. - * @ka: Kernel virtual address returned during _dio_alloc() - * @phy_addr: Physical address of the memory allocated. - * Typedef to system's dma_addr_t (u64) - * - * Return: - * none. - */ -void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka, - dma_addr_t phy_addr) -{ - if (!adp || !ka || !sz || !phy_addr) { - BCMLOG_ERR("Invalid Arg..\n"); - return; - } - - pci_free_consistent(adp->pdev, sz, ka, phy_addr); -} - -/** - * crystalhd_create_dioq - Create Generic DIO queue - * @adp: Adapter instance - * @dioq_hnd: Handle to the dio queue created - * @cb : Optional - Call back To free the element. - * @cbctx: Context to pass to callback. - * - * Return: - * status - * - * Initialize Generic DIO queue to hold any data. Callback - * will be used to free elements while deleting the queue. - */ -enum BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp, - struct crystalhd_dioq **dioq_hnd, - crystalhd_data_free_cb cb, void *cbctx) -{ - struct crystalhd_dioq *dioq = NULL; - - if (!adp || !dioq_hnd) { - BCMLOG_ERR("Invalid arg!!\n"); - return BC_STS_INV_ARG; - } - - dioq = kzalloc(sizeof(*dioq), GFP_KERNEL); - if (!dioq) - return BC_STS_INSUFF_RES; - - spin_lock_init(&dioq->lock); - dioq->sig = BC_LINK_DIOQ_SIG; - dioq->head = (struct crystalhd_elem *)&dioq->head; - dioq->tail = (struct crystalhd_elem *)&dioq->head; - crystalhd_create_event(&dioq->event); - dioq->adp = adp; - dioq->data_rel_cb = cb; - dioq->cb_context = cbctx; - *dioq_hnd = dioq; - - return BC_STS_SUCCESS; -} - -/** - * crystalhd_delete_dioq - Delete Generic DIO queue - * @adp: Adapter instance - * @dioq: DIOQ instance.. - * - * Return: - * None. - * - * Release Generic DIO queue. This function will remove - * all the entries from the Queue and will release data - * by calling the call back provided during creation. - * - */ -void crystalhd_delete_dioq(struct crystalhd_adp *adp, - struct crystalhd_dioq *dioq) -{ - void *temp; - - if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG)) - return; - - do { - temp = crystalhd_dioq_fetch(dioq); - if (temp && dioq->data_rel_cb) - dioq->data_rel_cb(dioq->cb_context, temp); - } while (temp); - dioq->sig = 0; - kfree(dioq); -} - -/** - * crystalhd_dioq_add - Add new DIO request element. - * @ioq: DIO queue instance - * @t: DIO request to be added. - * @wake: True - Wake up suspended process. - * @tag: Special tag to assign - For search and get. - * - * Return: - * Status. - * - * Insert new element to Q tail. - */ -enum BC_STATUS crystalhd_dioq_add(struct crystalhd_dioq *ioq, void *data, - bool wake, uint32_t tag) -{ - unsigned long flags = 0; - struct crystalhd_elem *tmp; - - if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) { - BCMLOG_ERR("Invalid arg!!\n"); - return BC_STS_INV_ARG; - } - - tmp = crystalhd_alloc_elem(ioq->adp); - if (!tmp) { - BCMLOG_ERR("No free elements.\n"); - return BC_STS_INSUFF_RES; - } - - tmp->data = data; - tmp->tag = tag; - spin_lock_irqsave(&ioq->lock, flags); - tmp->flink = (struct crystalhd_elem *)&ioq->head; - tmp->blink = ioq->tail; - tmp->flink->blink = tmp; - tmp->blink->flink = tmp; - ioq->count++; - spin_unlock_irqrestore(&ioq->lock, flags); - - if (wake) - crystalhd_set_event(&ioq->event); - - return BC_STS_SUCCESS; -} - -/** - * crystalhd_dioq_fetch - Fetch element from head. - * @ioq: DIO queue instance - * - * Return: - * data element from the head.. - * - * Remove an element from Queue. - */ -void *crystalhd_dioq_fetch(struct crystalhd_dioq *ioq) -{ - unsigned long flags = 0; - struct crystalhd_elem *tmp; - struct crystalhd_elem *ret = NULL; - void *data = NULL; - - if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) { - BCMLOG_ERR("Invalid arg!!\n"); - return data; - } - - spin_lock_irqsave(&ioq->lock, flags); - tmp = ioq->head; - if (tmp != (struct crystalhd_elem *)&ioq->head) { - ret = tmp; - tmp->flink->blink = tmp->blink; - tmp->blink->flink = tmp->flink; - ioq->count--; - } - spin_unlock_irqrestore(&ioq->lock, flags); - if (ret) { - data = ret->data; - crystalhd_free_elem(ioq->adp, ret); - } - - return data; -} -/** - * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element - * @ioq: DIO queue instance - * @tag: Tag to search for. - * - * Return: - * element from the head.. - * - * Search TAG and remove the element. - */ -void *crystalhd_dioq_find_and_fetch(struct crystalhd_dioq *ioq, uint32_t tag) -{ - unsigned long flags = 0; - struct crystalhd_elem *tmp; - struct crystalhd_elem *ret = NULL; - void *data = NULL; - - if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) { - BCMLOG_ERR("Invalid arg!!\n"); - return data; - } - - spin_lock_irqsave(&ioq->lock, flags); - tmp = ioq->head; - while (tmp != (struct crystalhd_elem *)&ioq->head) { - if (tmp->tag == tag) { - ret = tmp; - tmp->flink->blink = tmp->blink; - tmp->blink->flink = tmp->flink; - ioq->count--; - break; - } - tmp = tmp->flink; - } - spin_unlock_irqrestore(&ioq->lock, flags); - - if (ret) { - data = ret->data; - crystalhd_free_elem(ioq->adp, ret); - } - - return data; -} - -/** - * crystalhd_dioq_fetch_wait - Fetch element from Head. - * @ioq: DIO queue instance - * @to_secs: Wait timeout in seconds.. - * - * Return: - * element from the head.. - * - * Return element from head if Q is not empty. Wait for new element - * if Q is empty for Timeout seconds. - */ -void *crystalhd_dioq_fetch_wait(struct crystalhd_dioq *ioq, uint32_t to_secs, - uint32_t *sig_pend) -{ - unsigned long flags = 0; - int rc = 0, count; - void *tmp = NULL; - - if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) { - BCMLOG_ERR("Invalid arg!!\n"); - return tmp; - } - - count = to_secs; - spin_lock_irqsave(&ioq->lock, flags); - while ((ioq->count == 0) && count) { - spin_unlock_irqrestore(&ioq->lock, flags); - - crystalhd_wait_on_event(&ioq->event, - (ioq->count > 0), 1000, rc, 0); - if (rc == 0) { - goto out; - } else if (rc == -EINTR) { - BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n"); - *sig_pend = 1; - return tmp; - } - spin_lock_irqsave(&ioq->lock, flags); - count--; - } - spin_unlock_irqrestore(&ioq->lock, flags); - -out: - return crystalhd_dioq_fetch(ioq); -} - -/** - * crystalhd_map_dio - Map user address for DMA - * @adp: Adapter instance - * @ubuff: User buffer to map. - * @ubuff_sz: User buffer size. - * @uv_offset: UV buffer offset. - * @en_422mode: TRUE:422 FALSE:420 Capture mode. - * @dir_tx: TRUE for Tx (To device from host) - * @dio_hnd: Handle to mapped DIO request. - * - * Return: - * Status. - * - * This routine maps user address and lock pages for DMA. - * - */ -enum BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff, - uint32_t ubuff_sz, uint32_t uv_offset, - bool en_422mode, bool dir_tx, - struct crystalhd_dio_req **dio_hnd) -{ - struct crystalhd_dio_req *dio; - /* FIXME: jarod: should some of these - unsigned longs be uint32_t or uintptr_t? */ - unsigned long start = 0, end = 0, uaddr = 0, count = 0; - unsigned long spsz = 0, uv_start = 0; - int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0; - - if (!adp || !ubuff || !ubuff_sz || !dio_hnd) { - BCMLOG_ERR("Invalid arg\n"); - return BC_STS_INV_ARG; - } - /* Compute pages */ - uaddr = (unsigned long)ubuff; - count = (unsigned long)ubuff_sz; - end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; - start = uaddr >> PAGE_SHIFT; - nr_pages = end - start; - - if (!count || ((uaddr + count) < uaddr)) { - BCMLOG_ERR("User addr overflow!!\n"); - return BC_STS_INV_ARG; - } - - dio = crystalhd_alloc_dio(adp); - if (!dio) { - BCMLOG_ERR("dio pool empty..\n"); - return BC_STS_INSUFF_RES; - } - - if (dir_tx) { - rw = WRITE; - dio->direction = DMA_TO_DEVICE; - } else { - rw = READ; - dio->direction = DMA_FROM_DEVICE; - } - - if (nr_pages > dio->max_pages) { - BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n", - dio->max_pages, nr_pages); - crystalhd_unmap_dio(adp, dio); - return BC_STS_INSUFF_RES; - } - - if (uv_offset) { - uv_start = (uaddr + (unsigned long)uv_offset) >> PAGE_SHIFT; - dio->uinfo.uv_sg_ix = uv_start - start; - dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) & - ~PAGE_MASK); - } - - dio->fb_size = ubuff_sz & 0x03; - if (dio->fb_size) { - res = copy_from_user(dio->fb_va, - (void __user *)(uaddr + count - dio->fb_size), - dio->fb_size); - if (res) { - BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n", - res, dio->fb_size, - (void *)(uaddr + count-dio->fb_size)); - crystalhd_unmap_dio(adp, dio); - return BC_STS_INSUFF_RES; - } - } - - down_read(¤t->mm->mmap_sem); - res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ, - 0, dio->pages, NULL); - up_read(¤t->mm->mmap_sem); - - /* Save for release..*/ - dio->sig = crystalhd_dio_locked; - if (res < nr_pages) { - BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res); - dio->page_cnt = res; - crystalhd_unmap_dio(adp, dio); - return BC_STS_ERROR; - } - - dio->page_cnt = nr_pages; - /* Get scatter/gather */ - crystalhd_init_sg(dio->sg, dio->page_cnt); - crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK); - if (nr_pages > 1) { - dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset; - -#ifdef CONFIG_X86_64 - dio->sg[0].dma_length = dio->sg[0].length; -#endif - count -= dio->sg[0].length; - for (i = 1; i < nr_pages; i++) { - if (count < 4) { - spsz = count; - skip_fb_sg = 1; - } else { - spsz = (count < PAGE_SIZE) ? - (count & ~0x03) : PAGE_SIZE; - } - crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0); - count -= spsz; - } - } else { - if (count < 4) { - dio->sg[0].length = count; - skip_fb_sg = 1; - } else { - dio->sg[0].length = count - dio->fb_size; - } -#ifdef CONFIG_X86_64 - dio->sg[0].dma_length = dio->sg[0].length; -#endif - } - dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg, - dio->page_cnt, dio->direction); - if (dio->sg_cnt <= 0) { - BCMLOG_ERR("sg map %d-%d\n", dio->sg_cnt, dio->page_cnt); - crystalhd_unmap_dio(adp, dio); - return BC_STS_ERROR; - } - if (dio->sg_cnt && skip_fb_sg) - dio->sg_cnt -= 1; - dio->sig = crystalhd_dio_sg_mapped; - /* Fill in User info.. */ - dio->uinfo.xfr_len = ubuff_sz; - dio->uinfo.xfr_buff = ubuff; - dio->uinfo.uv_offset = uv_offset; - dio->uinfo.b422mode = en_422mode; - dio->uinfo.dir_tx = dir_tx; - - *dio_hnd = dio; - - return BC_STS_SUCCESS; -} - -/** - * crystalhd_unmap_sgl - Release mapped resources - * @adp: Adapter instance - * @dio: DIO request instance - * - * Return: - * Status. - * - * This routine is to unmap the user buffer pages. - */ -enum BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp, - struct crystalhd_dio_req *dio) -{ - struct page *page = NULL; - int j = 0; - - if (!adp || !dio) { - BCMLOG_ERR("Invalid arg\n"); - return BC_STS_INV_ARG; - } - - if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) { - for (j = 0; j < dio->page_cnt; j++) { - page = dio->pages[j]; - if (page) { - if (!PageReserved(page) && - (dio->direction == DMA_FROM_DEVICE)) - SetPageDirty(page); - page_cache_release(page); - } - } - } - if (dio->sig == crystalhd_dio_sg_mapped) - pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt, - dio->direction); - - crystalhd_free_dio(adp, dio); - - return BC_STS_SUCCESS; -} - -/** - * crystalhd_create_dio_pool - Allocate mem pool for DIO management. - * @adp: Adapter instance - * @max_pages: Max pages for size calculation. - * - * Return: - * system error. - * - * This routine creates a memory pool to hold dio context for - * for HW Direct IO operation. - */ -int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages) -{ - uint32_t asz = 0, i = 0; - uint8_t *temp; - struct crystalhd_dio_req *dio; - - if (!adp || !max_pages) { - BCMLOG_ERR("Invalid Arg!!\n"); - return -EINVAL; - } - - /* Get dma memory for fill byte handling..*/ - adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte", - adp->pdev, 8, 8, 0); - if (!adp->fill_byte_pool) { - BCMLOG_ERR("failed to create fill byte pool\n"); - return -ENOMEM; - } - - /* Get the max size from user based on 420/422 modes */ - asz = (sizeof(*dio->pages) * max_pages) + - (sizeof(*dio->sg) * max_pages) + sizeof(*dio); - - BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n", - BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool); - - for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) { - temp = kzalloc(asz, GFP_KERNEL); - if ((temp) == NULL) { - BCMLOG_ERR("Failed to alloc %d mem\n", asz); - return -ENOMEM; - } - - dio = (struct crystalhd_dio_req *)temp; - temp += sizeof(*dio); - dio->pages = (struct page **)temp; - temp += (sizeof(*dio->pages) * max_pages); - dio->sg = (struct scatterlist *)temp; - dio->max_pages = max_pages; - dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL, - &dio->fb_pa); - if (!dio->fb_va) { - BCMLOG_ERR("fill byte alloc failed.\n"); - return -ENOMEM; - } - - crystalhd_free_dio(adp, dio); - } - - return 0; -} - -/** - * crystalhd_destroy_dio_pool - Release DIO mem pool. - * @adp: Adapter instance - * - * Return: - * none. - * - * This routine releases dio memory pool during close. - */ -void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp) -{ - struct crystalhd_dio_req *dio; - int count = 0; - - if (!adp) { - BCMLOG_ERR("Invalid Arg!!\n"); - return; - } - - do { - dio = crystalhd_alloc_dio(adp); - if (dio) { - if (dio->fb_va) - pci_pool_free(adp->fill_byte_pool, - dio->fb_va, dio->fb_pa); - count++; - kfree(dio); - } - } while (dio); - - if (adp->fill_byte_pool) { - pci_pool_destroy(adp->fill_byte_pool); - adp->fill_byte_pool = NULL; - } - - BCMLOG(BCMLOG_DBG, "Released dio pool %d\n", count); -} - -/** - * crystalhd_create_elem_pool - List element pool creation. - * @adp: Adapter instance - * @pool_size: Number of elements in the pool. - * - * Return: - * 0 - success, <0 error - * - * Create general purpose list element pool to hold pending, - * and active requests. - */ -int crystalhd_create_elem_pool(struct crystalhd_adp *adp, - uint32_t pool_size) -{ - uint32_t i; - struct crystalhd_elem *temp; - - if (!adp || !pool_size) - return -EINVAL; - - for (i = 0; i < pool_size; i++) { - temp = kzalloc(sizeof(*temp), GFP_KERNEL); - if (!temp) { - BCMLOG_ERR("kalloc failed\n"); - return -ENOMEM; - } - crystalhd_free_elem(adp, temp); - } - BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size); - return 0; -} - -/** - * crystalhd_delete_elem_pool - List element pool deletion. - * @adp: Adapter instance - * - * Return: - * none - * - * Delete general purpose list element pool. - */ -void crystalhd_delete_elem_pool(struct crystalhd_adp *adp) -{ - struct crystalhd_elem *temp; - int dbg_cnt = 0; - - if (!adp) - return; - - do { - temp = crystalhd_alloc_elem(adp); - if (temp) { - kfree(temp); - dbg_cnt++; - } - } while (temp); - - BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt); -} - -/*================ Debug support routines.. ================================*/ -void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount) -{ - uint32_t i, k = 1; - - for (i = 0; i < dwcount; i++) { - if (k == 1) - BCMLOG(BCMLOG_DATA, "0x%08X : ", off); - - BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff)); - - buff += sizeof(uint32_t); - off += sizeof(uint32_t); - k++; - if ((i == dwcount - 1) || (k > 4)) { - BCMLOG(BCMLOG_DATA, "\n"); - k = 1; - } - } -} |