diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2019-01-22 02:47:23 -0800 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2019-01-22 02:47:23 -0800 |
commit | 6bb42bc6259b5549d6ca6cb655cd5d7aec65a5de (patch) | |
tree | f8890cacaef4e07ca0ad0cc3c9ea4193e7331075 | |
parent | d89b07f7fa015c63937d29a3443e776e83d614a5 (diff) | |
parent | d6def77b82151788b2fe7ecb0406b780a5ea8fde (diff) |
Merge d6def77b82151788b2fe7ecb0406b780a5ea8fde on remote branchLA.UM.6.3.r7-01200-sdm845.0
Change-Id: I3c365d632047ef2a073abfafbe1da930dab33f2e
138 files changed, 3853 insertions, 1996 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 87a98bc70af3..cce7a4c0cb8c 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -84,6 +84,7 @@ config ARM64 select HAVE_FUNCTION_GRAPH_TRACER select HAVE_GCC_PLUGINS select HAVE_GENERIC_DMA_COHERENT + select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_IRQ_TIME_ACCOUNTING select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP if NUMA diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig index b6b66117035c..eaa56a4bdf6f 100644 --- a/arch/arm64/configs/sdm845-perf_defconfig +++ b/arch/arm64/configs/sdm845-perf_defconfig @@ -225,6 +225,7 @@ CONFIG_NET_ACT_SKBEDIT=y CONFIG_RMNET_DATA=y CONFIG_RMNET_DATA_FC=y CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y CONFIG_CFG80211=y diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig index 69efd3b281ad..8c569a365b11 100644 --- a/arch/arm64/configs/sdm845_defconfig +++ b/arch/arm64/configs/sdm845_defconfig @@ -230,6 +230,7 @@ CONFIG_DNS_RESOLVER=y CONFIG_RMNET_DATA=y CONFIG_RMNET_DATA_FC=y CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y CONFIG_CFG80211=y diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 1ef2f68bfcb2..a9ae0620eb8a 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -465,8 +465,9 @@ struct binder_ref { }; enum binder_deferred_state { - BINDER_DEFERRED_FLUSH = 0x01, - BINDER_DEFERRED_RELEASE = 0x02, + BINDER_DEFERRED_PUT_FILES = 0x01, + BINDER_DEFERRED_FLUSH = 0x02, + BINDER_DEFERRED_RELEASE = 0x04, }; /** @@ -503,6 +504,9 @@ struct binder_priority { * (invariant after initialized) * @tsk task_struct for group_leader of process * (invariant after initialized) + * @files files_struct for process + * (protected by @files_lock) + * @files_lock mutex to protect @files * @deferred_work_node: element for binder_deferred_list * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform @@ -549,6 +553,8 @@ struct binder_proc { struct list_head waiting_threads; int pid; struct task_struct *tsk; + struct files_struct *files; + struct mutex files_lock; struct hlist_node deferred_work_node; int deferred_work; bool is_dead; @@ -944,33 +950,27 @@ static void binder_free_thread(struct binder_thread *thread); static void binder_free_proc(struct binder_proc *proc); static void binder_inc_node_tmpref_ilocked(struct binder_node *node); -struct files_struct *binder_get_files_struct(struct binder_proc *proc) -{ - return get_files_struct(proc->tsk); -} - static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) { - struct files_struct *files; unsigned long rlim_cur; unsigned long irqs; int ret; - files = binder_get_files_struct(proc); - if (files == NULL) - return -ESRCH; - + mutex_lock(&proc->files_lock); + if (proc->files == NULL) { + ret = -ESRCH; + goto err; + } if (!lock_task_sighand(proc->tsk, &irqs)) { ret = -EMFILE; goto err; } - rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE); unlock_task_sighand(proc->tsk, &irqs); - ret = __alloc_fd(files, 0, rlim_cur, flags); + ret = __alloc_fd(proc->files, 0, rlim_cur, flags); err: - put_files_struct(files); + mutex_unlock(&proc->files_lock); return ret; } @@ -980,12 +980,10 @@ err: static void task_fd_install( struct binder_proc *proc, unsigned int fd, struct file *file) { - struct files_struct *files = binder_get_files_struct(proc); - - if (files) { - __fd_install(files, fd, file); - put_files_struct(files); - } + mutex_lock(&proc->files_lock); + if (proc->files) + __fd_install(proc->files, fd, file); + mutex_unlock(&proc->files_lock); } /* @@ -993,21 +991,22 @@ static void task_fd_install( */ static long task_close_fd(struct binder_proc *proc, unsigned int fd) { - struct files_struct *files = binder_get_files_struct(proc); int retval; - if (files == NULL) - return -ESRCH; - - retval = __close_fd(files, fd); + mutex_lock(&proc->files_lock); + if (proc->files == NULL) { + retval = -ESRCH; + goto err; + } + retval = __close_fd(proc->files, fd); /* can't restart close syscall because file table entry was cleared */ if (unlikely(retval == -ERESTARTSYS || retval == -ERESTARTNOINTR || retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK)) retval = -EINTR; - put_files_struct(files); - +err: + mutex_unlock(&proc->files_lock); return retval; } @@ -4831,6 +4830,7 @@ static void binder_vma_close(struct vm_area_struct *vma) (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, (unsigned long)pgprot_val(vma->vm_page_prot)); binder_alloc_vma_close(&proc->alloc); + binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES); } static int binder_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -4872,8 +4872,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = proc; ret = binder_alloc_mmap_handler(&proc->alloc, vma); - - return ret; + if (ret) + return ret; + mutex_lock(&proc->files_lock); + proc->files = get_files_struct(current); + mutex_unlock(&proc->files_lock); + return 0; err_bad_arg: pr_err("binder_mmap: %d %lx-%lx %s failed %d\n", @@ -4896,6 +4900,7 @@ static int binder_open(struct inode *nodp, struct file *filp) spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); proc->tsk = current->group_leader; + mutex_init(&proc->files_lock); INIT_LIST_HEAD(&proc->todo); if (binder_supported_policy(current->policy)) { proc->default_priority.sched_policy = current->policy; @@ -5052,6 +5057,8 @@ static void binder_deferred_release(struct binder_proc *proc) struct rb_node *n; int threads, nodes, incoming_refs, outgoing_refs, active_transactions; + BUG_ON(proc->files); + mutex_lock(&binder_procs_lock); hlist_del(&proc->proc_node); mutex_unlock(&binder_procs_lock); @@ -5133,6 +5140,8 @@ static void binder_deferred_release(struct binder_proc *proc) static void binder_deferred_func(struct work_struct *work) { struct binder_proc *proc; + struct files_struct *files; + int defer; do { @@ -5149,11 +5158,23 @@ static void binder_deferred_func(struct work_struct *work) } mutex_unlock(&binder_deferred_lock); + files = NULL; + if (defer & BINDER_DEFERRED_PUT_FILES) { + mutex_lock(&proc->files_lock); + files = proc->files; + if (files) + proc->files = NULL; + mutex_unlock(&proc->files_lock); + } + if (defer & BINDER_DEFERRED_FLUSH) binder_deferred_flush(proc); if (defer & BINDER_DEFERRED_RELEASE) binder_deferred_release(proc); /* frees proc */ + + if (files) + put_files_struct(files); } while (proc); } static DECLARE_WORK(binder_deferred_work, binder_deferred_func); diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 6c867fbc56a7..688a0b0d93a4 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -231,11 +231,11 @@ static void qca_wq_awake_device(struct work_struct *work) BT_DBG("hu %p wq awake device", hu); + spin_lock(&qca->hci_ibs_lock); + /* Vote for serial clock */ serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu); - spin_lock(&qca->hci_ibs_lock); - /* Send wake indication to device */ if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) BT_ERR("Failed to send WAKE to device"); @@ -260,9 +260,10 @@ static void qca_wq_awake_rx(struct work_struct *work) BT_DBG("hu %p wq awake rx", hu); + spin_lock(&qca->hci_ibs_lock); + serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu); - spin_lock(&qca->hci_ibs_lock); qca->rx_ibs_state = HCI_IBS_RX_AWAKE; /* Always acknowledge device wake up, @@ -287,7 +288,11 @@ static void qca_wq_serial_rx_clock_vote_off(struct work_struct *work) BT_DBG("hu %p rx clock vote off", hu); + spin_lock(&qca->hci_ibs_lock); + serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu); + + spin_unlock(&qca->hci_ibs_lock); } static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work) @@ -298,6 +303,8 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work) BT_DBG("hu %p tx clock vote off", hu); + spin_lock(&qca->hci_ibs_lock); + /* Run HCI tx handling unlocked */ hci_uart_tx_wakeup(hu); @@ -305,6 +312,8 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work) * It is up to the tty driver to pend the clocks off until tx done. */ serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu); + + spin_unlock(&qca->hci_ibs_lock); } static void hci_ibs_tx_idle_timeout(unsigned long arg) @@ -520,8 +529,12 @@ static int qca_close(struct hci_uart *hu) BT_DBG("hu %p qca close", hu); + spin_lock(&qca->hci_ibs_lock); + serial_clock_vote(HCI_IBS_VOTE_STATS_UPDATE, hu); + spin_unlock(&qca->hci_ibs_lock); + skb_queue_purge(&qca->tx_wait_q); skb_queue_purge(&qca->txq); del_timer(&qca->tx_idle_timer); diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index b8ec3d4c2fbd..9851bcff982b 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -55,6 +55,7 @@ #define TZ_PIL_AUTH_QDSP6_PROC 1 #define ADSP_MMAP_HEAP_ADDR 4 #define ADSP_MMAP_REMOTE_HEAP_ADDR 8 +#define ADSP_MMAP_ADD_PAGES 0x1000 #define FASTRPC_DMAHANDLE_NOMAP (16) #define FASTRPC_ENOSUCH 39 @@ -173,10 +174,15 @@ struct fastrpc_file; struct fastrpc_buf { struct hlist_node hn; + struct hlist_node hn_rem; struct fastrpc_file *fl; void *virt; uint64_t phys; size_t size; + unsigned long dma_attr; + uintptr_t raddr; + uint32_t flags; + int remote; }; struct fastrpc_ctx_lst; @@ -333,9 +339,11 @@ struct fastrpc_file { struct hlist_node hn; spinlock_t hlock; struct hlist_head maps; - struct hlist_head bufs; + struct hlist_head cached_bufs; + struct hlist_head remote_bufs; struct fastrpc_ctx_lst clst; struct fastrpc_session_ctx *sctx; + struct fastrpc_buf *init_mem; struct fastrpc_session_ctx *secsctx; uint32_t mode; uint32_t profile; @@ -415,10 +423,17 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) return; if (cache) { spin_lock(&fl->hlock); - hlist_add_head(&buf->hn, &fl->bufs); + hlist_add_head(&buf->hn, &fl->cached_bufs); spin_unlock(&fl->hlock); return; } + if (buf->remote) { + spin_lock(&fl->hlock); + hlist_del_init(&buf->hn_rem); + spin_unlock(&fl->hlock); + buf->remote = 0; + buf->raddr = 0; + } if (!IS_ERR_OR_NULL(buf->virt)) { int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; @@ -432,13 +447,13 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) hyp_assign_phys(buf->phys, buf_page_size(buf->size), srcVM, 2, destVM, destVMperm, 1); } - dma_free_coherent(fl->sctx->smmu.dev, buf->size, buf->virt, - buf->phys); + dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt, + buf->phys, buf->dma_attr); } kfree(buf); } -static void fastrpc_buf_list_free(struct fastrpc_file *fl) +static void fastrpc_cached_buf_list_free(struct fastrpc_file *fl) { struct fastrpc_buf *buf, *free; @@ -447,7 +462,7 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl) free = NULL; spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { hlist_del_init(&buf->hn); free = buf; break; @@ -458,6 +473,25 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl) } while (free); } +static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl) +{ + struct fastrpc_buf *buf, *free; + + do { + struct hlist_node *n; + + free = NULL; + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->remote_bufs, hn_rem) { + free = buf; + break; + } + spin_unlock(&fl->hlock); + if (free) + fastrpc_buf_free(free, 0); + } while (free); +} + static void fastrpc_mmap_add(struct fastrpc_mmap *map) { if (map->flags == ADSP_MMAP_HEAP_ADDR || @@ -517,7 +551,8 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, return -ENOTTY; } -static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size) +static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size, + unsigned long dma_attrs) { struct fastrpc_apps *me = &gfa; @@ -525,10 +560,11 @@ static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size) pr_err("device adsprpc-mem is not initialized\n"); return -ENODEV; } - *vaddr = dma_alloc_coherent(me->dev, size, region_phys, GFP_KERNEL); - if (!*vaddr) { - pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n", - (unsigned int)size); + *vaddr = dma_alloc_attrs(me->dev, size, region_phys, GFP_KERNEL, + dma_attrs); + if (IS_ERR_OR_NULL(*vaddr)) { + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx, returned %pK\n", + current->comm, __func__, size, (*vaddr)); return -ENOMEM; } return 0; @@ -600,14 +636,17 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) } if (map->flags == ADSP_MMAP_HEAP_ADDR || map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + unsigned long dma_attrs = 0; if (me->dev == NULL) { pr_err("failed to free remote heap allocation\n"); return; } if (map->phys) { - dma_free_coherent(me->dev, map->size, - (void *)map->va, (dma_addr_t)map->phys); + dma_attrs |= + DMA_ATTR_SKIP_ZEROING | DMA_ATTR_NO_KERNEL_MAPPING; + dma_free_attrs(me->dev, map->size, (void *)map->va, + (dma_addr_t)map->phys, dma_attrs); } } else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) { if (!IS_ERR_OR_NULL(map->handle)) @@ -682,10 +721,14 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, map->attr = attr; if (mflags == ADSP_MMAP_HEAP_ADDR || mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + unsigned long dma_attrs = DMA_ATTR_SKIP_ZEROING | + DMA_ATTR_NO_KERNEL_MAPPING; + map->apps = me; map->fl = NULL; + VERIFY(err, !dma_alloc_memory(®ion_phys, ®ion_vaddr, - len)); + len, dma_attrs)); if (err) goto bail; map->phys = (uintptr_t)region_phys; @@ -824,7 +867,8 @@ bail: } static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, - struct fastrpc_buf **obuf) + unsigned long dma_attr, uint32_t rflags, + int remote, struct fastrpc_buf **obuf) { int err = 0, vmid; struct fastrpc_buf *buf = NULL, *fr = NULL; @@ -834,18 +878,20 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, if (err) goto bail; - /* find the smallest buffer that fits in the cache */ - spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - if (buf->size >= size && (!fr || fr->size > buf->size)) - fr = buf; - } - if (fr) - hlist_del_init(&fr->hn); - spin_unlock(&fl->hlock); - if (fr) { - *obuf = fr; - return 0; + if (!remote) { + /* find the smallest buffer that fits in the cache */ + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { + if (buf->size >= size && (!fr || fr->size > buf->size)) + fr = buf; + } + if (fr) + hlist_del_init(&fr->hn); + spin_unlock(&fl->hlock); + if (fr) { + *obuf = fr; + return 0; + } } buf = NULL; VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL))); @@ -856,17 +902,27 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, buf->virt = NULL; buf->phys = 0; buf->size = size; - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + buf->dma_attr = dma_attr; + buf->flags = rflags; + buf->raddr = 0; + buf->remote = 0; + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, buf->dma_attr); if (IS_ERR_OR_NULL(buf->virt)) { /* free cache and retry */ - fastrpc_buf_list_free(fl); - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + fastrpc_cached_buf_list_free(fl); + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, buf->dma_attr); VERIFY(err, !IS_ERR_OR_NULL(buf->virt)); } - if (err) + if (err) { + err = -ENOMEM; + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx\n", + current->comm, __func__, size); goto bail; + } if (fl->sctx->smmu.cb) buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32); vmid = fl->apps->channel[fl->cid].vmid; @@ -882,6 +938,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, goto bail; } + if (remote) { + INIT_HLIST_NODE(&buf->hn_rem); + spin_lock(&fl->hlock); + hlist_add_head(&buf->hn_rem, &fl->remote_bufs); + spin_unlock(&fl->hlock); + buf->remote = remote; + } *obuf = buf; bail: if (err && buf) @@ -1094,7 +1157,7 @@ static void context_save_interrupted(struct smq_invoke_ctx *ctx) hlist_add_head(&ctx->hn, &clst->interrupted); spin_unlock(&ctx->fl->hlock); /* free the cache on power collapse */ - fastrpc_buf_list_free(ctx->fl); + fastrpc_cached_buf_list_free(ctx->fl); } static void context_free(struct smq_invoke_ctx *ctx) @@ -1317,7 +1380,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) /* allocate new buffer */ if (copylen) { - VERIFY(err, !fastrpc_buf_alloc(ctx->fl, copylen, &ctx->buf)); + err = fastrpc_buf_alloc(ctx->fl, copylen, 0, 0, 0, &ctx->buf); if (err) goto bail; } @@ -1804,6 +1867,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; struct fastrpc_mmap *file = NULL, *mem = NULL; + struct fastrpc_buf *imem = NULL; + unsigned long imem_dma_attr = 0; char *proc_name = NULL; int srcVM[1] = {VMID_HLOS}; int destVM[1] = {me->channel[fl->cid].rhvmid}; @@ -1834,6 +1899,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, remote_arg_t ra[6]; int fds[6]; int mflags = 0; + int memlen; struct { int pgid; unsigned int namelen; @@ -1861,16 +1927,24 @@ static int fastrpc_init_process(struct fastrpc_file *fl, goto bail; } inbuf.pageslen = 1; - VERIFY(err, access_ok(1, (void __user *)init->mem, - init->memlen)); - if (err) + + VERIFY(err, !init->mem); + if (err) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n", + current->comm, __func__); goto bail; - mutex_lock(&fl->fl_map_mutex); - VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0, - init->mem, init->memlen, mflags, &mem)); - mutex_unlock(&fl->fl_map_mutex); + } + memlen = ALIGN(max(1024*1024*3, (int)init->filelen * 4), + 1024*1024); + imem_dma_attr = DMA_ATTR_EXEC_MAPPING | + DMA_ATTR_NO_KERNEL_MAPPING | + DMA_ATTR_FORCE_NON_COHERENT; + err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem); if (err) goto bail; + fl->init_mem = imem; + inbuf.pageslen = 1; ra[0].buf.pv = (void *)&inbuf; ra[0].buf.len = sizeof(inbuf); @@ -1884,8 +1958,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, ra[2].buf.len = inbuf.filelen; fds[2] = init->filefd; - pages[0].addr = mem->phys; - pages[0].size = mem->size; + pages[0].addr = imem->phys; + pages[0].size = imem->size; ra[3].buf.pv = (void *)pages; ra[3].buf.len = 1 * sizeof(*pages); fds[3] = 0; @@ -2046,7 +2120,8 @@ bail: } static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, - struct fastrpc_mmap *map) + uintptr_t va, uint64_t phys, + size_t size, uintptr_t *raddr) { struct fastrpc_ioctl_invoke_crc ioctl; struct fastrpc_apps *me = &gfa; @@ -2065,13 +2140,13 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, } routargs; inargs.pid = fl->tgid; - inargs.vaddrin = (uintptr_t)map->va; + inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; inargs.num = fl->apps->compat ? num * sizeof(page) : num; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); - page.addr = map->phys; - page.size = map->size; + page.addr = phys; + page.size = size; ra[1].buf.pv = (void *)&page; ra[1].buf.len = num * sizeof(page); @@ -2089,15 +2164,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, ioctl.crc = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); - map->raddr = (uintptr_t)routargs.vaddrout; + *raddr = (uintptr_t)routargs.vaddrout; if (err) goto bail; if (flags == ADSP_MMAP_HEAP_ADDR) { struct scm_desc desc = {0}; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.arginfo = SCM_ARGS(3); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc); @@ -2107,7 +2182,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, int destVM[1] = {me->channel[fl->cid].rhvmid}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -2116,8 +2191,8 @@ bail: return err; } -static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, + size_t size, uint32_t flags) { int err = 0; struct fastrpc_apps *me = &gfa; @@ -2125,7 +2200,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - if (map->flags == ADSP_MMAP_HEAP_ADDR) { + if (flags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_ioctl_invoke_crc ioctl; struct scm_desc desc = {0}; remote_arg_t ra[1]; @@ -2151,14 +2226,14 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, if (err) goto bail; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.args[3] = routargs.skey; desc.arginfo = SCM_ARGS(4); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc); - } else if (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -2168,8 +2243,8 @@ bail: return err; } -static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, + uint64_t phys, size_t size, uint32_t flags) { struct fastrpc_ioctl_invoke_crc ioctl; remote_arg_t ra[1]; @@ -2181,8 +2256,8 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, } inargs; inargs.pid = fl->tgid; - inargs.size = map->size; - inargs.vaddrout = map->raddr; + inargs.size = size; + inargs.vaddrout = raddr; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); @@ -2199,9 +2274,9 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; - if (map->flags == ADSP_MMAP_HEAP_ADDR || - map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map)); + if (flags == ADSP_MMAP_HEAP_ADDR || + flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, phys, size, flags)); if (err) goto bail; } @@ -2228,7 +2303,8 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) spin_unlock(&me->hlock); if (match) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match)); + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match->phys, + match->size, match->flags)); if (err) goto bail; if (me->channel[0].ramdumpenabled) { @@ -2292,14 +2368,40 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, { int err = 0; struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL, *free = NULL; + struct hlist_node *n; mutex_lock(&fl->map_mutex); + + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(rbuf, n, &fl->remote_bufs, hn_rem) { + if (rbuf->raddr && (rbuf->flags == ADSP_MMAP_ADD_PAGES)) { + if ((rbuf->raddr == ud->vaddrout) && + (rbuf->size == ud->size)) { + free = rbuf; + break; + } + } + } + spin_unlock(&fl->hlock); + + if (free) { + VERIFY(err, !fastrpc_munmap_on_dsp(fl, free->raddr, + free->phys, free->size, free->flags)); + if (err) + goto bail; + fastrpc_buf_free(rbuf, 0); + mutex_unlock(&fl->map_mutex); + return err; + } + mutex_lock(&fl->fl_map_mutex); VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); mutex_unlock(&fl->fl_map_mutex); if (err) goto bail; - VERIFY(err, !fastrpc_munmap_on_dsp(fl, map)); + VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr, + map->phys, map->size, map->flags)); if (err) goto bail; mutex_lock(&fl->fl_map_mutex); @@ -2345,26 +2447,62 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl, { struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL; + unsigned long dma_attr = 0; + uintptr_t raddr = 0; int err = 0; mutex_lock(&fl->map_mutex); - mutex_lock(&fl->fl_map_mutex); - if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin, - ud->size, ud->flags, 1, &map)) { + if (ud->flags == ADSP_MMAP_ADD_PAGES) { + if (ud->vaddrin) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: adding user allocated pages is not supported\n", + current->comm, __func__); + goto bail; + } + dma_attr = DMA_ATTR_EXEC_MAPPING | + DMA_ATTR_NO_KERNEL_MAPPING | + DMA_ATTR_FORCE_NON_COHERENT; + err = fastrpc_buf_alloc(fl, ud->size, dma_attr, ud->flags, + 1, &rbuf); + if (err) + goto bail; + err = fastrpc_mmap_on_dsp(fl, ud->flags, 0, + rbuf->phys, rbuf->size, &raddr); + if (err) + goto bail; + rbuf->raddr = raddr; + } else { + + uintptr_t va_to_dsp; + + mutex_lock(&fl->fl_map_mutex); + if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin, + ud->size, ud->flags, 1, &map)) { + mutex_unlock(&fl->fl_map_mutex); + mutex_unlock(&fl->map_mutex); + return 0; + } + + VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, + (uintptr_t)ud->vaddrin, ud->size, + ud->flags, &map)); mutex_unlock(&fl->fl_map_mutex); - mutex_unlock(&fl->map_mutex); - return 0; + if (err) + goto bail; + + if (ud->flags == ADSP_MMAP_HEAP_ADDR || + ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + va_to_dsp = 0; + else + va_to_dsp = (uintptr_t)map->va; + VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, va_to_dsp, + map->phys, map->size, &raddr)); + if (err) + goto bail; + map->raddr = raddr; } - VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, - (uintptr_t)ud->vaddrin, ud->size, - ud->flags, &map)); - mutex_unlock(&fl->fl_map_mutex); - if (err) - goto bail; - VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, map)); - if (err) - goto bail; - ud->vaddrout = map->raddr; + ud->vaddrout = raddr; bail: if (err && map) { mutex_lock(&fl->fl_map_mutex); @@ -2541,8 +2679,10 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_lock(&fl->hlock); fl->file_close = 1; spin_unlock(&fl->hlock); + if (!IS_ERR_OR_NULL(fl->init_mem)) + fastrpc_buf_free(fl->init_mem, 0); fastrpc_context_list_dtor(fl); - fastrpc_buf_list_free(fl); + fastrpc_cached_buf_list_free(fl); mutex_lock(&fl->fl_map_mutex); do { lmap = NULL; @@ -2561,6 +2701,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) fastrpc_session_free(&fl->apps->channel[cid], fl->sctx); if (fl->secsctx) fastrpc_session_free(&fl->apps->channel[cid], fl->secsctx); + fastrpc_remote_buf_list_free(fl); bail: mutex_destroy(&fl->fl_map_mutex); mutex_destroy(&fl->map_mutex); @@ -2759,14 +2900,18 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%s %d\n\n", "DEV_MINOR:", fl->dev_minor); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %d\n\n", + "KERNEL MEMORY ALLOCATION:", 1); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s\n", - "LIST OF BUFS:"); + "LIST OF CACHED BUFS:"); spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %pK %s %llx\n", "buf:", - buf, "buf->virt:", buf->virt, - "buf->phys:", buf->phys); + "%s %pK %s %pK %s %llx %s %lx\n", + "buf:", buf, "buf->virt:", buf->virt, + "buf->phys:", buf->phys, + "buf->dma_attr:", buf->dma_attr); } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n%s\n", @@ -2906,7 +3051,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); - INIT_HLIST_HEAD(&fl->bufs); + INIT_HLIST_HEAD(&fl->cached_bufs); + INIT_HLIST_HEAD(&fl->remote_bufs); INIT_HLIST_NODE(&fl->hn); fl->sessionid = 0; fl->tgid = current->tgid; @@ -2914,6 +3060,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) fl->mode = FASTRPC_MODE_SERIAL; fl->cid = -1; fl->dev_minor = dev_minor; + fl->init_mem = NULL; if (debugfs_file != NULL) fl->debugfs_file = debugfs_file; @@ -3001,6 +3148,9 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, } else pm_qos_update_request(&fl->pm_qos_req, latency); break; + case FASTRPC_CONTROL_KALLOC: + cp->kalloc.kalloc_support = 1; + break; default: err = -ENOTTY; break; @@ -3163,6 +3313,11 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp))); if (err) goto bail; + if (p.cp.req == FASTRPC_CONTROL_KALLOC) { + K_COPY_TO_USER(err, 0, param, &p.cp, sizeof(p.cp)); + if (err) + goto bail; + } break; case FASTRPC_IOCTL_GETINFO: K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index 804cedade655..ea7967c55aa1 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -126,16 +126,22 @@ struct compat_fastrpc_ioctl_perf { /* kernel performance data */ compat_uptr_t keys; }; -#define FASTRPC_CONTROL_LATENCY (1) +#define FASTRPC_CONTROL_LATENCY (1) struct compat_fastrpc_ctrl_latency { compat_uint_t enable; /* latency control enable */ compat_uint_t level; /* level of control */ }; +#define FASTRPC_CONTROL_KALLOC (3) +struct compat_fastrpc_ctrl_kalloc { + compat_uint_t kalloc_support; /* Remote memory allocation from kernel */ +}; + struct compat_fastrpc_ioctl_control { compat_uint_t req; union { struct compat_fastrpc_ctrl_latency lp; + struct compat_fastrpc_ctrl_kalloc kalloc; }; }; @@ -528,6 +534,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, { struct compat_fastrpc_ioctl_control __user *ctrl32; struct fastrpc_ioctl_control __user *ctrl; + compat_uptr_t p; ctrl32 = compat_ptr(arg); VERIFY(err, NULL != (ctrl = compat_alloc_user_space( @@ -540,6 +547,15 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, return err; err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL, (unsigned long)ctrl); + if (err) + return err; + err = get_user(p, &ctrl32->req); + if (err) + return err; + if (p == FASTRPC_CONTROL_KALLOC) { + err = get_user(p, &ctrl->kalloc.kalloc_support); + err |= put_user(p, &ctrl32->kalloc.kalloc_support); + } return err; } case COMPAT_FASTRPC_IOCTL_GETPERF: diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index e3c5ee0d87e9..c7f67fe695e1 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -220,7 +220,7 @@ struct fastrpc_ioctl_mmap { }; struct fastrpc_ioctl_mmap_64 { - int fd; /* ion fd */ + int fd; /* ion fd */ uint32_t flags; /* flags for dsp to map with */ uint64_t vaddrin; /* optional virtual address */ size_t size; /* size */ @@ -240,16 +240,22 @@ struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t keys; }; -#define FASTRPC_CONTROL_LATENCY (1) +#define FASTRPC_CONTROL_LATENCY (1) struct fastrpc_ctrl_latency { - uint32_t enable; //!latency control enable - uint32_t level; //!level of control + uint32_t enable; /* latency control enable */ + uint32_t level; /* level of control */ +}; + +#define FASTRPC_CONTROL_KALLOC (3) +struct fastrpc_ctrl_kalloc { + uint32_t kalloc_support; /* Remote memory allocation from kernel */ }; struct fastrpc_ioctl_control { uint32_t req; union { struct fastrpc_ctrl_latency lp; + struct fastrpc_ctrl_kalloc kalloc; }; }; diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c index ce0c7bb2fbef..46de6a67a0a4 100644 --- a/drivers/char/diag/diag_memorydevice.c +++ b/drivers/char/diag/diag_memorydevice.c @@ -194,6 +194,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) } found = 0; + mutex_lock(&driver->diagchar_mutex); for (i = 0; i < driver->num_clients && !found; i++) { if ((driver->client_map[i].pid != pid) || (driver->client_map[i].pid == 0)) @@ -207,6 +208,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) pr_debug("diag: wake up logging process\n"); wake_up_interruptible(&driver->wait_q); } + mutex_unlock(&driver->diagchar_mutex); if (!found) return -EINVAL; diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index cd65e0f52591..52b18d8cbf7a 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -389,6 +389,8 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, goto end; } } + mutex_unlock(&fwd_info->data_mutex); + mutex_unlock(&driver->hdlc_disable_mutex); if (write_len > 0) { err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len, @@ -396,18 +398,18 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, if (err) { pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n", __func__, err); - goto end; + goto end_write; } } - mutex_unlock(&fwd_info->data_mutex); - mutex_unlock(&driver->hdlc_disable_mutex); + diagfwd_queue_read(fwd_info); return; end: - diag_ws_release(); mutex_unlock(&fwd_info->data_mutex); mutex_unlock(&driver->hdlc_disable_mutex); +end_write: + diag_ws_release(); if (buf) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "Marking buffer as free p: %d, t: %d, buf_num: %d\n", @@ -699,24 +701,26 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info, } } + mutex_unlock(&fwd_info->data_mutex); + mutex_unlock(&driver->hdlc_disable_mutex); + if (write_len > 0) { err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len, temp_buf->ctxt); if (err) { pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n", __func__, err); - goto end; + goto end_write; } } - mutex_unlock(&fwd_info->data_mutex); - mutex_unlock(&driver->hdlc_disable_mutex); diagfwd_queue_read(fwd_info); return; end: - diag_ws_release(); mutex_unlock(&fwd_info->data_mutex); mutex_unlock(&driver->hdlc_disable_mutex); +end_write: + diag_ws_release(); if (temp_buf) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "Marking buffer as free p: %d, t: %d, buf_num: %d\n", diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 958fb9160c2d..6974e1038bc6 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1,7 +1,7 @@ /* * QTI CE device driver. * - * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1227,8 +1227,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, goto exit; } - k_align_dst += creq->vbuf.dst[dst_i].len + - byteoffset; + k_align_dst += creq->vbuf.dst[dst_i].len; creq->data_len -= creq->vbuf.dst[dst_i].len; dst_i++; } else { diff --git a/drivers/devfreq/governor_gpubw_mon.c b/drivers/devfreq/governor_gpubw_mon.c index 9c24eef6a497..f7bb7ebf41ea 100644 --- a/drivers/devfreq/governor_gpubw_mon.c +++ b/drivers/devfreq/governor_gpubw_mon.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -224,10 +224,11 @@ static int devfreq_gpubw_event_handler(struct devfreq *devfreq, case DEVFREQ_GOV_SUSPEND: { struct devfreq_msm_adreno_tz_data *priv = devfreq->data; - - priv->bus.total_time = 0; - priv->bus.gpu_time = 0; - priv->bus.ram_time = 0; + if (priv) { + priv->bus.total_time = 0; + priv->bus.gpu_time = 0; + priv->bus.ram_time = 0; + } } break; default: diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 68418a6536b0..beba6635cd2c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -143,4 +143,3 @@ obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_MSM_SMP2P) += gpio-msm-smp2p.o -obj-$(CONFIG_MSM_SMP2P_TEST) += gpio-msm-smp2p-test.o diff --git a/drivers/gpio/gpio-msm-smp2p-test.c b/drivers/gpio/gpio-msm-smp2p-test.c deleted file mode 100644 index 1067c4aade39..000000000000 --- a/drivers/gpio/gpio-msm-smp2p-test.c +++ /dev/null @@ -1,763 +0,0 @@ -/* drivers/gpio/gpio-msm-smp2p-test.c - * - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program 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. - */ -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/of_gpio.h> -#include <linux/of_irq.h> -#include <linux/gpio.h> -#include <linux/debugfs.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/bitmap.h> -#include "../soc/qcom/smp2p_private.h" -#include "../soc/qcom/smp2p_test_common.h" - -/* Interrupt callback data */ -struct gpio_info { - int gpio_base_id; - int irq_base_id; - - bool initialized; - struct completion cb_completion; - int cb_count; - DECLARE_BITMAP(triggered_irqs, SMP2P_BITS_PER_ENTRY); -}; - -/* GPIO Inbound/Outbound callback info */ -struct gpio_inout { - struct gpio_info in; - struct gpio_info out; -}; - -static struct gpio_inout gpio_info[SMP2P_NUM_PROCS]; - -/** - * Init/reset the callback data. - * - * @info: Pointer to callback data - */ -static void cb_data_reset(struct gpio_info *info) -{ - int n; - - if (!info) - return; - - if (!info->initialized) { - init_completion(&info->cb_completion); - info->initialized = true; - } - info->cb_count = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) - clear_bit(n, info->triggered_irqs); - - reinit_completion(&info->cb_completion); -} - -static int smp2p_gpio_test_probe(struct platform_device *pdev) -{ - int id; - int cnt; - struct device_node *node = pdev->dev.of_node; - struct gpio_info *gpio_info_ptr = NULL; - - /* - * NOTE: This does a string-lookup of the GPIO pin name and doesn't - * actually directly link to the SMP2P GPIO driver since all - * GPIO/Interrupt access must be through standard - * Linux GPIO / Interrupt APIs. - */ - if (strcmp("qcom,smp2pgpio_test_smp2p_1_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_1_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_15_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - } else if ( - strcmp("qcom,smp2pgpio_test_smp2p_15_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - } else { - pr_err("%s: unable to match device type '%s'\n", - __func__, node->name); - return -ENODEV; - } - - /* retrieve the GPIO and interrupt ID's */ - cnt = of_gpio_count(node); - if (cnt && gpio_info_ptr) { - /* - * Instead of looping through all 32-bits, we can just get the - * first pin to get the base IDs. This saves on the verbosity - * of the device tree nodes as well. - */ - id = of_get_gpio(node, 0); - if (id == -EPROBE_DEFER) - return id; - gpio_info_ptr->gpio_base_id = id; - gpio_info_ptr->irq_base_id = gpio_to_irq(id); - } - return 0; -} - -/* - * NOTE: Instead of match table and device driver, you may be able to just - * call of_find_compatible_node() in your init function. - */ -static const struct of_device_id msm_smp2p_match_table[] = { - /* modem */ - {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", }, - - /* audio (adsp) */ - {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", }, - - /* sensor */ - {.compatible = "qcom,smp2pgpio_test_smp2p_3_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_3_in", }, - - /* wcnss */ - {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", }, - - /* CDSP */ - {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", }, - - /* TZ */ - {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", }, - - /* mock loopback */ - {.compatible = "qcom,smp2pgpio_test_smp2p_15_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_15_in", }, - {}, -}; - -static struct platform_driver smp2p_gpio_driver = { - .probe = smp2p_gpio_test_probe, - .driver = { - .name = "smp2pgpio_test", - .owner = THIS_MODULE, - .of_match_table = msm_smp2p_match_table, - }, -}; - -/** - * smp2p_ut_local_gpio_out - Verify outbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_out(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - int ret; - int id; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* open GPIO entry */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin = cb_info->gpio_base_id + id; - - mock->rx_interrupt_count = 0; - gpio_set_value(pin, 1); - UT_ASSERT_INT(1, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(1, ==, gpio_get_value(pin)); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(2, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(0, ==, gpio_get_value(pin)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_irq - Interrupt handler for inbound entries. - * - * @irq: Virtual IRQ being triggered - * @data: Cookie data (struct gpio_info * in this case) - * @returns: Number of bytes written - */ -static irqreturn_t smp2p_gpio_irq(int irq, void *data) -{ - struct gpio_info *gpio_ptr = (struct gpio_info *)data; - int offset; - - if (!gpio_ptr) { - pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq); - return IRQ_HANDLED; - } - - offset = irq - gpio_ptr->irq_base_id; - if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY) - set_bit(offset, gpio_ptr->triggered_irqs); - else - pr_err("%s: invalid irq offset base %d; irq %d\n", - __func__, gpio_ptr->irq_base_id, irq); - - ++gpio_ptr->cb_count; - complete(&gpio_ptr->cb_completion); - return IRQ_HANDLED; -} - -/** - * smp2p_ut_local_gpio_in - Verify inbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_in(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions locally */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin; - int current_value; - - /* verify pin value cannot be set */ - pin = cb_info->gpio_base_id + id; - current_value = gpio_get_value(pin); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - gpio_set_value(pin, 1); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - - /* verify no interrupts */ - UT_ASSERT_INT(0, ==, cb_info->cb_count); - } - if (failed) - break; - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQF_TRIGGER_RISING, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* verify both rising and falling edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH); - cb_data_reset(cb_info); - - /* verify rising-edge interrupt */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - /* verify falling-edge interrupt */ - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 2); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify rising-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify falling-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 0); - UT_ASSERT_INT(0, ==, - test_bit(id, cb_info->triggered_irqs)); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_ut_local_gpio_in_update_open - Verify combined open/update. - * - * @s: pointer to output file - * - * If the remote side updates the SMP2P bits and sends before negotiation is - * complete, then the UPDATE event will have to be delayed until negotiation is - * complete. This should result in both the OPEN and UPDATE events coming in - * right after each other and the behavior should be transparent to the clients - * of SMP2P GPIO. - */ -static void smp2p_ut_local_gpio_in_update_open(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - - /* register for interrupts */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQ_TYPE_EDGE_BOTH, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* update the state value and complete negotiation */ - mock->remote_item.entries[0].entry = 0xDEADDEAD; - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* verify delayed state updates were processed */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - - UT_ASSERT_INT(cb_info->cb_count, >, 0); - if (0x1 & (0xDEADDEAD >> id)) { - /* rising edge should have been triggered */ - if (!test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d clear, ", - __func__, __LINE__, id); - seq_puts(s, "expected set\n"); - failed = 1; - break; - } - } else { - /* edge should not have been triggered */ - if (test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d set, ", - __func__, __LINE__, id); - seq_puts(s, "expected clear\n"); - failed = 1; - break; - } - } - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask. - * - * @gpio: gpio test structure - * @mask: 1 = write gpio_value to this GPIO pin - * @gpio_value: value to write to GPIO pin - */ -static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask, - int gpio_value) -{ - int n; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (mask & 0x1) - gpio_set_value(gpio->gpio_base_id + n, gpio_value); - mask >>= 1; - } -} - -static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 1); -} - -static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 0); -} - -/** - * smp2p_gpio_get_value - reads entire 32-bits of GPIO - * - * @gpio: gpio structure - * @returns: 32 bit value of GPIO pins - */ -static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio) -{ - int n; - uint32_t value = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (gpio_get_value(gpio->gpio_base_id + n)) - value |= 1 << n; - } - return value; -} - -/** - * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - * @name: Name of the test for reporting - * - * This test verifies inbound/outbound functionality for the remote processor. - */ -static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid, - const char *name) -{ - int failed = 0; - uint32_t request; - uint32_t response; - struct gpio_info *cb_in; - struct gpio_info *cb_out; - int id; - int ret; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_in = &gpio_info[remote_pid].in; - cb_out = &gpio_info[remote_pid].out; - cb_data_reset(cb_in); - cb_data_reset(cb_out); - do { - /* open test entries */ - msm_smp2p_deinit_rmt_lpb_proc(remote_pid); - smp2p_gpio_open_test_entry("smp2p", remote_pid, true); - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_in->gpio_base_id); - UT_ASSERT_INT(0, <, cb_in->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int virq = cb_in->irq_base_id + id; - - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "smp2p_test", cb_in); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* write echo of data value 0 */ - UT_ASSERT_INT(0, <, cb_out->gpio_base_id); - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, 0x0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response */ - do { - /* wait for up to 32 changes */ - if (wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2) == 0) - break; - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 32); - UT_ASSERT_INT(cb_in->cb_count, >, 0); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - - /* write echo of data value of all 1's */ - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, ~0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - cb_data_reset(cb_in); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response including 24 interrupts */ - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2), - >, 0); - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 24); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - UT_ASSERT_INT(24, ==, cb_in->cb_count); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", name); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_in->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_in->irq_base_id + id, cb_in); - } - - smp2p_gpio_open_test_entry("smp2p", remote_pid, false); - msm_smp2p_init_rmt_lpb_proc(remote_pid); -} - -/** - * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_inout(struct seq_file *s) -{ - struct smp2p_interrupt_config *int_cfg; - int pid; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { - if (!int_cfg[pid].is_configured) - continue; - - smp2p_ut_remote_inout_core(s, pid, __func__); - } -} - -static int __init smp2p_debugfs_init(void) -{ - /* register GPIO pins */ - (void)platform_driver_register(&smp2p_gpio_driver); - - /* - * Add Unit Test entries. - * - * The idea with unit tests is that you can run all of them - * from ADB shell by doing: - * adb shell - * cat ut* - * - * And if particular tests fail, you can then repeatedly run the - * failing tests as you debug and resolve the failing test. - */ - smp2p_debug_create("ut_local_gpio_out", smp2p_ut_local_gpio_out); - smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in); - smp2p_debug_create("ut_local_gpio_in_update_open", - smp2p_ut_local_gpio_in_update_open); - smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout); - return 0; -} -late_initcall(smp2p_debugfs_init); diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 78bea02955fb..0589bda19884 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -104,7 +104,7 @@ static ssize_t dp_debug_write_edid(struct file *file, size = min_t(size_t, count, SZ_1K); buf = kzalloc(size, GFP_KERNEL); - if (!buf) { + if (ZERO_OR_NULL_PTR(buf)) { rc = -ENOMEM; goto bail; } @@ -172,7 +172,7 @@ static ssize_t dp_debug_write_dpcd(struct file *file, size = min_t(size_t, count, SZ_2K); buf = kzalloc(size, GFP_KERNEL); - if (!buf) { + if (ZERO_OR_NULL_PTR(buf)) { rc = -ENOMEM; goto bail; } @@ -493,7 +493,7 @@ static ssize_t dp_debug_read_edid_modes(struct file *file, goto error; buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) { + if (ZERO_OR_NULL_PTR(buf)) { rc = -ENOMEM; goto error; } @@ -538,7 +538,7 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, return 0; buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) + if (ZERO_OR_NULL_PTR(buf)) return -ENOMEM; rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state); @@ -624,7 +624,7 @@ static ssize_t dp_debug_bw_code_read(struct file *file, return 0; buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) + if (ZERO_OR_NULL_PTR(buf)) return -ENOMEM; len += snprintf(buf + len, (SZ_4K - len), @@ -745,7 +745,7 @@ static ssize_t dp_debug_read_hdr(struct file *file, goto error; buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) { + if (ZERO_OR_NULL_PTR(buf)) { rc = -ENOMEM; goto error; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index ca9935c9741f..c429975dbc20 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -1099,7 +1099,7 @@ static ssize_t debugfs_misr_read(struct file *file, return 0; buf = kzalloc(max_len, GFP_KERNEL); - if (!buf) + if (ZERO_OR_NULL_PTR(buf)) return -ENOMEM; mutex_lock(&display->display_lock); @@ -1130,7 +1130,7 @@ static ssize_t debugfs_misr_read(struct file *file, goto error; } - if (copy_to_user(user_buf, buf, len)) { + if (copy_to_user(user_buf, buf, max_len)) { rc = -EFAULT; goto error; } @@ -1162,6 +1162,9 @@ static ssize_t debugfs_esd_trigger_check(struct file *file, if (user_len > sizeof(u32)) return -EINVAL; + if (!user_len || !user_buf) + return -EINVAL; + buf = kzalloc(user_len, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -1217,7 +1220,7 @@ static ssize_t debugfs_alter_esd_check_mode(struct file *file, return 0; buf = kzalloc(len, GFP_KERNEL); - if (!buf) + if (ZERO_OR_NULL_PTR(buf)) return -ENOMEM; if (copy_from_user(buf, user_buf, user_len)) { @@ -1289,7 +1292,7 @@ static ssize_t debugfs_read_esd_check_mode(struct file *file, } buf = kzalloc(len, GFP_KERNEL); - if (!buf) + if (ZERO_OR_NULL_PTR(buf)) return -ENOMEM; esd_config = &display->panel->esd_config; @@ -3067,9 +3070,6 @@ int dsi_post_clkon_cb(void *priv, __func__, rc); goto error; } - - /* enable dsi to serve irqs */ - dsi_display_ctrl_irq_update(display, true); } if ((clk & DSI_LINK_CLK) && (l_type & DSI_LINK_HS_CLK)) { @@ -3091,6 +3091,11 @@ int dsi_post_clkon_cb(void *priv, } } } + + /* enable dsi to serve irqs */ + if (clk & DSI_CORE_CLK) + dsi_display_ctrl_irq_update(display, true); + error: return rc; } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 05ac8930ce2d..01d2f527d041 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -24,8 +24,7 @@ #define GAMUT_LUT_MEM_SIZE ((sizeof(struct drm_msm_3d_gamut)) + \ REG_DMA_HEADERS_BUFFER_SZ) -#define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * \ - GAMUT_3D_SCALE_OFF_TBL_NUM * sizeof(u32)) +#define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * sizeof(u32)) #define GAMUT_SCALE_OFF_LEN_12 (GAMUT_3D_SCALEB_OFF_SZ * sizeof(u32)) #define GC_LUT_MEM_SIZE ((sizeof(struct drm_msm_pgc_lut)) + \ diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c index 582909580be9..d8f75c05f739 100644 --- a/drivers/gpu/drm/msm/sde_dbg.c +++ b/drivers/gpu/drm/msm/sde_dbg.c @@ -3002,6 +3002,37 @@ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file) return 0; } +/** + * sde_dbg_reg_base_is_valid_range - verify if requested memory range is valid + * @off: address offset in bytes + * @cnt: memory size in bytes + * Return: true if valid; false otherwise + */ +static bool sde_dbg_reg_base_is_valid_range(u32 off, u32 cnt) +{ + static struct sde_dbg_base *dbg_base = &sde_dbg_base; + struct sde_dbg_reg_range *node; + struct sde_dbg_reg_base *base; + + pr_debug("check offset=0x%x cnt=0x%x\n", off, cnt); + + list_for_each_entry(base, &dbg_base->reg_base_list, reg_base_head) { + list_for_each_entry(node, &base->sub_range_list, head) { + pr_debug("%s: start=0x%x end=0x%x\n", node->range_name, + node->offset.start, node->offset.end); + + if (node->offset.start <= off + && off <= node->offset.end + && off + cnt <= node->offset.end) { + pr_debug("valid range requested\n"); + return true; + } + } + } + + pr_err("invalid range requested\n"); + return false; +} /** * sde_dbg_reg_base_offset_write - set new offset and len to debugfs reg base @@ -3048,6 +3079,9 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file, if (cnt == 0) return -EINVAL; + if (!sde_dbg_reg_base_is_valid_range(off, cnt)) + return -EINVAL; + mutex_lock(&sde_dbg_base.mutex); dbg->off = off; dbg->cnt = cnt; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index f0e2757cb909..216f0338a1f7 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -192,6 +192,11 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t int ret = 0, len; unsigned char report_number; + if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + ret = -ENODEV; + goto out; + } + dev = hidraw_table[minor]->hid; if (!dev->ll_driver->raw_request) { diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index 4daed7f4875f..fa55b6e8d163 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2321,6 +2321,12 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) struct i2c_msm_ctrl *ctrl = i2c_get_adapdata(adap); struct i2c_msm_xfer *xfer = &ctrl->xfer; + if (num < 1) { + dev_err(ctrl->dev, + "error on number of msgs(%d) received\n", num); + return -EINVAL; + } + if (IS_ERR_OR_NULL(msgs)) { dev_err(ctrl->dev, " error on msgs Accessing invalid pointer location\n"); return PTR_ERR(msgs); diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h index 03f6e0c4d5c8..ff8be3570bc5 100644 --- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h +++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -195,11 +195,11 @@ struct cam_cdm_hw_intf_cmd_submit_bl { struct cam_cdm_bl_request *data; }; -/* struct cam_cdm_hw_mem - CDM hw memory.struct */ +/* struct cam_cdm_hw_mem - CDM hw memory struct */ struct cam_cdm_hw_mem { int32_t handle; uint32_t vaddr; - uint64_t kmdvaddr; + uintptr_t kmdvaddr; size_t size; }; diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c index f2796be6d682..4ae2f0a3bee2 100644 --- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c @@ -624,7 +624,8 @@ static void cam_hw_cdm_work(struct work_struct *work) } static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, - struct device *dev, unsigned long iova, int flags, void *token) + struct device *dev, unsigned long iova, int flags, void *token, + uint32_t buf_info) { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; @@ -910,7 +911,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) CAM_ERR(CAM_CDM, "cpas-cdm get iommu handle failed"); goto unlock_release_mem; } - cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, + cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_hw_cdm_iommu_fault_handler, cdm_hw); rc = cam_smmu_ops(cdm_core->iommu_hdl.non_secure, CAM_SMMU_ATTACH); @@ -1034,7 +1035,7 @@ release_platform_resource: flush_workqueue(cdm_core->work_queue); destroy_workqueue(cdm_core->work_queue); destroy_non_secure_hdl: - cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, + cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, NULL, cdm_hw); if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); @@ -1106,8 +1107,8 @@ int cam_hw_cdm_remove(struct platform_device *pdev) if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); - cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, - NULL, cdm_hw); + cam_smmu_unset_client_page_fault_handler( + cdm_core->iommu_hdl.non_secure, cdm_hw); mutex_destroy(&cdm_hw->hw_mutex); kfree(cdm_hw->soc_info.soc_private); diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h index 2b00a87544fa..6aa6e6d2bc4c 100644 --- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h +++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h @@ -105,10 +105,10 @@ struct cam_cdm_bl_cmd { union { int32_t mem_handle; uint32_t *hw_iova; - void *kernel_iova; + uintptr_t kernel_iova; } bl_addr; - uint32_t offset; - uint32_t len; + uint32_t offset; + uint32_t len; }; /** diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c index d76f344c1efa..9021ecabb27c 100644 --- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c +++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -87,7 +87,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw, mutex_lock(&client->lock); for (i = 0; i < req->data->cmd_arrary_count ; i++) { - uint64_t vaddr_ptr = 0; + uintptr_t vaddr_ptr = 0; size_t len = 0; if ((!cdm_cmd->cmd[i].len) && @@ -106,8 +106,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw, } else if (req->data->type == CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA) { rc = 0; - vaddr_ptr = - (uint64_t)cdm_cmd->cmd[i].bl_addr.kernel_iova; + vaddr_ptr = cdm_cmd->cmd[i].bl_addr.kernel_iova; len = cdm_cmd->cmd[i].offset + cdm_cmd->cmd[i].len; } else { CAM_ERR(CAM_CDM, diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c index da785271053f..4ed53f9b576c 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c @@ -42,6 +42,7 @@ int cam_context_shutdown(struct cam_context *ctx) int rc = 0; int32_t ctx_hdl = ctx->dev_hdl; + mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) { rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev( ctx, NULL); @@ -54,6 +55,7 @@ int cam_context_shutdown(struct cam_context *ctx) if (rc < 0) CAM_ERR(CAM_CORE, "Error while dev release %d", rc); } + mutex_unlock(&ctx->ctx_mutex); if (!rc) rc = cam_destroy_device_hdl(ctx_hdl); @@ -221,6 +223,27 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, return rc; } +int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, + uint32_t buf_info) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].pagefault_ops) { + rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova, + buf_info); + } else { + CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", + ctx->dev_hdl, ctx->state); + } + + return rc; +} + int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h index ffceea22ae0f..420f9f65987c 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context.h +++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h @@ -57,23 +57,25 @@ enum cam_context_state { * @num_out_acked: Number of out fence acked * @flushed: Request is flushed * @ctx: The context to which this request belongs + * @pf_data page fault debug data * */ struct cam_ctx_request { - struct list_head list; - uint32_t status; - uint64_t request_id; + struct list_head list; + uint32_t status; + uint64_t request_id; void *req_priv; - struct cam_hw_update_entry hw_update_entries[CAM_CTX_CFG_MAX]; - uint32_t num_hw_update_entries; - struct cam_hw_fence_map_entry in_map_entries[CAM_CTX_CFG_MAX]; - uint32_t num_in_map_entries; - struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX]; - uint32_t num_out_map_entries; - atomic_t num_in_acked; - uint32_t num_out_acked; - int flushed; - struct cam_context *ctx; + struct cam_hw_update_entry hw_update_entries[CAM_CTX_CFG_MAX]; + uint32_t num_hw_update_entries; + struct cam_hw_fence_map_entry in_map_entries[CAM_CTX_CFG_MAX]; + uint32_t num_in_map_entries; + struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX]; + uint32_t num_out_map_entries; + atomic_t num_in_acked; + uint32_t num_out_acked; + int flushed; + struct cam_context *ctx; + struct cam_hw_mgr_dump_pf_data pf_data; }; /** @@ -135,12 +137,14 @@ struct cam_ctx_crm_ops { * @ioctl_ops: Ioctl funciton table * @crm_ops: CRM to context interface function table * @irq_ops: Hardware event handle function + * @pagefault_ops: Function to be called on page fault * */ struct cam_ctx_ops { struct cam_ctx_ioctl_ops ioctl_ops; struct cam_ctx_crm_ops crm_ops; cam_hw_event_cb_func irq_ops; + cam_hw_pagefault_cb_func pagefault_ops; }; /** @@ -292,6 +296,19 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *process_evt); /** + * cam_context_dump_pf_info() + * + * @brief: Handle dump active request request command + * + * @ctx: Object pointer for cam_context + * @iova: Page fault address + * @buf_info: Information about closest memory handle + * + */ +int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, + uint32_t buf_info); + +/** * cam_context_handle_acquire_dev() * * @brief: Handle acquire device command diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c index 6c2383ed8110..8021f12934a9 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c @@ -272,7 +272,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, int rc = 0; struct cam_ctx_request *req = NULL; struct cam_hw_prepare_update_args cfg; - uint64_t packet_addr; + uintptr_t packet_addr; struct cam_packet *packet; size_t len = 0; int32_t i = 0, j = 0; @@ -315,8 +315,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, /* for config dev, only memory handle is supported */ /* map packet from the memhandle */ rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, - (uint64_t *) &packet_addr, - &len); + &packet_addr, &len); if (rc != 0) { CAM_ERR(CAM_CTXT, "[%s][%d] Can not get packet address", ctx->dev_name, ctx->ctx_id); @@ -324,7 +323,8 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, goto free_req; } - packet = (struct cam_packet *) (packet_addr + cmd->offset); + packet = (struct cam_packet *) ((uint8_t *)packet_addr + + (uint32_t)cmd->offset); /* preprocess the configuration */ memset(&cfg, 0, sizeof(cfg)); @@ -337,6 +337,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, cfg.out_map_entries = req->out_map_entries; cfg.max_in_map_entries = CAM_CTX_CFG_MAX; cfg.in_map_entries = req->in_map_entries; + cfg.pf_data = &(req->pf_data); rc = ctx->hw_mgr_intf->hw_prepare_update( ctx->hw_mgr_intf->hw_mgr_priv, &cfg); @@ -905,3 +906,38 @@ int32_t cam_context_stop_dev_to_hw(struct cam_context *ctx) end: return rc; } + +int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, + struct cam_packet *packet, unsigned long iova, uint32_t buf_info, + bool *mem_found) +{ + int rc = 0; + struct cam_hw_cmd_args cmd_args; + + if (!ctx) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK ", ctx); + rc = -EINVAL; + goto end; + } + + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + rc = -EFAULT; + goto end; + } + + if (ctx->hw_mgr_intf->hw_cmd) { + cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO; + cmd_args.u.pf_args.pf_data.packet = packet; + cmd_args.u.pf_args.iova = iova; + cmd_args.u.pf_args.buf_info = buf_info; + cmd_args.u.pf_args.mem_found = mem_found; + ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &cmd_args); + } + +end: + return rc; +} diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h index 9b95eaddb3c7..43e69405ee3b 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h +++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -31,5 +31,8 @@ int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx); int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); +int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, + struct cam_packet *packet, unsigned long iova, uint32_t buf_info, + bool *mem_found); #endif /* _CAM_CONTEXT_UTILS_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h index f7990b6d5d4a..54b0f4d63bf8 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h @@ -13,6 +13,9 @@ #ifndef _CAM_HW_MGR_INTF_H_ #define _CAM_HW_MGR_INTF_H_ +#include <linux/time.h> +#include <linux/types.h> + /* * This file declares Constants, Enums, Structures and APIs to be used as * Interface between HW Manager and Context. @@ -29,6 +32,10 @@ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id, void *evt_data); +/* hardware page fault callback function type */ +typedef int (*cam_hw_pagefault_cb_func)(void *context, unsigned long iova, + uint32_t buf_info); + /** * struct cam_hw_update_entry - Entry for hardware config * @@ -44,7 +51,7 @@ struct cam_hw_update_entry { uint32_t offset; uint32_t len; uint32_t flags; - uint64_t addr; + uintptr_t addr; }; /** @@ -89,7 +96,7 @@ struct cam_hw_acquire_args { void *context_data; cam_hw_event_cb_func event_cb; uint32_t num_acq; - uint64_t acquire_info; + uintptr_t acquire_info; void *ctxt_to_hw_map; }; @@ -131,6 +138,16 @@ struct cam_hw_stop_args { void *args; }; + +/** + * struct cam_hw_mgr_dump_pf_data - page fault debug data + * + * packet: pointer to packet + */ +struct cam_hw_mgr_dump_pf_data { + void *packet; +}; + /** * struct cam_hw_prepare_update_args - Payload for prepare command * @@ -146,6 +163,7 @@ struct cam_hw_stop_args { * @in_map_entries: Actual input fence mapping list (returned) * @num_in_map_entries: Number of acutal input fence mapping (returned) * @priv: Private pointer of hw update + * @pf_data: Debug data for page fault * */ struct cam_hw_prepare_update_args { @@ -161,6 +179,7 @@ struct cam_hw_prepare_update_args { struct cam_hw_fence_map_entry *in_map_entries; uint32_t num_in_map_entries; void *priv; + struct cam_hw_mgr_dump_pf_data *pf_data; }; /** @@ -207,6 +226,48 @@ struct cam_hw_flush_args { }; /** + * struct cam_hw_dump_pf_args - Payload for dump pf info command + * + * @pf_data: Debug data for page fault + * @iova: Page fault address + * @buf_info: Info about memory buffer where page + * fault occurred + * @mem_found: If fault memory found in current + * request + * + */ +struct cam_hw_dump_pf_args { + struct cam_hw_mgr_dump_pf_data pf_data; + unsigned long iova; + uint32_t buf_info; + bool *mem_found; +}; + +/* enum cam_hw_mgr_command - Hardware manager command type */ +enum cam_hw_mgr_command { + CAM_HW_MGR_CMD_INTERNAL, + CAM_HW_MGR_CMD_DUMP_PF_INFO, +}; + +/** + * struct cam_hw_cmd_args - Payload for hw manager command + * + * @ctxt_to_hw_map: HW context from the acquire + * @cmd_type HW command type + * @internal_args Arguments for internal command + * @pf_args Arguments for Dump PF info command + * + */ +struct cam_hw_cmd_args { + void *ctxt_to_hw_map; + uint32_t cmd_type; + union { + void *internal_args; + struct cam_hw_dump_pf_args pf_args; + } u; +}; + +/** * cam_hw_mgr_intf - HW manager interface * * @hw_mgr_priv: HW manager object diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c index 18d5446d24f7..212a11bf2ee7 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_node.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c @@ -430,6 +430,9 @@ int cam_node_shutdown(struct cam_node *node) for (i = 0; i < node->ctx_size; i++) { if (node->ctx_list[i].dev_hdl > 0) { + CAM_DBG(CAM_CORE, + "Node [%s] invoking shutdown on context [%d]", + node->name, i); rc = cam_context_shutdown(&(node->ctx_list[i])); if (rc) continue; @@ -501,7 +504,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_QUERY_CAP: { struct cam_query_cap_cmd query; - if (copy_from_user(&query, (void __user *)cmd->handle, + if (copy_from_user(&query, u64_to_user_ptr(cmd->handle), sizeof(query))) { rc = -EFAULT; break; @@ -514,7 +517,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) break; } - if (copy_to_user((void __user *)cmd->handle, &query, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &query, sizeof(query))) rc = -EFAULT; @@ -523,7 +526,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_ACQUIRE_DEV: { struct cam_acquire_dev_cmd acquire; - if (copy_from_user(&acquire, (void __user *)cmd->handle, + if (copy_from_user(&acquire, u64_to_user_ptr(cmd->handle), sizeof(acquire))) { rc = -EFAULT; break; @@ -534,7 +537,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) rc); break; } - if (copy_to_user((void __user *)cmd->handle, &acquire, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &acquire, sizeof(acquire))) rc = -EFAULT; break; @@ -542,7 +545,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_START_DEV: { struct cam_start_stop_dev_cmd start; - if (copy_from_user(&start, (void __user *)cmd->handle, + if (copy_from_user(&start, u64_to_user_ptr(cmd->handle), sizeof(start))) rc = -EFAULT; else { @@ -556,7 +559,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_STOP_DEV: { struct cam_start_stop_dev_cmd stop; - if (copy_from_user(&stop, (void __user *)cmd->handle, + if (copy_from_user(&stop, u64_to_user_ptr(cmd->handle), sizeof(stop))) rc = -EFAULT; else { @@ -570,7 +573,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_CONFIG_DEV: { struct cam_config_dev_cmd config; - if (copy_from_user(&config, (void __user *)cmd->handle, + if (copy_from_user(&config, u64_to_user_ptr(cmd->handle), sizeof(config))) rc = -EFAULT; else { @@ -584,7 +587,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_RELEASE_DEV: { struct cam_release_dev_cmd release; - if (copy_from_user(&release, (void __user *)cmd->handle, + if (copy_from_user(&release, u64_to_user_ptr(cmd->handle), sizeof(release))) rc = -EFAULT; else { @@ -598,7 +601,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) case CAM_FLUSH_REQ: { struct cam_flush_dev_cmd flush; - if (copy_from_user(&flush, (void __user *)cmd->handle, + if (copy_from_user(&flush, u64_to_user_ptr(cmd->handle), sizeof(flush))) rc = -EFAULT; else { diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c index 053447e331a8..948485fa6474 100644 --- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c +++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c @@ -933,7 +933,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, } if (sizeof(struct cam_cpas_hw_cmd_start) != arg_size) { - CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d", + CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d", sizeof(struct cam_cpas_hw_cmd_start), arg_size); return -EINVAL; } @@ -1065,7 +1065,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, } if (sizeof(struct cam_cpas_hw_cmd_stop) != arg_size) { - CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d", + CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d", sizeof(struct cam_cpas_hw_cmd_stop), arg_size); return -EINVAL; } @@ -1168,7 +1168,7 @@ static int cam_cpas_hw_init(void *hw_priv, void *init_hw_args, } if (sizeof(struct cam_cpas_hw_caps) != arg_size) { - CAM_ERR(CAM_CPAS, "INIT HW size mismatch %ld %d", + CAM_ERR(CAM_CPAS, "INIT HW size mismatch %zd %d", sizeof(struct cam_cpas_hw_caps), arg_size); return -EINVAL; } @@ -1325,7 +1325,7 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, } if (sizeof(struct cam_cpas_hw_caps) != arg_size) { - CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d", + CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d", sizeof(struct cam_cpas_hw_caps), arg_size); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h index d51b15291142..eb8b156a4fc2 100644 --- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h +++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h @@ -23,7 +23,7 @@ #define CAM_CPAS_AXI_MIN_MNOC_AB_BW (2048 * 1024) #define CAM_CPAS_AXI_MIN_MNOC_IB_BW (2048 * 1024) #define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024) -#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000L) +#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000UL) #define CAM_CPAS_GET_CLIENT_IDX(handle) (handle) #define CAM_CPAS_GET_CLIENT_HANDLE(indx) (indx) diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c index cdc8a3baef28..a9f1e4f8364e 100644 --- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c +++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c @@ -367,7 +367,7 @@ int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf, case CAM_QUERY_CAP: { struct cam_cpas_query_cap query; - rc = copy_from_user(&query, (void __user *) cmd->handle, + rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle), sizeof(query)); if (rc) { CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d", @@ -381,7 +381,7 @@ int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf, if (rc) break; - rc = copy_to_user((void __user *) cmd->handle, &query, + rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query, sizeof(query)); if (rc) CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc); diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c index 09388fe40c70..7e78f458ec2b 100644 --- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c @@ -417,7 +417,7 @@ static int cam_fd_packet_generic_blob_handler(void *user_data, uint32_t *get_raw_results = (uint32_t *)blob_data; if (sizeof(uint32_t) != blob_size) { - CAM_ERR(CAM_FD, "Invalid blob size %lu %u", + CAM_ERR(CAM_FD, "Invalid blob size %zu %u", sizeof(uint32_t), blob_size); return -EINVAL; } @@ -430,7 +430,7 @@ static int cam_fd_packet_generic_blob_handler(void *user_data, (struct cam_fd_soc_clock_bw_request *)blob_data; if (sizeof(struct cam_fd_soc_clock_bw_request) != blob_size) { - CAM_ERR(CAM_FD, "Invalid blob size %lu %u", + CAM_ERR(CAM_FD, "Invalid blob size %zu %u", sizeof(struct cam_fd_soc_clock_bw_request), blob_size); return -EINVAL; @@ -537,7 +537,7 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl, uint32_t i, j, plane, num_out_buf, num_in_buf; struct cam_buf_io_cfg *io_cfg; dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; - uint64_t cpu_addr[CAM_PACKET_MAX_PLANES]; + uintptr_t cpu_addr[CAM_PACKET_MAX_PLANES]; size_t size; bool need_io_map, need_cpu_map; @@ -583,7 +583,7 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl, rc = cam_mem_get_io_buf( io_cfg[i].mem_handle[plane], iommu_hdl, &io_addr[plane], &size); - if ((rc) || (io_addr[plane] >> 32)) { + if (rc) { CAM_ERR(CAM_FD, "Invalid io buf %d %d %d %d", io_cfg[i].direction, @@ -599,7 +599,8 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl, rc = cam_mem_get_cpu_buf( io_cfg[i].mem_handle[plane], &cpu_addr[plane], &size); - if (rc) { + if (rc || ((io_addr[plane] & 0xFFFFFFFF) + != io_addr[plane])) { CAM_ERR(CAM_FD, "Invalid cpu buf %d %d %d %d", io_cfg[i].direction, @@ -1088,8 +1089,10 @@ static int cam_fd_mgr_hw_get_caps(void *hw_mgr_priv, void *hw_get_caps_args) struct cam_fd_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_query_cap_cmd *query = hw_get_caps_args; struct cam_fd_query_cap_cmd query_fd; + void __user *caps_handle = + u64_to_user_ptr(query->caps_handle); - if (copy_from_user(&query_fd, (void __user *)query->caps_handle, + if (copy_from_user(&query_fd, caps_handle, sizeof(struct cam_fd_query_cap_cmd))) { CAM_ERR(CAM_FD, "Failed in copy from user, rc=%d", rc); return -EFAULT; @@ -1106,7 +1109,7 @@ static int cam_fd_mgr_hw_get_caps(void *hw_mgr_priv, void *hw_get_caps_args) query_fd.hw_caps.wrapper_version.major, query_fd.hw_caps.wrapper_version.minor); - if (copy_to_user((void __user *)query->caps_handle, &query_fd, + if (copy_to_user(caps_handle, &query_fd, sizeof(struct cam_fd_query_cap_cmd))) rc = -EFAULT; diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c index 87dc6949de0c..fa648c7a773e 100644 --- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -651,7 +651,7 @@ int cam_fd_hw_init(void *hw_priv, void *init_hw_args, uint32_t arg_size) } if (arg_size != sizeof(struct cam_fd_hw_init_args)) { - CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size, + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, sizeof(struct cam_fd_hw_init_args)); return -EINVAL; } @@ -735,7 +735,7 @@ int cam_fd_hw_deinit(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) } if (arg_size != sizeof(struct cam_fd_hw_deinit_args)) { - CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size, + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, sizeof(struct cam_fd_hw_deinit_args)); return -EINVAL; } @@ -859,7 +859,7 @@ int cam_fd_hw_start(void *hw_priv, void *hw_start_args, uint32_t arg_size) } if (arg_size != sizeof(struct cam_fd_hw_cmd_start_args)) { - CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size, + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, sizeof(struct cam_fd_hw_cmd_start_args)); return -EINVAL; } @@ -1010,7 +1010,7 @@ int cam_fd_hw_reserve(void *hw_priv, void *hw_reserve_args, uint32_t arg_size) } if (arg_size != sizeof(struct cam_fd_hw_reserve_args)) { - CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size, + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, sizeof(struct cam_fd_hw_reserve_args)); return -EINVAL; } @@ -1079,7 +1079,7 @@ int cam_fd_hw_release(void *hw_priv, void *hw_release_args, uint32_t arg_size) } if (arg_size != sizeof(struct cam_fd_hw_release_args)) { - CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size, + CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size, sizeof(struct cam_fd_hw_release_args)); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h index aae7648ba1e2..ef3b6c9314e2 100644 --- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -111,7 +111,7 @@ struct cam_fd_hw_io_buffer { struct cam_buf_io_cfg *io_cfg; uint32_t num_buf; uint64_t io_addr[CAM_PACKET_MAX_PLANES]; - uint64_t cpu_addr[CAM_PACKET_MAX_PLANES]; + uintptr_t cpu_addr[CAM_PACKET_MAX_PLANES]; }; /** diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c index 502c95d4c60e..522a602883eb 100644 --- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c +++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c @@ -25,9 +25,46 @@ #include "cam_mem_mgr.h" #include "cam_trace.h" #include "cam_debug_util.h" +#include "cam_packet_util.h" static const char icp_dev_name[] = "icp"; +static int cam_icp_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + int rc = 0; + bool b_mem_found = false; + + if (!ctx) { + CAM_ERR(CAM_ICP, "Invalid ctx"); + return -EINVAL; + } + + CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &b_mem_found); + if (rc) + CAM_ERR(CAM_ICP, "Failed to dump pf info"); + + if (b_mem_found) + CAM_ERR(CAM_ICP, "Found page fault in req %lld %d", + req->request_id, rc); + } + + return rc; +} + static int __cam_icp_acquire_dev_in_available(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { @@ -156,6 +193,7 @@ static struct cam_ctx_ops }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, + .pagefault_ops = cam_icp_context_dump_active_request, }, /* Ready */ { @@ -167,12 +205,14 @@ static struct cam_ctx_ops }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, + .pagefault_ops = cam_icp_context_dump_active_request, }, /* Activated */ { .ioctl_ops = {}, .crm_ops = {}, .irq_ops = NULL, + .pagefault_ops = cam_icp_context_dump_active_request, }, }; diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c index 7df806b1b7a3..2ea7738cbdef 100644 --- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c +++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c @@ -35,6 +35,7 @@ #include "cam_hw_mgr_intf.h" #include "cam_icp_hw_mgr_intf.h" #include "cam_debug_util.h" +#include "cam_smmu_api.h" #define CAM_ICP_DEV_NAME "cam-icp" @@ -55,6 +56,25 @@ static const struct of_device_id cam_icp_dt_match[] = { {} }; +static void cam_icp_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_ICP, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + static int cam_icp_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { @@ -96,7 +116,7 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_ERR(CAM_ICP, "ICP subdev is already closed"); + CAM_DBG(CAM_ICP, "ICP subdev is already closed"); rc = -EINVAL; goto end; } @@ -135,6 +155,7 @@ static int cam_icp_probe(struct platform_device *pdev) int rc = 0, i = 0; struct cam_node *node; struct cam_hw_mgr_intf *hw_mgr_intf; + int iommu_hdl = -1; if (!pdev) { CAM_ERR(CAM_ICP, "pdev is NULL"); @@ -158,7 +179,8 @@ static int cam_icp_probe(struct platform_device *pdev) goto hw_alloc_fail; } - rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf); + rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf, + &iommu_hdl); if (rc) { CAM_ERR(CAM_ICP, "ICP HW manager init failed: %d", rc); goto hw_init_fail; @@ -181,6 +203,9 @@ static int cam_icp_probe(struct platform_device *pdev) goto ctx_fail; } + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_icp_dev_iommu_fault_handler, node); + g_icp_dev.open_cnt = 0; mutex_init(&g_icp_dev.icp_lock); diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h index 3e636c65138d..3d0ee725dcad 100644 --- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h @@ -23,10 +23,10 @@ * @reserved: reserved field */ struct hfi_mem { - uint64_t len; - uint64_t kva; - uint32_t iova; - uint32_t reserved; + uint64_t len; + uintptr_t kva; + uint32_t iova; + uint32_t reserved; }; /** diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c index 14a3e656e76d..cbe6886e5712 100644 --- a/drivers/media/platform/msm/camera/cam_icp/hfi.c +++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c @@ -42,6 +42,9 @@ #define HFI_MAX_POLL_TRY 5 +#define HFI_MAX_PC_POLL_TRY 50 +#define HFI_POLL_TRY_SLEEP 20 + static struct hfi_info *g_hfi; unsigned int g_icp_mmu_hdl; static DEFINE_MUTEX(hfi_cmd_q_mutex); @@ -513,8 +516,8 @@ void cam_hfi_disable_cpu(void __iomem *icp_base) uint32_t val; uint32_t try = 0; - while (try < HFI_MAX_POLL_TRY) { - data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS); + while (try < HFI_MAX_PC_POLL_TRY) { + data = cam_io_r_mb(icp_base + HFI_REG_A5_CSR_A5_STATUS); CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data); if (data & ICP_CSR_A5_STATUS_WFI) @@ -523,7 +526,7 @@ void cam_hfi_disable_cpu(void __iomem *icp_base) * and Host can the proceed. No interrupt is expected from FW * at this time. */ - msleep(100); + msleep_interruptible(HFI_POLL_TRY_SLEEP); try++; } @@ -533,6 +536,11 @@ void cam_hfi_disable_cpu(void __iomem *icp_base) val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET); cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET); + + cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET, + icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); + cam_io_w_mb((uint32_t)INTR_DISABLE, + g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN); } void cam_hfi_enable_cpu(void __iomem *icp_base) @@ -883,11 +891,6 @@ void cam_hfi_deinit(void __iomem *icp_base) g_hfi->cmd_q_state = false; g_hfi->msg_q_state = false; - cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET, - icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); - - cam_io_w_mb((uint32_t)INTR_DISABLE, - g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN); kzfree(g_hfi); g_hfi = NULL; diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c index 8f2c76943ebc..18bd6d8dd2c7 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c @@ -167,7 +167,7 @@ static int32_t cam_icp_program_fw(const uint8_t *elf, if (prg_hdr->p_filesz != 0) { src = (u8 *)((u8 *)elf + prg_hdr->p_offset); dest = (u8 *)(((u8 *)core_info->fw_kva_addr) + - prg_hdr->p_vaddr); + prg_hdr->p_vaddr); memcpy_toio(dest, src, prg_hdr->p_filesz); } diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h index f4bc813353a8..9b02167b3c7f 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h @@ -69,7 +69,7 @@ struct cam_a5_device_core_info { const struct firmware *fw_elf; void *fw; uint32_t fw_buf; - uint64_t fw_kva_addr; + uintptr_t fw_kva_addr; uint64_t fw_buf_len; struct cam_icp_a5_query_cap query_cap; struct cam_icp_a5_acquire_dev a5_acquire[8]; diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c index d01637436a51..b969c92ccbc8 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c @@ -199,8 +199,10 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); if (pwr_ctrl & BPS_COLLAPSE_MASK) { - CAM_ERR(CAM_ICP, "BPS: pwr_ctrl(%x)", pwr_ctrl); - return -EINVAL; + CAM_DBG(CAM_ICP, "BPS: pwr_ctrl set(%x)", pwr_ctrl); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0); } rc = cam_bps_transfer_gdsc_control(soc_info); diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 1d5e4832535e..ca8bb3c8d543 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1455,7 +1455,8 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; request_id = ioconfig_ack->user_data2; - ctx_data = (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); if (!ctx_data) { CAM_ERR(CAM_ICP, "Invalid Context"); return -EINVAL; @@ -1562,8 +1563,8 @@ static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr) ipe_config_ack->rc, ioconfig_ack->err_type); return -EIO; } - ctx_data = - (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); if (!ctx_data) { CAM_ERR(CAM_ICP, "wrong ctx data from IPE response"); return -EINVAL; @@ -1577,8 +1578,8 @@ static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr) bps_config_ack->rc, ioconfig_ack->opcode); return -EIO; } - ctx_data = - (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); if (!ctx_data) { CAM_ERR(CAM_ICP, "wrong ctx data from BPS response"); return -EINVAL; @@ -1601,7 +1602,9 @@ static int cam_icp_mgr_process_msg_create_handle(uint32_t *msg_ptr) return -EINVAL; } - ctx_data = (struct cam_icp_hw_ctx_data *)create_handle_ack->user_data1; + ctx_data = + (struct cam_icp_hw_ctx_data *)(uintptr_t) + create_handle_ack->user_data1; if (!ctx_data) { CAM_ERR(CAM_ICP, "Invalid ctx_data"); return -EINVAL; @@ -1632,7 +1635,8 @@ static int cam_icp_mgr_process_msg_ping_ack(uint32_t *msg_ptr) return -EINVAL; } - ctx_data = (struct cam_icp_hw_ctx_data *)ping_ack->user_data; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ping_ack->user_data); if (!ctx_data) { CAM_ERR(CAM_ICP, "Invalid ctx_data"); return -EINVAL; @@ -1696,8 +1700,8 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr) case HFI_IPEBPS_CMD_OPCODE_IPE_ABORT: case HFI_IPEBPS_CMD_OPCODE_BPS_ABORT: ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; - ctx_data = - (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); if (ctx_data->state != CAM_ICP_CTX_STATE_FREE) complete(&ctx_data->wait_complete); CAM_DBG(CAM_ICP, "received IPE/BPS/ ABORT: ctx_state =%d", @@ -1706,8 +1710,8 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr) case HFI_IPEBPS_CMD_OPCODE_IPE_DESTROY: case HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY: ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr; - ctx_data = - (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1; + ctx_data = (struct cam_icp_hw_ctx_data *) + U64_TO_PTR(ioconfig_ack->user_data1); if ((ctx_data->state == CAM_ICP_CTX_STATE_RELEASE) || (ctx_data->state == CAM_ICP_CTX_STATE_IN_USE)) { complete(&ctx_data->wait_complete); @@ -2132,7 +2136,7 @@ static int cam_icp_alloc_shared_mem(struct cam_mem_mgr_memory_desc *qtbl) static int cam_icp_allocate_fw_mem(void) { int rc; - uint64_t kvaddr; + uintptr_t kvaddr; size_t len; dma_addr_t iova; @@ -2146,7 +2150,7 @@ static int cam_icp_allocate_fw_mem(void) icp_hw_mgr.hfi_mem.fw_buf.iova = iova; icp_hw_mgr.hfi_mem.fw_buf.smmu_hdl = icp_hw_mgr.iommu_hdl; - CAM_DBG(CAM_ICP, "kva: %llX, iova: %llx, len: %zu", + CAM_DBG(CAM_ICP, "kva: %zX, iova: %llx, len: %zu", kvaddr, iova, len); return rc; @@ -2486,7 +2490,7 @@ static int cam_icp_mgr_abort_handle( reinit_completion(&ctx_data->wait_complete); abort_cmd->num_fw_handles = 1; abort_cmd->fw_handles[0] = ctx_data->fw_handle; - abort_cmd->user_data1 = (uint64_t)ctx_data; + abort_cmd->user_data1 = PTR_TO_U64(ctx_data); abort_cmd->user_data2 = (uint64_t)0x0; rc = hfi_write_cmd(abort_cmd); @@ -2537,7 +2541,7 @@ static int cam_icp_mgr_destroy_handle( reinit_completion(&ctx_data->wait_complete); destroy_cmd->num_fw_handles = 1; destroy_cmd->fw_handles[0] = ctx_data->fw_handle; - destroy_cmd->user_data1 = (uint64_t)ctx_data; + destroy_cmd->user_data1 = PTR_TO_U64(ctx_data); destroy_cmd->user_data2 = (uint64_t)0x0; memcpy(destroy_cmd->payload.direct, &ctx_data->temp_payload, sizeof(uint64_t)); @@ -3097,7 +3101,7 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data, ioconfig_cmd.num_fw_handles = 1; ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle; ioconfig_cmd.payload.indirect = io_buf_addr; - ioconfig_cmd.user_data1 = (uint64_t)ctx_data; + ioconfig_cmd.user_data1 = PTR_TO_U64(ctx_data); ioconfig_cmd.user_data2 = (uint64_t)0x0; task_data = (struct hfi_cmd_work_data *)task->payload; task_data->data = (void *)&ioconfig_cmd; @@ -3228,7 +3232,7 @@ static int cam_icp_mgr_prepare_frame_process_cmd( hfi_cmd->num_fw_handles = 1; hfi_cmd->fw_handles[0] = ctx_data->fw_handle; hfi_cmd->payload.indirect = fw_cmd_buf_iova_addr; - hfi_cmd->user_data1 = (uint64_t)ctx_data; + hfi_cmd->user_data1 = PTR_TO_U64(ctx_data); hfi_cmd->user_data2 = request_id; CAM_DBG(CAM_ICP, "ctx_data : %pK, request_id :%lld cmd_buf %x", @@ -3277,7 +3281,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, dma_addr_t addr; size_t len; struct cam_cmd_buf_desc *cmd_desc = NULL; - uint64_t cpu_addr = 0; + uintptr_t cpu_addr = 0; struct ipe_frame_process_data *frame_process_data = NULL; struct bps_frame_process_data *bps_frame_process_data = NULL; struct frame_set *ipe_set = NULL; @@ -3318,7 +3322,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS) { - CAM_DBG(CAM_ICP, "cpu addr = %llx", cpu_addr); + CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr); frame_process_data = (struct ipe_frame_process_data *)cpu_addr; CAM_DBG(CAM_ICP, "%u %u %u", frame_process_data->max_num_cores, frame_process_data->target_time, @@ -3339,7 +3343,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr, } } } else { - CAM_DBG(CAM_ICP, "cpu addr = %llx", cpu_addr); + CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr); bps_frame_process_data = (struct bps_frame_process_data *)cpu_addr; CAM_DBG(CAM_ICP, "%u %u", @@ -3388,10 +3392,11 @@ static int cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr, prepare_args->num_out_map_entries++; } CAM_DBG(CAM_REQ, - "ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u", + "ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u memh %x", ctx_data->ctx_id, packet->header.request_id, i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence, - io_cfg_ptr[i].resource_type); + io_cfg_ptr[i].resource_type, + io_cfg_ptr[i].mem_handle[0]); } if (prepare_args->num_in_map_entries > 1) @@ -3439,7 +3444,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data, uint32_t index; size_t io_buf_size; int rc = 0; - uint64_t pResource; + uintptr_t pResource; if (!blob_data || (blob_size == 0)) { CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data, @@ -3545,7 +3550,7 @@ static int cam_icp_mgr_process_cfg_io_cmd( ioconfig_cmd->num_fw_handles = 1; ioconfig_cmd->fw_handles[0] = ctx_data->fw_handle; ioconfig_cmd->payload.indirect = io_config; - ioconfig_cmd->user_data1 = (uint64_t)ctx_data; + ioconfig_cmd->user_data1 = PTR_TO_U64(ctx_data); ioconfig_cmd->user_data2 = request_id; return 0; @@ -3593,6 +3598,77 @@ static int cam_icp_mgr_update_hfi_frame_process( return rc; } +static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + uint64_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_ICP, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_ICP, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get src buf address fail"); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_ICP, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_ICP, + "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x", + j, io_cfg[i].planes[j].width, + io_cfg[i].planes[j].height, + (int32_t)src_buf_size, + (unsigned int)iova_addr, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + + iova_addr += io_cfg[i].offsets[j]; + + } + } +} + static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) { @@ -3635,6 +3711,8 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv, return rc; } + prepare_args->pf_data->packet = packet; + CAM_DBG(CAM_REQ, "req id = %lld for ctx = %u", packet->header.request_id, ctx_data->ctx_id); /* Update Buffer Address from handles and patch information */ @@ -3671,7 +3749,7 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv, fw_cmd_buf_iova_addr); prepare_args->num_hw_update_entries = 1; - prepare_args->hw_update_entries[0].addr = (uint64_t)hfi_cmd; + prepare_args->hw_update_entries[0].addr = (uintptr_t)hfi_cmd; prepare_args->priv = &ctx_data->hfi_frame_process.frame_info[idx]; CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u", @@ -3968,7 +4046,7 @@ static int cam_icp_mgr_create_handle(uint32_t dev_type, create_handle.size = sizeof(struct hfi_cmd_create_handle); create_handle.pkt_type = HFI_CMD_IPEBPS_CREATE_HANDLE; create_handle.handle_type = dev_type; - create_handle.user_data1 = (uint64_t)ctx_data; + create_handle.user_data1 = PTR_TO_U64(ctx_data); reinit_completion(&ctx_data->wait_complete); task_data = (struct hfi_cmd_work_data *)task->payload; task_data->data = (void *)&create_handle; @@ -4013,7 +4091,7 @@ static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data) ping_pkt.size = sizeof(struct hfi_cmd_ping_pkt); ping_pkt.pkt_type = HFI_CMD_SYS_PING; - ping_pkt.user_data = (uint64_t)ctx_data; + ping_pkt.user_data = PTR_TO_U64(ctx_data); init_completion(&ctx_data->wait_complete); task_data = (struct hfi_cmd_work_data *)task->payload; task_data->data = (void *)&ping_pkt; @@ -4313,7 +4391,7 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) mutex_lock(&hw_mgr->hw_mgr_mutex); if (copy_from_user(&icp_hw_mgr.icp_caps, - (void __user *)query_cap->caps_handle, + u64_to_user_ptr(query_cap->caps_handle), sizeof(struct cam_icp_query_cap_cmd))) { CAM_ERR(CAM_ICP, "copy_from_user failed"); rc = -EFAULT; @@ -4327,7 +4405,7 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) icp_hw_mgr.icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl; icp_hw_mgr.icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl; - if (copy_to_user((void __user *)query_cap->caps_handle, + if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), &icp_hw_mgr.icp_caps, sizeof(struct cam_icp_query_cap_cmd))) { CAM_ERR(CAM_ICP, "copy_to_user failed"); rc = -EFAULT; @@ -4551,7 +4629,35 @@ cmd_work_failed: return rc; } -int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl) +static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_ICP, "Invalid arguments"); + return -EINVAL; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_icp_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->iommu_hdl, + hw_mgr->iommu_sec_hdl, + hw_cmd_args->u.pf_args.buf_info, + hw_cmd_args->u.pf_args.mem_found); + break; + default: + CAM_ERR(CAM_ICP, "Invalid cmd"); + } + + return rc; +} + +int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, + int *iommu_hdl) { int i, rc = 0; struct cam_hw_mgr_intf *hw_mgr_intf; @@ -4574,6 +4680,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl) hw_mgr_intf->hw_open = cam_icp_mgr_hw_open_u; hw_mgr_intf->hw_close = cam_icp_mgr_hw_close_u; hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush; + hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd; icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE; mutex_init(&icp_hw_mgr.hw_mgr_mutex); @@ -4617,6 +4724,9 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl) if (rc) goto icp_wq_create_failed; + if (iommu_hdl) + *iommu_hdl = icp_hw_mgr.iommu_hdl; + init_completion(&icp_hw_mgr.a5_complete); return rc; diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h index 771c4ed7c55c..7bb9b9ed18a2 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h @@ -28,7 +28,7 @@ #define CPAS_IPE1_BIT 0x2000 int cam_icp_hw_mgr_init(struct device_node *of_node, - uint64_t *hw_mgr_hdl); + uint64_t *hw_mgr_hdl, int *iommu_hdl); /** * struct cam_icp_cpas_vote diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c index 620a4bd4943b..142fcdc6017d 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -195,9 +195,12 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); if (pwr_ctrl & IPE_COLLAPSE_MASK) { - CAM_ERR(CAM_ICP, "IPE: resume failed : %d", pwr_ctrl); - return -EINVAL; + CAM_DBG(CAM_ICP, "IPE pwr_ctrl set(%x)", pwr_ctrl); + cam_cpas_reg_write(core_info->cpas_handle, + CAM_CPAS_REG_CPASTOP, + hw_info->pwr_ctrl, true, 0); } + rc = cam_ipe_transfer_gdsc_control(soc_info); cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 5760371bbde3..aaa172deea97 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -23,8 +23,15 @@ #include "cam_req_mgr_dev.h" #include "cam_trace.h" #include "cam_debug_util.h" +#include "cam_packet_util.h" +#include "cam_context_utils.h" +#include "cam_common_util.h" static const char isp_dev_name[] = "isp"; + +static int cam_isp_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info); + static void __cam_isp_ctx_update_state_monitor_array( struct cam_isp_context *ctx_isp, enum cam_isp_state_change_trigger trigger_type, @@ -375,7 +382,7 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( continue; } - if (!bubble_state) { + if (!req_isp->bubble_detected) { CAM_DBG(CAM_ISP, "Sync with success: req %lld res 0x%x fd 0x%x", req->request_id, @@ -402,15 +409,14 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( } else { /* * Ignore the buffer done if bubble detect is on - * In most case, active list should be empty when - * bubble detects. But for safety, we just move the - * current active request to the pending list here. + * Increment the ack number here, and queue the + * request back to pending list whenever all the + * buffers are done. */ + req_isp->num_acked++; CAM_DBG(CAM_ISP, "buf done with bubble state %d recovery %d", bubble_state, req_isp->bubble_report); - list_del_init(&req->list); - list_add(&req->list, &ctx->pending_req_list); continue; } @@ -431,10 +437,25 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( req_isp->num_fence_map_out); WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out); } - if (req_isp->num_acked == req_isp->num_fence_map_out) { + + if (req_isp->num_acked != req_isp->num_fence_map_out) + return rc; + + ctx_isp->active_req_cnt--; + + if (req_isp->bubble_detected && req_isp->bubble_report) { + req_isp->num_acked = 0; + req_isp->bubble_detected = false; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + + CAM_DBG(CAM_REQ, + "Move active request %lld to pending list(cnt = %d) [bubble recovery]", + req->request_id, ctx_isp->active_req_cnt); + } else { list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); - ctx_isp->active_req_cnt--; + CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done]", req->request_id, ctx_isp->active_req_cnt); @@ -732,15 +753,13 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; - list_del_init(&req->list); - list_add(&req->list, &ctx->pending_req_list); - notify.link_hdl = ctx->link_hdl; notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; @@ -749,18 +768,19 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld", ctx_isp->frame_id); } else { - /* - * Since can not bubble report, always move the request to - * active list. - */ - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->active_req_list); - ctx_isp->active_req_cnt++; - CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)", - req->request_id, ctx_isp->active_req_cnt); req_isp->bubble_report = 0; } + /* + * Always move the request to active list. Let buf done + * function handles the rest. + */ + CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)", + req->request_id, ctx_isp->active_req_cnt); + ctx_isp->active_req_cnt++; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + if (req->request_id > ctx_isp->reported_req_id) { request_id = req->request_id; ctx_isp->reported_req_id = request_id; @@ -882,13 +902,12 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; - list_del_init(&req->list); + req_isp->bubble_detected = true; if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; - list_add(&req->list, &ctx->pending_req_list); notify.link_hdl = ctx->link_hdl; notify.dev_hdl = ctx->dev_hdl; notify.req_id = req->request_id; @@ -898,17 +917,19 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( "Notify CRM about Bubble req_id %llu frame %lld", req->request_id, ctx_isp->frame_id); } else { - /* - * If we can not report bubble, then treat it as if no bubble - * report. Just move the req to active list. - */ - list_add_tail(&req->list, &ctx->active_req_list); - ctx_isp->active_req_cnt++; - CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)", - req->request_id, ctx_isp->active_req_cnt); req_isp->bubble_report = 0; } + /* + * Always move the request to active list. Let buf done + * function handles the rest. + */ + CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)", + req->request_id, ctx_isp->active_req_cnt); + ctx_isp->active_req_cnt++; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + if (!req_isp->bubble_report) { if (req->request_id > ctx_isp->reported_req_id) { request_id = req->request_id; @@ -1411,6 +1432,7 @@ static int __cam_isp_ctx_flush_req_in_top_state( CAM_DBG(CAM_ISP, "try to flush active list"); rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list, flush_req); + ctx_isp->active_req_cnt = 0; spin_unlock_bh(&ctx->lock); /* Start hw */ @@ -1609,12 +1631,12 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", ctx_isp->frame_id, ctx_isp->sof_timestamp_val); - if (list_empty(&ctx->pending_req_list)) { + if (list_empty(&ctx->wait_req_list)) { /* * If no pending req in epoch, this is an error case. * The recovery is to go back to sof state */ - CAM_ERR(CAM_ISP, "No pending request"); + CAM_ERR(CAM_ISP, "No wait request"); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; /* Send SOF event as empty frame*/ @@ -1624,9 +1646,10 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( goto end; } - req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, + req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request, list); req_isp = (struct cam_isp_ctx_req *)req->req_priv; + req_isp->bubble_detected = true; CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report); if (req_isp->bubble_report && ctx->ctx_crm_intf && @@ -1641,18 +1664,19 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld", ctx_isp->frame_id); } else { - /* - * Since can not bubble report, always move the request to - * active list. - */ - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->active_req_list); - ctx_isp->active_req_cnt++; - CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)", - req->request_id, ctx_isp->active_req_cnt); req_isp->bubble_report = 0; } + /* + * Always move the request to active list. Let buf done + * function handles the rest. + */ + ctx_isp->active_req_cnt++; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->active_req_list); + CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)", + req->request_id, ctx_isp->active_req_cnt); + if (!req_isp->bubble_report) { if (req->request_id > ctx_isp->reported_req_id) { request_id = req->request_id; @@ -2008,7 +2032,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( int rc = 0, i; struct cam_ctx_request *req = NULL; struct cam_isp_ctx_req *req_isp; - uint64_t packet_addr; + uintptr_t packet_addr; struct cam_packet *packet; size_t len = 0; struct cam_hw_prepare_update_args cfg; @@ -2038,16 +2062,16 @@ static int __cam_isp_ctx_config_dev_in_top_state( /* for config dev, only memory handle is supported */ /* map packet from the memhandle */ rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle, - (uint64_t *) &packet_addr, &len); + &packet_addr, &len); if (rc != 0) { CAM_ERR(CAM_ISP, "Can not get packet address"); rc = -EINVAL; goto free_req; } - packet = (struct cam_packet *) (packet_addr + cmd->offset); + packet = (struct cam_packet *)(packet_addr + (uint32_t)cmd->offset); CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle); - CAM_DBG(CAM_ISP, "packet address is 0x%llx", packet_addr); + CAM_DBG(CAM_ISP, "packet address is 0x%zx", packet_addr); CAM_DBG(CAM_ISP, "packet with length %zu, offset 0x%llx", len, cmd->offset); CAM_DBG(CAM_ISP, "Packet request id %lld", @@ -2066,6 +2090,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( cfg.out_map_entries = req_isp->fence_map_out; cfg.in_map_entries = req_isp->fence_map_in; cfg.priv = &req_isp->hw_update_data; + cfg.pf_data = &(req->pf_data); CAM_DBG(CAM_ISP, "try to prepare config packet......"); @@ -2080,6 +2105,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( req_isp->num_fence_map_out = cfg.num_out_map_entries; req_isp->num_fence_map_in = cfg.num_in_map_entries; req_isp->num_acked = 0; + req_isp->bubble_detected = false; for (i = 0; i < req_isp->num_fence_map_out; i++) { rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id); @@ -2164,7 +2190,8 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, struct cam_hw_release_args release; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; - struct cam_isp_hw_cmd_args hw_cmd_args; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; if (!ctx->hw_mgr_intf) { CAM_ERR(CAM_ISP, "HW interface is not ready"); @@ -2200,7 +2227,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, CAM_DBG(CAM_ISP, "start copy %d resources from user", cmd->num_resources); - if (copy_from_user(isp_res, (void __user *)cmd->resource_hdl, + if (copy_from_user(isp_res, u64_to_user_ptr(cmd->resource_hdl), sizeof(*isp_res)*cmd->num_resources)) { rc = -EFAULT; goto free_res; @@ -2209,7 +2236,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, param.context_data = ctx; param.event_cb = ctx->irq_cb_intf; param.num_acq = cmd->num_resources; - param.acquire_info = (uint64_t) isp_res; + param.acquire_info = (uintptr_t) isp_res; /* call HW manager to reserve the resource */ rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, @@ -2221,7 +2248,9 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, /* Query the context has rdi only resource */ hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map; - hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT; + hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { @@ -2229,7 +2258,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, goto free_hw; } - if (hw_cmd_args.u.is_rdi_only_context) { + if (isp_hw_cmd_args.u.is_rdi_only_context) { /* * this context has rdi only resource assign rdi only * state machine @@ -2248,8 +2277,9 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, cam_isp_ctx_activated_state_machine; } - ctx_isp->rdi_only_context = hw_cmd_args.u.is_rdi_only_context; + ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context; ctx_isp->hw_ctx = param.ctxt_to_hw_map; + ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; req_hdl_param.session_hdl = cmd->session_handle; /* bridge is not ready for these flags. so false for now */ @@ -2276,7 +2306,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, CAM_DBG(CAM_ISP, "Acquire success on session_hdl 0x%x num_rsrces %d RDI only %d ctx %u", cmd->session_handle, cmd->num_resources, - (hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id); + (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id); kfree(isp_res); return rc; @@ -2567,12 +2597,15 @@ static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx, static int __cam_isp_ctx_link_pause(struct cam_context *ctx) { int rc = 0; - struct cam_isp_hw_cmd_args hw_cmd_args; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; - hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW; + hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); @@ -2582,12 +2615,15 @@ static int __cam_isp_ctx_link_pause(struct cam_context *ctx) static int __cam_isp_ctx_link_resume(struct cam_context *ctx) { int rc = 0; - struct cam_isp_hw_cmd_args hw_cmd_args; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; - hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW; + hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); @@ -2598,13 +2634,16 @@ static int __cam_isp_ctx_handle_sof_freeze_evt( struct cam_context *ctx) { int rc = 0; - struct cam_isp_hw_cmd_args hw_cmd_args; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx; - hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_SOF_DEBUG; - hw_cmd_args.u.sof_irq_enable = 1; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_SOF_DEBUG; + isp_hw_cmd_args.u.sof_irq_enable = 1; + hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); @@ -2746,6 +2785,7 @@ static struct cam_ctx_ops .flush_req = __cam_isp_ctx_flush_req_in_top_state, }, .irq_ops = NULL, + .pagefault_ops = cam_isp_context_dump_active_request, }, /* Ready */ { @@ -2759,6 +2799,7 @@ static struct cam_ctx_ops .flush_req = __cam_isp_ctx_flush_req_in_ready, }, .irq_ops = NULL, + .pagefault_ops = cam_isp_context_dump_active_request, }, /* Activated */ { @@ -2774,10 +2815,55 @@ static struct cam_ctx_ops .process_evt = __cam_isp_ctx_process_evt, }, .irq_ops = __cam_isp_ctx_handle_irq_in_activated, + .pagefault_ops = cam_isp_context_dump_active_request, }, }; +static int cam_isp_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_prepare_hw_update_data *hw_update_data = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + bool mem_found = false; + int rc = 0; + + struct cam_isp_context *isp_ctx = + (struct cam_isp_context *)ctx->ctx_priv; + + if (!isp_ctx) { + CAM_ERR(CAM_ISP, "Invalid isp ctx"); + return -EINVAL; + } + + CAM_INFO(CAM_ISP, "iommu fault handler for isp ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + hw_update_data = &req_isp->hw_update_data; + pf_dbg_entry = &(req->pf_data); + CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &mem_found); + if (rc) + CAM_ERR(CAM_ISP, "Failed to dump pf info"); + + if (mem_found) + CAM_ERR(CAM_ISP, "Found page fault in req %lld %d", + req->request_id, rc); + } + + return rc; +} + int cam_isp_context_init(struct cam_isp_context *ctx, struct cam_context *ctx_base, struct cam_req_mgr_kmd_ops *crm_node_intf, diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h index 4592e42932d8..6f89841d22bc 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h @@ -115,6 +115,7 @@ struct cam_isp_ctx_req { uint32_t num_acked; int32_t bubble_report; struct cam_isp_prepare_hw_update_data hw_update_data; + bool bubble_detected; }; /** diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c index a067915bed7d..c7e5d3836fda 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c @@ -26,9 +26,29 @@ #include "cam_isp_hw_mgr_intf.h" #include "cam_node.h" #include "cam_debug_util.h" +#include "cam_smmu_api.h" static struct cam_isp_dev g_isp_dev; +static void cam_isp_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_ISP, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + static const struct of_device_id cam_isp_dt_match[] = { { .compatible = "qcom,cam-isp" @@ -36,23 +56,47 @@ static const struct of_device_id cam_isp_dt_match[] = { {} }; +static int cam_isp_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + mutex_lock(&g_isp_dev.isp_mutex); + g_isp_dev.open_cnt++; + mutex_unlock(&g_isp_dev.isp_mutex); + + return 0; +} + static int cam_isp_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { + int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); + mutex_lock(&g_isp_dev.isp_mutex); + if (g_isp_dev.open_cnt <= 0) { + CAM_DBG(CAM_ISP, "ISP subdev is already closed"); + rc = -EINVAL; + goto end; + } + + g_isp_dev.open_cnt--; if (!node) { CAM_ERR(CAM_ISP, "Node ptr is NULL"); - return -EINVAL; + rc = -EINVAL; + goto end; } - cam_node_shutdown(node); + if (g_isp_dev.open_cnt == 0) + cam_node_shutdown(node); - return 0; +end: + mutex_unlock(&g_isp_dev.isp_mutex); + return rc; } static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .close = cam_isp_subdev_close, + .open = cam_isp_subdev_open, }; static int cam_isp_dev_remove(struct platform_device *pdev) @@ -82,6 +126,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev) int i; struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; + int iommu_hdl = -1; g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; /* Initialze the v4l2 subdevice first. (create cam_node) */ @@ -94,7 +139,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev) node = (struct cam_node *) g_isp_dev.sd.token; memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf)); - rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf); + rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf, &iommu_hdl); if (rc != 0) { CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!"); goto unregister; @@ -119,6 +164,11 @@ static int cam_isp_dev_probe(struct platform_device *pdev) goto unregister; } + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_isp_dev_iommu_fault_handler, node); + + mutex_init(&g_isp_dev.isp_mutex); + CAM_INFO(CAM_ISP, "Camera ISP probe complete"); return 0; diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h index 95463ca37a13..a88ed5533907 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -24,12 +24,15 @@ * @sd: Commone camera subdevice node * @ctx: Isp base context storage * @ctx_isp: Isp private context storage - * + * @isp_mutex: ISP dev mutex + * @open_cnt: Open device count */ struct cam_isp_dev { struct cam_subdev sd; struct cam_context ctx[CAM_CTX_MAX]; struct cam_isp_context ctx_isp[CAM_CTX_MAX]; + struct mutex isp_mutex; + int32_t open_cnt; }; #endif /* __CAM_ISP_DEV_H__ */ diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7e0aa4b62ba7..d29506fb8a21 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -28,6 +28,8 @@ #include "cam_packet_util.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include "cam_mem_mgr_api.h" +#include "cam_common_util.h" #define CAM_IFE_HW_ENTRIES_MAX 20 @@ -94,7 +96,8 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "enter"); - if (copy_from_user(&query_isp, (void __user *)query->caps_handle, + if (copy_from_user(&query_isp, + u64_to_user_ptr(query->caps_handle), sizeof(struct cam_isp_query_cap_cmd))) { rc = -EFAULT; return rc; @@ -113,8 +116,8 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv, query_isp.dev_caps[i].hw_version.reserved = 0; } - if (copy_to_user((void __user *)query->caps_handle, &query_isp, - sizeof(struct cam_isp_query_cap_cmd))) + if (copy_to_user(u64_to_user_ptr(query->caps_handle), + &query_isp, sizeof(struct cam_isp_query_cap_cmd))) rc = -EFAULT; CAM_DBG(CAM_ISP, "exit rc :%d", rc); @@ -1561,7 +1564,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, goto free_res; } - in_port = memdup_user((void __user *)isp_resource[i].res_hdl, + in_port = memdup_user( + u64_to_user_ptr(isp_resource[i].res_hdl), isp_resource[i].length); if (!IS_ERR(in_port)) { in_port_length = sizeof(struct cam_isp_in_port_info) + @@ -2161,7 +2165,8 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) struct cam_isp_stop_args stop_isp; struct cam_ife_hw_mgr_ctx *ctx; struct cam_ife_hw_mgr_res *hw_mgr_res; - uint32_t i; + struct cam_isp_resource_node *rsrc_node = NULL; + uint32_t i, camif_debug; if (!hw_mgr_priv || !start_isp) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -2195,6 +2200,24 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) sizeof(g_ife_hw_mgr.debug_cfg.csid_debug)); } + camif_debug = g_ife_hw_mgr.debug_cfg.camif_debug; + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->process_cmd && (rsrc_node->res_id == + CAM_ISP_HW_VFE_IN_CAMIF)) { + rc = hw_mgr_res->hw_res[i]->process_cmd( + hw_mgr_res->hw_res[i], + CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + &camif_debug, + sizeof(camif_debug)); + } + } + } + rc = cam_ife_hw_mgr_init_hw(ctx); if (rc) { CAM_ERR(CAM_ISP, "Init failed"); @@ -2806,45 +2829,133 @@ static int cam_ife_mgr_sof_irq_debug( return rc; } +static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + uint64_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_ISP, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_ISP, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_ISP, "get src buf address fail"); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_ISP, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_ISP, + "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x", + j, io_cfg[i].planes[j].width, + io_cfg[i].planes[j].height, + (int32_t)src_buf_size, + (unsigned int)iova_addr, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + } + } +} + static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; - struct cam_isp_hw_cmd_args *hw_cmd_args = cmd_args; - struct cam_ife_hw_mgr_ctx *ctx; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *) + hw_cmd_args->ctxt_to_hw_map; if (!hw_mgr_priv || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); return -EINVAL; } - ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_ISP, "Fatal: Invalid context is used"); return -EPERM; } switch (hw_cmd_args->cmd_type) { - case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT: - if (ctx->is_rdi_only_context) - hw_cmd_args->u.is_rdi_only_context = 1; - else - hw_cmd_args->u.is_rdi_only_context = 0; - - break; - case CAM_ISP_HW_MGR_CMD_PAUSE_HW: - cam_ife_mgr_pause_hw(ctx); - break; - case CAM_ISP_HW_MGR_CMD_RESUME_HW: - cam_ife_mgr_resume_hw(ctx); + case CAM_HW_MGR_CMD_INTERNAL: { + struct cam_isp_hw_cmd_args *isp_hw_cmd_args = + (struct cam_isp_hw_cmd_args *)hw_cmd_args-> + u.internal_args; + + switch (isp_hw_cmd_args->cmd_type) { + case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT: + if (ctx->is_rdi_only_context) + isp_hw_cmd_args->u.is_rdi_only_context = 1; + else + isp_hw_cmd_args->u.is_rdi_only_context = 0; + break; + case CAM_ISP_HW_MGR_CMD_PAUSE_HW: + cam_ife_mgr_pause_hw(ctx); + break; + case CAM_ISP_HW_MGR_CMD_RESUME_HW: + cam_ife_mgr_resume_hw(ctx); + break; + case CAM_ISP_HW_MGR_CMD_SOF_DEBUG: + cam_ife_mgr_sof_irq_debug(ctx, + isp_hw_cmd_args->u.sof_irq_enable); + break; + default: + CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", + hw_cmd_args->cmd_type); + rc = -EINVAL; + break; + } break; - case CAM_ISP_HW_MGR_CMD_SOF_DEBUG: - cam_ife_mgr_sof_irq_debug(ctx, hw_cmd_args->u.sof_irq_enable); + } + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_ife_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->mgr_common.img_iommu_hdl, + hw_mgr->mgr_common.img_iommu_hdl_secure, + hw_cmd_args->u.pf_args.buf_info, + hw_cmd_args->u.pf_args.mem_found); break; default: - CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", - hw_cmd_args->cmd_type); - rc = -EINVAL; - break; + CAM_ERR(CAM_ISP, "Invalid cmd"); } return rc; @@ -4040,8 +4151,8 @@ int cam_ife_mgr_do_tasklet_buf_done(void *handler_priv, evt_payload = evt_payload_priv; ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)evt_payload->ctx; - CAM_DBG(CAM_ISP, "addr of evt_payload = %llx core index:0x%x", - (uint64_t)evt_payload, evt_payload->core_index); + CAM_DBG(CAM_ISP, "addr of evt_payload = %pK core index:0x%x", + evt_payload, evt_payload->core_index); CAM_DBG(CAM_ISP, "bus_irq_status_0: = %x", evt_payload->irq_reg_val[0]); CAM_DBG(CAM_ISP, "bus_irq_status_1: = %x", evt_payload->irq_reg_val[1]); CAM_DBG(CAM_ISP, "bus_irq_status_2: = %x", evt_payload->irq_reg_val[2]); @@ -4176,6 +4287,28 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_ife_csid_debug, cam_ife_get_csid_debug, cam_ife_set_csid_debug, "%16llu"); +static int cam_ife_set_camif_debug(void *data, u64 val) +{ + g_ife_hw_mgr.debug_cfg.camif_debug = val; + CAM_DBG(CAM_ISP, + "Set camif enable_diag_sensor_status value :%lld", val); + return 0; +} + +static int cam_ife_get_camif_debug(void *data, u64 *val) +{ + *val = g_ife_hw_mgr.debug_cfg.camif_debug; + CAM_DBG(CAM_ISP, + "Set camif enable_diag_sensor_status value :%lld", + g_ife_hw_mgr.debug_cfg.csid_debug); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug, + cam_ife_get_camif_debug, + cam_ife_set_camif_debug, "%16llu"); + static int cam_ife_hw_mgr_debug_register(void) { g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife", @@ -4201,6 +4334,14 @@ static int cam_ife_hw_mgr_debug_register(void) CAM_ERR(CAM_ISP, "failed to create enable_recovery"); goto err; } + + if (!debugfs_create_file("ife_camif_debug", + 0644, + g_ife_hw_mgr.debug_cfg.dentry, NULL, + &cam_ife_camif_debug)) { + CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug"); + goto err; + } g_ife_hw_mgr.debug_cfg.enable_recovery = 0; return 0; @@ -4210,7 +4351,7 @@ err: return -ENOMEM; } -int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf) +int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { int rc = -EFAULT; int i, j; @@ -4382,6 +4523,9 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf) hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; + if (iommu_hdl) + *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; + cam_ife_hw_mgr_debug_register(); CAM_DBG(CAM_ISP, "Exit"); diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 0198f3d62e9c..9bfa34fe91ab 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -81,15 +81,17 @@ struct ctx_base_info { /** * struct cam_ife_hw_mgr_debug - contain the debug information * - * @dentry: Debugfs entry - * @csid_debug: csid debug information - * @enable_recovery enable recovery + * @dentry: Debugfs entry + * @csid_debug: csid debug information + * @enable_recovery: enable recovery + * @enable_diag_sensor_status: enable sensor diagnosis status * */ struct cam_ife_hw_mgr_debug { struct dentry *dentry; uint64_t csid_debug; uint32_t enable_recovery; + uint32_t camif_debug; }; /** @@ -203,9 +205,10 @@ struct cam_ife_hw_mgr { * etnry functinon for the IFE HW manager. * * @hw_mgr_intf: IFE hardware manager object returned + * @iommu_hdl: Iommu handle to be returned * */ -int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf); +int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl); /** * cam_ife_mgr_do_tasklet_buf_done() diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c index 2f18895c2402..8b9c555cae17 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,7 +16,7 @@ int cam_isp_hw_mgr_init(struct device_node *of_node, - struct cam_hw_mgr_intf *hw_mgr) + struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl) { int rc = 0; const char *compat_str = NULL; @@ -25,7 +25,7 @@ int cam_isp_hw_mgr_init(struct device_node *of_node, (const char **)&compat_str); if (strnstr(compat_str, "ife", strlen(compat_str))) - rc = cam_ife_hw_mgr_init(hw_mgr); + rc = cam_ife_hw_mgr_init(hw_mgr, iommu_hdl); else { CAM_ERR(CAM_ISP, "Invalid ISP hw type"); rc = -EINVAL; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index eaa7325fbca8..f652256d3dc5 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -457,6 +457,7 @@ int cam_isp_add_io_buffers( num_out_buf = 0; num_in_buf = 0; io_cfg_used_bytes = 0; + prepare->pf_data->packet = prepare->packet; /* Max one hw entries required for each base */ if (prepare->num_hw_update_entries + 1 >= @@ -595,13 +596,6 @@ int cam_isp_add_io_buffers( return rc; } - if (io_addr[plane_id] >> 32) { - CAM_ERR(CAM_ISP, - "Invalid mapped address"); - rc = -EINVAL; - return rc; - } - /* need to update with offset */ io_addr[plane_id] += io_cfg[i].offsets[plane_id]; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index fd71c37c8fa1..1586216f2073 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -203,13 +203,11 @@ enum cam_isp_hw_mgr_command { /** * struct cam_isp_hw_cmd_args - Payload for hw manager command * - * @ctxt_to_hw_map: HW context from the acquire * @cmd_type HW command type * @get_context Get context type information */ struct cam_isp_hw_cmd_args { - void *ctxt_to_hw_map; - uint32_t cmd_type; + uint32_t cmd_type; union { uint32_t is_rdi_only_context; uint32_t sof_irq_enable; @@ -225,9 +223,9 @@ struct cam_isp_hw_cmd_args { * @of_node: Device node input * @hw_mgr: Input/output structure for the ISP hardware manager * initialization - * + * @iommu_hdl: Iommu handle to be returned */ int cam_isp_hw_mgr_init(struct device_node *of_node, - struct cam_hw_mgr_intf *hw_mgr); + struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl); #endif /* __CAM_ISP_HW_MGR_INTF_H__ */ diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h index c68ddf7343fc..f90356aa2e5c 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -52,6 +52,7 @@ static struct cam_ife_csid_ipp_reg_offset cam_ife_csid_170_ipp_reg_offset = { .csid_ipp_timestamp_perv1_eof_addr = 0x2ac, /* configurations */ .pix_store_en_shift_val = 7, + .early_eof_en_shift_val = 29, }; static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_170_rdi_0_reg_offset = { @@ -286,6 +287,8 @@ static struct cam_ife_csid_common_reg_offset .crop_shift = 16, .ipp_irq_mask_all = 0x7FFF, .rdi_irq_mask_all = 0x7FFF, + .measure_en_hbi_vbi_cnt_mask = 0xC, + .format_measure_en_val = 1, }; struct cam_ife_csid_reg_offset cam_ife_csid_170_reg_offset = { diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 47f44ea4785c..9ffd923b55cb 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1395,8 +1395,12 @@ static int cam_ife_csid_init_config_ipp_path( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_ipp_cfg0_addr); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_cfg1_addr); + /* select the post irq sub sample strobe for time stamp capture */ - cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base + + val |= CSID_TIMESTAMP_STB_POST_IRQ; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_ipp_cfg1_addr); if (path_data->crop_enable) { @@ -1415,6 +1419,16 @@ static int cam_ife_csid_init_config_ipp_path( csid_reg->ipp_reg->csid_ipp_vcrop_addr); CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", csid_hw->hw_intf->hw_idx, val); + + /* Enable generating early eof strobe based on crop config */ + if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_cfg0_addr); + val |= (1 << + csid_reg->ipp_reg->early_eof_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_cfg0_addr); + } } /* set frame drop pattern to 0 and period to 1 */ @@ -1443,9 +1457,23 @@ static int cam_ife_csid_init_config_ipp_path( val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_ipp_cfg0_addr); val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) + val |= csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_ipp_cfg0_addr); + /* Enable the HBI/VBI counter */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_format_measure_cfg0_addr); + val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_format_measure_cfg0_addr); + } + /* configure the rx packet capture based on csid debug set */ val = 0; if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) @@ -1484,8 +1512,10 @@ static int cam_ife_csid_deinit_ipp_path( struct cam_isp_resource_node *res) { int rc = 0; + uint32_t val = 0; struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_ife_csid_ipp_reg_offset *ipp_reg; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1503,8 +1533,26 @@ static int cam_ife_csid_deinit_ipp_path( csid_hw->hw_intf->hw_idx, res->res_id); rc = -EINVAL; + goto end; } + ipp_reg = csid_reg->ipp_reg; + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ipp_reg->csid_ipp_cfg0_addr); + if (val & csid_reg->cmn_reg->format_measure_en_val) { + val &= ~csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + ipp_reg->csid_ipp_cfg0_addr); + + /* Disable the HBI/VBI counter */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ipp_reg->csid_ipp_format_measure_cfg0_addr); + val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + ipp_reg->csid_ipp_format_measure_cfg0_addr); + } + +end: res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; return rc; } @@ -1649,6 +1697,7 @@ static int cam_ife_csid_init_config_rdi_path( struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; uint32_t path_format = 0, plain_fmt = 0, val = 0, id; + uint32_t format_measure_addr; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -1742,9 +1791,24 @@ static int cam_ife_csid_init_config_rdi_path( csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); val |= (1 << csid_reg->cmn_reg->path_en_shift_val); + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) + val |= csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + format_measure_addr = + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr; + + /* Enable the HBI/VBI counter */ + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + format_measure_addr); + val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + format_measure_addr); + } + /* configure the rx packet capture based on csid debug set */ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) val = ((1 << @@ -1780,7 +1844,7 @@ static int cam_ife_csid_deinit_rdi_path( struct cam_isp_resource_node *res) { int rc = 0; - uint32_t id; + uint32_t id, val, format_measure_addr; struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; @@ -1797,6 +1861,24 @@ static int cam_ife_csid_deinit_rdi_path( return -EINVAL; } + format_measure_addr = + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr; + + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + val &= ~csid_reg->cmn_reg->format_measure_en_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + + /* Disable the HBI/VBI counter */ + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + format_measure_addr); + val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + format_measure_addr); + } + res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; return rc; } @@ -1899,6 +1981,55 @@ static int cam_ife_csid_disable_rdi_path( return rc; } +static int cam_ife_csid_get_hbi_vbi( + struct cam_ife_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + uint32_t hbi, vbi; + const struct cam_ife_csid_reg_offset *csid_reg; + const struct cam_ife_csid_rdi_reg_offset *rdi_reg; + struct cam_hw_soc_info *soc_info; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH || + res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d", + csid_hw->hw_intf->hw_idx, res->res_type, + res->res_id); + return -EINVAL; + } + + if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d", + csid_hw->hw_intf->hw_idx, + csid_hw->hw_info->hw_state); + return -EINVAL; + } + + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { + hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_format_measure1_addr); + vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_ipp_format_measure2_addr); + } else { + rdi_reg = csid_reg->rdi_reg[res->res_id]; + hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure1_addr); + vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure2_addr); + } + + CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u HBI: 0x%x", res->res_id, + hbi); + CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u VBI: 0x%x", res->res_id, + vbi); + + return 0; +} + + static int cam_ife_csid_get_time_stamp( struct cam_ife_csid_hw *csid_hw, void *cmd_args) { @@ -2552,6 +2683,7 @@ static int cam_ife_csid_process_cmd(void *hw_priv, int rc = 0; struct cam_ife_csid_hw *csid_hw; struct cam_hw_info *csid_hw_info; + struct cam_isp_resource_node *res = NULL; if (!hw_priv || !cmd_args) { CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); @@ -2564,6 +2696,11 @@ static int cam_ife_csid_process_cmd(void *hw_priv, switch (cmd_type) { case CAM_IFE_CSID_CMD_GET_TIME_STAMP: rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args); + if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) { + res = ((struct cam_csid_get_time_stamp_args *) + cmd_args)->node_res; + cam_ife_csid_get_hbi_vbi(csid_hw, res); + } break; case CAM_IFE_CSID_SET_CSID_DEBUG: rc = cam_ife_csid_set_csid_debug(csid_hw, cmd_args); diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 74aa199aa848..c547f4cb5286 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -76,6 +76,8 @@ #define CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE BIT(4) #define CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE BIT(5) #define CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6) +#define CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7) +#define CSID_DEBUG_DISABLE_EARLY_EOF BIT(8) /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_csid_path_halt_mode { @@ -135,6 +137,7 @@ struct cam_ife_csid_ipp_reg_offset { /* configuration */ uint32_t pix_store_en_shift_val; + uint32_t early_eof_en_shift_val; }; struct cam_ife_csid_rdi_reg_offset { @@ -285,6 +288,8 @@ struct cam_ife_csid_common_reg_offset { uint32_t crop_shift; uint32_t ipp_irq_mask_all; uint32_t rdi_irq_mask_all; + uint32_t measure_en_hbi_vbi_cnt_mask; + uint32_t format_measure_en_val; }; /** diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 28cfcc8bea74..54aa4c23b4d1 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -96,6 +96,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ, CAM_ISP_HW_CMD_GET_REG_DUMP, CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, + CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h index c7d3aa2fd487..d1284d9f23d2 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h @@ -50,6 +50,8 @@ static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = { .raw_crop_width_cfg = 0x00000CE4, .raw_crop_height_cfg = 0x00000CE8, .reg_update_cmd = 0x000004AC, + .vfe_diag_config = 0x00000C48, + .vfe_diag_sensor_status = 0x00000C4C, }; static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = { @@ -79,6 +81,7 @@ static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = { .eof_irq_mask = 0x00000002, .error_irq_mask0 = 0x0003FC00, .error_irq_mask1 = 0x0FFF7E80, + .enable_diagnostic_hw = 0x1, }; struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = { diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 0bb13741f2b1..54ec2823ae11 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -2438,7 +2438,7 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args, for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) { if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { CAM_ERR(CAM_ISP, - "reg_val_pair %d exceeds the array limit %lu", + "reg_val_pair %d exceeds the array limit %zu", j, MAX_REG_VAL_PAIR_SIZE); return -ENOMEM; } @@ -2711,7 +2711,7 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args, for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) { if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { CAM_ERR(CAM_ISP, - "reg_val_pair %d exceeds the array limit %lu", + "reg_val_pair %d exceeds the array limit %zu", j, MAX_REG_VAL_PAIR_SIZE); return -ENOMEM; } diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 1da2d2e9588e..fc257ecaa604 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -43,6 +43,7 @@ struct cam_vfe_mux_camif_data { uint32_t last_line; bool enable_sof_irq_debug; uint32_t irq_debug_cnt; + uint32_t camif_debug; }; static int cam_vfe_camif_validate_pix_pattern(uint32_t pattern) @@ -309,6 +310,15 @@ static int cam_vfe_camif_resource_start( rsrc_data->enable_sof_irq_debug = false; rsrc_data->irq_debug_cnt = 0; + if (rsrc_data->camif_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r_mb(rsrc_data->mem_base + + rsrc_data->camif_reg->vfe_diag_config); + val |= rsrc_data->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->camif_reg->vfe_diag_config); + } + CAM_DBG(CAM_ISP, "Start Camif IFE %d Done", camif_res->hw_intf->hw_idx); return 0; } @@ -400,6 +410,14 @@ static int cam_vfe_camif_resource_stop( if (camif_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) camif_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->camif_reg->vfe_diag_config); + if (val & camif_priv->reg_data->enable_diagnostic_hw) { + val &= ~camif_priv->reg_data->enable_diagnostic_hw; + cam_io_w_mb(val, camif_priv->mem_base + + camif_priv->camif_reg->vfe_diag_config); + } + return rc; } @@ -424,6 +442,7 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { int rc = -EINVAL; + struct cam_vfe_mux_camif_data *camif_priv = NULL; if (!rsrc_node || !cmd_args) { CAM_ERR(CAM_ISP, "Invalid input arguments"); @@ -441,6 +460,11 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG: rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args); break; + case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG: + camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + camif_priv->camif_debug = *((uint32_t *)cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); @@ -465,6 +489,7 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; uint32_t irq_status0; uint32_t irq_status1; + uint32_t val; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -527,6 +552,14 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, } else { ret = CAM_ISP_HW_ERROR_NONE; } + + if (camif_priv->camif_debug & + CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) { + val = cam_io_r(camif_priv->mem_base + + camif_priv->camif_reg->vfe_diag_sensor_status); + CAM_DBG(CAM_ISP, "VFE_DIAG_SENSOR_STATUS: 0x%x", + camif_priv->mem_base, val); + } break; default: break; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h index 4a73bd74c097..7a6958930caa 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,6 +16,11 @@ #include "cam_isp_hw.h" #include "cam_vfe_top.h" +/* + * Debug values for camif module + */ +#define CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS BIT(0) + struct cam_vfe_camif_ver2_reg { uint32_t camif_cmd; uint32_t camif_config; @@ -27,6 +32,8 @@ struct cam_vfe_camif_ver2_reg { uint32_t raw_crop_width_cfg; uint32_t raw_crop_height_cfg; uint32_t reg_update_cmd; + uint32_t vfe_diag_config; + uint32_t vfe_diag_sensor_status; }; struct cam_vfe_camif_reg_data { @@ -63,6 +70,8 @@ struct cam_vfe_camif_reg_data { uint32_t eof_irq_mask; uint32_t error_irq_mask0; uint32_t error_irq_mask1; + + uint32_t enable_diagnostic_hw; }; struct cam_vfe_camif_ver2_hw_info { diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c index 02334a4e8195..287d4a4162fc 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c @@ -20,9 +20,49 @@ #include "cam_jpeg_context.h" #include "cam_context_utils.h" #include "cam_debug_util.h" +#include "cam_packet_util.h" static const char jpeg_dev_name[] = "jpeg"; +static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova, + uint32_t buf_info) +{ + + struct cam_context *ctx = (struct cam_context *)data; + struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_temp = NULL; + struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL; + int rc = 0; + int closest_port; + bool b_mem_found = false; + + + if (!ctx) { + CAM_ERR(CAM_JPEG, "Invalid ctx"); + return -EINVAL; + } + + CAM_INFO(CAM_JPEG, "iommu fault for jpeg ctx %d state %d", + ctx->ctx_id, ctx->state); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + pf_dbg_entry = &(req->pf_data); + closest_port = -1; + CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id); + + rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet, + iova, buf_info, &b_mem_found); + if (rc) + CAM_ERR(CAM_JPEG, "Failed to dump pf info"); + + if (b_mem_found) + CAM_ERR(CAM_JPEG, "Found page fault in req %lld %d", + req->request_id, rc); + } + return rc; +} + static int __cam_jpeg_ctx_acquire_dev_in_available(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { @@ -116,6 +156,7 @@ static struct cam_ctx_ops }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, + .pagefault_ops = cam_jpeg_context_dump_active_request, }, }; diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c index 46cc08f7ea5f..14892224e412 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c @@ -22,11 +22,31 @@ #include "cam_jpeg_hw_mgr_intf.h" #include "cam_jpeg_dev.h" #include "cam_debug_util.h" +#include "cam_smmu_api.h" #define CAM_JPEG_DEV_NAME "cam-jpeg" static struct cam_jpeg_dev g_jpeg_dev; +static void cam_jpeg_dev_iommu_fault_handler( + struct iommu_domain *domain, struct device *dev, unsigned long iova, + int flags, void *token, uint32_t buf_info) +{ + int i = 0; + struct cam_node *node = NULL; + + if (!token) { + CAM_ERR(CAM_JPEG, "invalid token in page handler cb"); + return; + } + + node = (struct cam_node *)token; + + for (i = 0; i < node->ctx_size; i++) + cam_context_dump_pf_info(&(node->ctx_list[i]), iova, + buf_info); +} + static const struct of_device_id cam_jpeg_dt_match[] = { { .compatible = "qcom,cam-jpeg" @@ -34,23 +54,50 @@ static const struct of_device_id cam_jpeg_dt_match[] = { { } }; +static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + + mutex_lock(&g_jpeg_dev.jpeg_mutex); + g_jpeg_dev.open_cnt++; + mutex_unlock(&g_jpeg_dev.jpeg_mutex); + + return 0; +} + static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { + int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); + + mutex_lock(&g_jpeg_dev.jpeg_mutex); + if (g_jpeg_dev.open_cnt <= 0) { + CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); + rc = -EINVAL; + goto end; + } + + g_jpeg_dev.open_cnt--; + if (!node) { CAM_ERR(CAM_JPEG, "Node ptr is NULL"); - return -EINVAL; + rc = -EINVAL; + goto end; } - cam_node_shutdown(node); + if (g_jpeg_dev.open_cnt == 0) + cam_node_shutdown(node); - return 0; +end: + mutex_unlock(&g_jpeg_dev.jpeg_mutex); + return rc; } static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .close = cam_jpeg_subdev_close, + .open = cam_jpeg_subdev_open, }; static int cam_jpeg_dev_remove(struct platform_device *pdev) @@ -78,6 +125,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev) int i; struct cam_hw_mgr_intf hw_mgr_intf; struct cam_node *node; + int iommu_hdl = -1; g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, @@ -89,7 +137,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev) node = (struct cam_node *)g_jpeg_dev.sd.token; rc = cam_jpeg_hw_mgr_init(pdev->dev.of_node, - (uint64_t *)&hw_mgr_intf); + (uint64_t *)&hw_mgr_intf, &iommu_hdl); if (rc) { CAM_ERR(CAM_JPEG, "Can not initialize JPEG HWmanager %d", rc); goto unregister; @@ -114,6 +162,9 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev) goto ctx_init_fail; } + cam_smmu_set_client_page_fault_handler(iommu_hdl, + cam_jpeg_dev_iommu_fault_handler, node); + mutex_init(&g_jpeg_dev.jpeg_mutex); CAM_INFO(CAM_JPEG, "Camera JPEG probe complete"); diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h index deab2d5c0d02..0d15ced16e80 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h +++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -26,6 +26,7 @@ * @ctx: JPEG base context storage * @ctx_jpeg: JPEG private context storage * @jpeg_mutex: Jpeg dev mutex + * @open_cnt: Open device count */ struct cam_jpeg_dev { struct cam_subdev sd; @@ -33,5 +34,6 @@ struct cam_jpeg_dev { struct cam_context ctx[CAM_CTX_MAX]; struct cam_jpeg_context ctx_jpeg[CAM_CTX_MAX]; struct mutex jpeg_mutex; + int32_t open_cnt; }; #endif /* __CAM_JPEG_DEV_H__ */ diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index f0913b2df834..7f0199f6e119 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -34,6 +34,7 @@ #include "cam_mem_mgr.h" #include "cam_cdm_intf_api.h" #include "cam_debug_util.h" +#include "cam_common_util.h" #define CAM_JPEG_HW_ENTRIES_MAX 20 #define CAM_JPEG_CHBASE 0 @@ -55,8 +56,8 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) struct cam_jpeg_hw_ctx_data *ctx_data = NULL; struct cam_hw_done_event_data buf_data; struct cam_jpeg_set_irq_cb irq_cb; - uint32_t dev_type = 0; - uint64_t kaddr; + uintptr_t dev_type = 0; + uintptr_t kaddr; uint32_t *cmd_buf_kaddr; size_t cmd_buf_len; struct cam_jpeg_config_inout_param_info *p_params; @@ -113,7 +114,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) rc = hw_mgr->devices[dev_type][0]->hw_ops.deinit( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) - CAM_ERR(CAM_JPEG, "Failed to Deinit %d HW", dev_type); + CAM_ERR(CAM_JPEG, "Failed to Deinit %lu HW", dev_type); } hw_mgr->device_in_use[dev_type][0] = false; @@ -133,7 +134,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) CAM_ERR(CAM_JPEG, "task_data is NULL"); return -EINVAL; } - wq_task_data->data = (void *)(uint64_t)dev_type; + wq_task_data->data = (void *)dev_type; wq_task_data->request_id = 0; wq_task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE; task->process_cb = cam_jpeg_mgr_process_cmd; @@ -146,7 +147,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) rc = cam_mem_get_cpu_buf( p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].handle, - (uint64_t *)&kaddr, &cmd_buf_len); + &kaddr, &cmd_buf_len); if (rc) { CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d", hw_mgr->iommu_hdl, rc); @@ -172,7 +173,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) p_cfg_req->hw_cfg_args.out_map_entries[i].resource_handle; } buf_data.request_id = - (uint64_t)p_cfg_req->hw_cfg_args.priv; + PTR_TO_U64(p_cfg_req->hw_cfg_args.priv); ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list); @@ -262,7 +263,7 @@ static int cam_jpeg_insert_cdm_change_base( struct cam_cdm_bl_request *cdm_cmd; uint32_t size; uint32_t mem_cam_base; - uint64_t iova_addr; + uintptr_t iova_addr; uint32_t *ch_base_iova_addr; size_t ch_base_len; @@ -314,7 +315,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; - uint64_t request_id = 0; + uintptr_t request_id = 0; struct cam_jpeg_process_frame_work_data_t *task_data = (struct cam_jpeg_process_frame_work_data_t *)data; uint32_t dev_type; @@ -357,9 +358,9 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args; request_id = task_data->request_id; - if (request_id != (uint64_t)config_args->priv) { - CAM_DBG(CAM_JPEG, "not a recent req %lld %lld", - request_id, (uint64_t)config_args->priv); + if (request_id != (uintptr_t)config_args->priv) { + CAM_DBG(CAM_JPEG, "not a recent req %zd %zd", + request_id, (uintptr_t)config_args->priv); } if (!config_args->num_hw_update_entries) { @@ -489,7 +490,8 @@ end_callcb: buf_data.resource_handle[i] = hw_cfg_args->out_map_entries[i].resource_handle; } - buf_data.request_id = (uint64_t)p_cfg_req->hw_cfg_args.priv; + buf_data.request_id = + (uintptr_t)p_cfg_req->hw_cfg_args.priv; ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data); } @@ -509,7 +511,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_hw_config_args *config_args = config_hw_args; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; - uint64_t request_id = 0; + uintptr_t request_id = 0; struct cam_hw_update_entry *hw_update_entries; struct crm_workq_task *task; struct cam_jpeg_process_frame_work_data_t *task_data; @@ -549,11 +551,11 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) p_cfg_req->hw_cfg_args = *config_args; p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; - request_id = (uint64_t)config_args->priv; + request_id = (uintptr_t)config_args->priv; p_cfg_req->req_id = request_id; hw_update_entries = config_args->hw_update_entries; - CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %lld", - ctx_data, request_id, (uint64_t)config_args->priv); + CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd", + ctx_data, request_id, (uintptr_t)config_args->priv); task = cam_req_mgr_workq_get_task(g_jpeg_hw_mgr.work_process_frame); if (!task) { CAM_ERR(CAM_JPEG, "no empty task"); @@ -578,7 +580,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) list_add_tail(&p_cfg_req->list, &hw_mgr->hw_config_req_list); mutex_unlock(&hw_mgr->hw_mgr_mutex); - task_data->data = (void *)(int64_t)p_cfg_req->dev_type; + task_data->data = (void *)(uintptr_t)p_cfg_req->dev_type; task_data->request_id = request_id; task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE; task->process_cb = cam_jpeg_mgr_process_cmd; @@ -600,6 +602,74 @@ err_after_dq_free_list: return rc; } +static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, + int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info, + bool *mem_found) +{ + uint64_t iova_addr; + size_t src_buf_size; + int i; + int j; + int rc = 0; + int32_t mmu_hdl; + struct cam_buf_io_cfg *io_cfg = NULL; + + if (mem_found) + *mem_found = false; + + io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload + + packet->io_configs_offset / 4); + + for (i = 0; i < packet->num_io_configs; i++) { + for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { + if (!io_cfg[i].mem_handle[j]) + break; + + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == + GET_FD_FROM_HANDLE(pf_buf_info)) { + CAM_INFO(CAM_JPEG, + "Found PF at port: %d mem %x fd: %x", + io_cfg[i].resource_type, + io_cfg[i].mem_handle[j], + pf_buf_info); + if (mem_found) + *mem_found = true; + } + + CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d", + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].format, + io_cfg[i].direction); + + mmu_hdl = cam_mem_is_secure_buf( + io_cfg[i].mem_handle[j]) ? sec_mmu_hdl : + iommu_hdl; + rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j], + mmu_hdl, &iova_addr, &src_buf_size); + if (rc < 0) { + CAM_ERR(CAM_UTIL, "get src buf address fail"); + continue; + } + if (iova_addr >> 32) { + CAM_ERR(CAM_JPEG, "Invalid mapped address"); + rc = -EINVAL; + continue; + } + + CAM_INFO(CAM_JPEG, + "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x", + j, io_cfg[i].planes[j].width, + io_cfg[i].planes[j].height, + (int32_t)src_buf_size, + (unsigned int)iova_addr, + io_cfg[i].offsets[j], + io_cfg[i].mem_handle[j]); + + iova_addr += io_cfg[i].offsets[j]; + } + } +} static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, void *prepare_hw_update_args) @@ -675,6 +745,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, CAM_DBG(CAM_JPEG, "packet = %pK io_cfg_ptr = %pK size = %lu", (void *)packet, (void *)io_cfg_ptr, sizeof(struct cam_buf_io_cfg)); + prepare_args->pf_data->packet = packet; prepare_args->num_out_map_entries = 0; @@ -721,7 +792,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, (uint32_t)cmd_desc[i].offset; } prepare_args->num_hw_update_entries = j; - prepare_args->priv = (void *)packet->header.request_id; + prepare_args->priv = (void *)(uintptr_t)packet->header.request_id; CAM_DBG(CAM_JPEG, "will wait on input sync sync_id %d", prepare_args->in_map_entries[0].sync_id); @@ -827,7 +898,7 @@ static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv, struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_jpeg_hw_cfg_req *cfg_req = NULL; struct cam_jpeg_hw_cfg_req *req_temp = NULL; - int64_t request_id = 0; + long request_id = 0; uint32_t dev_type; struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; bool b_req_found = false; @@ -842,13 +913,13 @@ static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv, if (flush_args->num_req_pending) return 0; - request_id = (int64_t)flush_args->flush_req_active[0]; + request_id = (uintptr_t)flush_args->flush_req_active[0]; if (!flush_args->num_req_active) return 0; if (request_id <= 0) { - CAM_ERR(CAM_JPEG, "Invalid red id %lld", request_id); + CAM_ERR(CAM_JPEG, "Invalid red id %ld", request_id); return -EINVAL; } @@ -885,7 +956,7 @@ static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv, } if (!b_req_found) { - CAM_ERR(CAM_JPEG, "req not found %lld", request_id); + CAM_ERR(CAM_JPEG, "req not found %ld", request_id); return -EINVAL; } @@ -1189,7 +1260,7 @@ static int cam_jpeg_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) mutex_lock(&hw_mgr->hw_mgr_mutex); - if (copy_to_user((void __user *)query_cap->caps_handle, + if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), &g_jpeg_hw_mgr.jpeg_caps, sizeof(struct cam_jpeg_query_cap_cmd))) { CAM_ERR(CAM_JPEG, "copy_to_user failed"); @@ -1410,7 +1481,35 @@ num_dev_failed: return rc; } -int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl) +static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_JPEG, "Invalid arguments"); + return -EINVAL; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_DUMP_PF_INFO: + cam_jpeg_mgr_print_io_bufs( + hw_cmd_args->u.pf_args.pf_data.packet, + hw_mgr->iommu_hdl, + hw_mgr->iommu_sec_hdl, + hw_cmd_args->u.pf_args.buf_info, + hw_cmd_args->u.pf_args.mem_found); + break; + default: + CAM_ERR(CAM_JPEG, "Invalid cmd"); + } + + return rc; +} + +int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, + int *iommu_hdl) { int i, rc; uint32_t num_dev; @@ -1434,6 +1533,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl) hw_mgr_intf->hw_config = cam_jpeg_mgr_config_hw; hw_mgr_intf->hw_flush = cam_jpeg_mgr_hw_flush; hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop; + hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd; mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex); spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock); @@ -1495,6 +1595,9 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl) goto cdm_iommu_failed; } + if (iommu_hdl) + *iommu_hdl = g_jpeg_hw_mgr.iommu_hdl; + return rc; cdm_iommu_failed: diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 5e1016725095..82022ec24a77 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -38,7 +38,7 @@ struct cam_jpeg_process_frame_work_data_t { uint32_t type; void *data; - uint64_t request_id; + uintptr_t request_id; }; /** @@ -81,7 +81,7 @@ struct cam_jpeg_hw_cfg_req { struct list_head list; struct cam_hw_config_args hw_cfg_args; uint32_t dev_type; - int64_t req_id; + uintptr_t req_id; }; /** diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h index 5fb4e3ad3399..5705890cd109 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,8 +17,7 @@ #include <uapi/media/cam_defs.h> #include <linux/of.h> - int cam_jpeg_hw_mgr_init(struct device_node *of_node, - uint64_t *hw_mgr_hdl); + uint64_t *hw_mgr_hdl, int *iommu_hdl); #endif /* CAM_JPEG_HW_MGR_INTF_H */ diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c index 5dc87633991f..99a8fe1f8eca 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c +++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c @@ -22,7 +22,7 @@ static int __cam_lrme_ctx_acquire_dev_in_available(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { int rc = 0; - uint64_t ctxt_to_hw_map = (uint64_t)ctx->ctxt_to_hw_map; + uintptr_t ctxt_to_hw_map = (uintptr_t)ctx->ctxt_to_hw_map; struct cam_lrme_context *lrme_ctx = ctx->ctx_priv; CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id); diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h index 4c705c139405..dc1c8f4c10aa 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h +++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h @@ -19,7 +19,7 @@ #include "cam_req_mgr_interface.h" #include "cam_sync_api.h" -#define CAM_LRME_CTX_INDEX_SHIFT 32 +#define CAM_LRME_CTX_INDEX_SHIFT 16 /** * struct cam_lrme_context diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c index a4ee1040e4c8..6b1250aea714 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c +++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c @@ -81,6 +81,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, static int cam_lrme_dev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { + int rc = 0; struct cam_lrme_dev *lrme_dev = g_lrme_dev; struct cam_node *node = v4l2_get_subdevdata(sd); @@ -90,18 +91,25 @@ static int cam_lrme_dev_close(struct v4l2_subdev *sd, } mutex_lock(&lrme_dev->lock); - lrme_dev->open_cnt--; - mutex_unlock(&lrme_dev->lock); + if (lrme_dev->open_cnt <= 0) { + CAM_DBG(CAM_LRME, "LRME subdev is already closed"); + rc = -EINVAL; + goto end; + } + lrme_dev->open_cnt--; if (!node) { CAM_ERR(CAM_LRME, "Node is NULL"); - return -EINVAL; + rc = -EINVAL; + goto end; } if (lrme_dev->open_cnt == 0) cam_node_shutdown(node); - return 0; +end: + mutex_unlock(&lrme_dev->lock); + return rc; } static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c index 79d23cbf79b6..eecba3972875 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c @@ -188,12 +188,6 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl, io_addr[plane] += io_cfg[i].offsets[plane]; - if (io_addr[plane] >> 32) { - CAM_ERR(CAM_LRME, "Invalid io addr for %d %d", - plane, rc); - return -ENOMEM; - } - CAM_DBG(CAM_LRME, "IO Address[%d][%d] : %llu", io_cfg[i].direction, plane, io_addr[plane]); } @@ -571,12 +565,13 @@ static int cam_lrme_mgr_get_caps(void *hw_mgr_priv, void *hw_get_caps_args) if (sizeof(struct cam_lrme_query_cap_cmd) != args->size) { CAM_ERR(CAM_LRME, - "sizeof(struct cam_query_cap_cmd) = %lu, args->size = %d", + "sizeof(struct cam_query_cap_cmd) = %zu, args->size = %d", sizeof(struct cam_query_cap_cmd), args->size); return -EFAULT; } - if (copy_to_user((void __user *)args->caps_handle, &(hw_mgr->lrme_caps), + if (copy_to_user(u64_to_user_ptr(args->caps_handle), + &(hw_mgr->lrme_caps), sizeof(struct cam_lrme_query_cap_cmd))) { CAM_ERR(CAM_LRME, "copy to user failed"); return -EFAULT; @@ -591,7 +586,7 @@ static int cam_lrme_mgr_hw_acquire(void *hw_mgr_priv, void *hw_acquire_args) struct cam_hw_acquire_args *args = (struct cam_hw_acquire_args *)hw_acquire_args; struct cam_lrme_acquire_args lrme_acquire_args; - uint64_t device_index; + uintptr_t device_index; if (!hw_mgr_priv || !args) { CAM_ERR(CAM_LRME, @@ -612,7 +607,7 @@ static int cam_lrme_mgr_hw_acquire(void *hw_mgr_priv, void *hw_acquire_args) CAM_DBG(CAM_LRME, "Get device id %llu", device_index); if (device_index >= hw_mgr->device_count) { - CAM_ERR(CAM_LRME, "Get wrong device id %llu", device_index); + CAM_ERR(CAM_LRME, "Get wrong device id %lu", device_index); return -EINVAL; } @@ -667,7 +662,7 @@ static int cam_lrme_mgr_hw_flush(void *hw_mgr_priv, void *hw_flush_args) } args = (struct cam_hw_flush_args *)hw_flush_args; - device_index = ((uint64_t)args->ctxt_to_hw_map & 0xF); + device_index = ((uintptr_t)args->ctxt_to_hw_map & 0xF); if (device_index >= hw_mgr->device_count) { CAM_ERR(CAM_LRME, "Invalid device index %d", device_index); return -EPERM; diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h index 53d3c6342ea5..87419cf59e00 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h +++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -30,13 +30,13 @@ #define CAM_LRME_WORKQ_NUM_TASK 10 #define CAM_LRME_DECODE_DEVICE_INDEX(ctxt_to_hw_map) \ - ((uint64_t)ctxt_to_hw_map & 0xF) + ((uintptr_t)ctxt_to_hw_map & 0xF) #define CAM_LRME_DECODE_PRIORITY(ctxt_to_hw_map) \ - (((uint64_t)ctxt_to_hw_map & 0xF0) >> 4) + (((uintptr_t)ctxt_to_hw_map & 0xF0) >> 4) #define CAM_LRME_DECODE_CTX_INDEX(ctxt_to_hw_map) \ - ((uint64_t)ctxt_to_hw_map >> CAM_LRME_CTX_INDEX_SHIFT) + ((uint64_t)(uintptr_t)ctxt_to_hw_map >> CAM_LRME_CTX_INDEX_SHIFT) /** * enum cam_lrme_hw_mgr_ctx_priority diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c index 022e1a7fcf1e..a5f9ff17ad22 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c +++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c @@ -920,7 +920,7 @@ int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args, if (sizeof(struct cam_lrme_hw_submit_args) != arg_size) { CAM_ERR(CAM_LRME, - "size of args %lu, arg_size %d", + "size of args %zu, arg_size %d", sizeof(struct cam_lrme_hw_submit_args), arg_size); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c index 0e77a4c01fb4..f2c243e8c7a9 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c @@ -25,11 +25,11 @@ static struct cam_mem_table tbl; static int cam_mem_util_map_cpu_va(struct ion_handle *hdl, - uint64_t *vaddr, + uintptr_t *vaddr, size_t *len) { *vaddr = (uintptr_t)ion_map_kernel(tbl.client, hdl); - if (IS_ERR_OR_NULL((void *)*vaddr)) { + if (IS_ERR_OR_NULL((void *)(uintptr_t)(*vaddr))) { CAM_ERR(CAM_MEM, "kernel map fail"); return -ENOSPC; } @@ -183,12 +183,12 @@ handle_mismatch: } EXPORT_SYMBOL(cam_mem_get_io_buf); -int cam_mem_get_cpu_buf(int32_t buf_handle, uint64_t *vaddr_ptr, size_t *len) +int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len) { int rc = 0; int idx; struct ion_handle *ion_hdl = NULL; - uint64_t kvaddr = 0; + uintptr_t kvaddr = 0; size_t klen = 0; if (!buf_handle || !vaddr_ptr || !len) @@ -288,7 +288,7 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) rc = msm_ion_do_cache_op(tbl.client, tbl.bufq[idx].i_hdl, - (void *)tbl.bufq[idx].vaddr, + (void *)(uintptr_t)tbl.bufq[idx].vaddr, tbl.bufq[idx].len, ion_cache_ops); if (rc) @@ -926,7 +926,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp, int rc = 0; uint32_t heap_id; int32_t ion_flag = 0; - uint64_t kvaddr; + uintptr_t kvaddr; dma_addr_t iova = 0; size_t request_len = 0; uint32_t mem_handle; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h index 83727d20e685..92c366d723f9 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -56,7 +56,7 @@ struct cam_mem_buf_queue { size_t len; uint32_t flags; uint64_t vaddr; - uint64_t kmdvaddr; + uintptr_t kmdvaddr; bool active; bool is_imported; }; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h index 14b1a678e010..64258e8fb5ee 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h @@ -43,7 +43,7 @@ struct cam_mem_mgr_request_desc { * @region : Region to which allocated memory belongs */ struct cam_mem_mgr_memory_desc { - uint64_t kva; + uintptr_t kva; uint32_t iova; int32_t smmu_hdl; uint32_t mem_handle; @@ -92,7 +92,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, * * @return Status of operation. Negative in case of error. Zero otherwise. */ -int cam_mem_get_cpu_buf(int32_t buf_handle, uint64_t *vaddr_ptr, +int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len); static inline bool cam_mem_is_secure_buf(int32_t buf_handle) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index 460b3dfe59a2..4c4afc1841f8 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -1325,9 +1325,9 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( return NULL; } - if (session->num_links >= MAX_LINKS_PER_SESSION) { + if (session->num_links >= MAXIMUM_LINKS_PER_SESSION) { CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d", - session->num_links, MAX_LINKS_PER_SESSION); + session->num_links, MAXIMUM_LINKS_PER_SESSION); return NULL; } @@ -1362,7 +1362,7 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( mutex_lock(&session->lock); /* Loop through and find a free index */ - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (!session->links[i]) { CAM_DBG(CAM_CRM, "Free link index %d found, num_links=%d", @@ -1372,7 +1372,7 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( } } - if (i == MAX_LINKS_PER_SESSION) { + if (i == MAXIMUM_LINKS_PER_SESSION) { CAM_ERR(CAM_CRM, "Free link index not found"); goto error; } @@ -1433,7 +1433,7 @@ static void __cam_req_mgr_unreserve_link( return; } - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i] == link) session->links[i] = NULL; } @@ -1445,7 +1445,7 @@ static void __cam_req_mgr_unreserve_link( * of only having 2 links in a given session */ session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i]) session->links[i]->sync_link = NULL; } @@ -2387,7 +2387,7 @@ int cam_req_mgr_destroy_session( ses_info->session_hdl, cam_session->num_links); - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { link = cam_session->links[i]; if (!link) @@ -2628,7 +2628,8 @@ int cam_req_mgr_sync_config( } if ((sync_info->num_links < 0) || - (sync_info->num_links > MAX_LINKS_PER_SESSION)) { + (sync_info->num_links > + MAX_LINKS_PER_SESSION)) { CAM_ERR(CAM_CRM, "Invalid num links %d", sync_info->num_links); return -EINVAL; } @@ -2777,6 +2778,13 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) goto end; } + if (control->num_links > MAX_LINKS_PER_SESSION) { + CAM_ERR(CAM_CRM, "Invalid number of links %d", + control->num_links); + rc = -EINVAL; + goto end; + } + mutex_lock(&g_crm_core_dev->crm_lock); for (i = 0; i < control->num_links; i++) { link = (struct cam_req_mgr_core_link *) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h index 68ec09b1e89e..8b86931cd1e3 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h @@ -34,6 +34,8 @@ #define SYNC_LINK_SOF_CNT_MAX_LMT 1 +#define MAXIMUM_LINKS_PER_SESSION 4 + /** * enum crm_workq_task_type * @codes: to identify which type of task is present @@ -353,7 +355,7 @@ struct cam_req_mgr_core_link { struct cam_req_mgr_core_session { int32_t session_hdl; uint32_t num_links; - struct cam_req_mgr_core_link *links[MAX_LINKS_PER_SESSION]; + struct cam_req_mgr_core_link *links[MAXIMUM_LINKS_PER_SESSION]; struct list_head entry; struct mutex lock; int32_t force_err_recovery; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c index 0d21064afed7..cb60ef4abb5a 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c @@ -25,6 +25,7 @@ #include "cam_subdev.h" #include "cam_mem_mgr.h" #include "cam_debug_util.h" +#include "cam_common_util.h" #include <linux/slub_def.h> #define CAM_REQ_MGR_EVENT_MAX 30 @@ -153,6 +154,10 @@ static unsigned int cam_req_mgr_poll(struct file *f, static int cam_req_mgr_close(struct file *filep) { + struct v4l2_subdev *sd; + struct v4l2_fh *vfh = filep->private_data; + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); + mutex_lock(&g_dev.cam_lock); if (g_dev.open_cnt <= 0) { @@ -161,6 +166,17 @@ static int cam_req_mgr_close(struct file *filep) } cam_req_mgr_handle_core_shutdown(); + + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) + continue; + if (sd->internal_ops && sd->internal_ops->close) { + CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", + sd->name); + sd->internal_ops->close(sd, subdev_fh); + } + } + g_dev.open_cnt--; v4l2_fh_release(filep); @@ -220,14 +236,15 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&ses_info, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } rc = cam_req_mgr_create_session(&ses_info); if (!rc) - if (copy_to_user((void *)k_ioctl->handle, + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), &ses_info, k_ioctl->size)) rc = -EFAULT; } @@ -240,7 +257,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&ses_info, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } @@ -256,14 +273,15 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&link_info, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } rc = cam_req_mgr_link(&link_info); if (!rc) - if (copy_to_user((void *)k_ioctl->handle, + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), &link_info, k_ioctl->size)) rc = -EFAULT; } @@ -276,7 +294,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&unlink_info, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } @@ -292,7 +310,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&sched_req, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } @@ -308,7 +326,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&flush_info, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } @@ -324,7 +342,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&sync_info, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { return -EFAULT; } @@ -339,7 +357,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&cmd, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { rc = -EFAULT; break; @@ -347,7 +365,8 @@ static long cam_private_ioctl(struct file *file, void *fh, rc = cam_mem_mgr_alloc_and_map(&cmd); if (!rc) - if (copy_to_user((void *)k_ioctl->handle, + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), &cmd, k_ioctl->size)) { rc = -EFAULT; break; @@ -361,7 +380,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&cmd, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { rc = -EFAULT; break; @@ -369,7 +388,8 @@ static long cam_private_ioctl(struct file *file, void *fh, rc = cam_mem_mgr_map(&cmd); if (!rc) - if (copy_to_user((void *)k_ioctl->handle, + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), &cmd, k_ioctl->size)) { rc = -EFAULT; break; @@ -383,7 +403,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&cmd, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { rc = -EFAULT; break; @@ -399,7 +419,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&cmd, - (void *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { rc = -EFAULT; break; @@ -417,7 +437,7 @@ static long cam_private_ioctl(struct file *file, void *fh, return -EINVAL; if (copy_from_user(&cmd, - (void __user *)k_ioctl->handle, + u64_to_user_ptr(k_ioctl->handle), k_ioctl->size)) { rc = -EFAULT; break; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c index 3798ef8e6d5f..68b5569097df 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c @@ -228,7 +228,7 @@ int cam_req_mgr_workq_create(char *name, int32_t num_tasks, crm_workq->task.num_task, GFP_KERNEL); if (!crm_workq->task.pool) { - CAM_WARN(CAM_CRM, "Insufficient memory %lu", + CAM_WARN(CAM_CRM, "Insufficient memory %zu", sizeof(struct crm_workq_task) * crm_workq->task.num_task); kfree(crm_workq); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c index ed0a26b70eff..c14a74d7c862 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -16,6 +16,7 @@ #include "cam_sensor_util.h" #include "cam_trace.h" #include "cam_res_mgr_api.h" +#include "cam_common_util.h" int32_t cam_actuator_construct_default_power_setting( struct cam_sensor_power_ctrl_t *power_info) @@ -141,7 +142,7 @@ static int32_t cam_actuator_power_down(struct cam_actuator_ctrl_t *a_ctrl) CAM_ERR(CAM_ACTUATOR, "failed: power_info %pK", power_info); return -EINVAL; } - rc = msm_camera_power_down(power_info, soc_info); + rc = cam_sensor_util_power_down(power_info, soc_info); if (rc) { CAM_ERR(CAM_ACTUATOR, "power down the core is failed:%d", rc); return rc; @@ -301,7 +302,7 @@ int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply) trace_cam_apply_req("Actuator", apply->request_id); CAM_DBG(CAM_ACTUATOR, "Request Id: %lld", apply->request_id); - + mutex_lock(&(a_ctrl->actuator_mutex)); if ((apply->request_id == a_ctrl->i2c_data.per_frame[request_id].request_id) && (a_ctrl->i2c_data.per_frame[request_id].is_settings_valid) @@ -312,7 +313,7 @@ int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply) CAM_ERR(CAM_ACTUATOR, "Failed in applying the request: %lld\n", apply->request_id); - return rc; + goto release_mutex; } } del_req_id = (request_id + @@ -327,12 +328,14 @@ int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply) CAM_ERR(CAM_ACTUATOR, "Fail deleting the req: %d err: %d\n", del_req_id, rc); - return rc; + goto release_mutex; } } else { CAM_DBG(CAM_ACTUATOR, "No Valid Req to clean Up"); } +release_mutex: + mutex_unlock(&(a_ctrl->actuator_mutex)); return rc; } @@ -352,6 +355,8 @@ int32_t cam_actuator_establish_link( CAM_ERR(CAM_ACTUATOR, "Device data is NULL"); return -EINVAL; } + + mutex_lock(&(a_ctrl->actuator_mutex)); if (link->link_enable) { a_ctrl->bridge_intf.link_hdl = link->link_hdl; a_ctrl->bridge_intf.crm_cb = link->crm_cb; @@ -359,6 +364,7 @@ int32_t cam_actuator_establish_link( a_ctrl->bridge_intf.link_hdl = -1; a_ctrl->bridge_intf.crm_cb = NULL; } + mutex_unlock(&(a_ctrl->actuator_mutex)); return 0; } @@ -409,7 +415,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, size_t len_of_buff = 0; uint32_t *offset = NULL; uint32_t *cmd_buf = NULL; - uint64_t generic_ptr; + uintptr_t generic_ptr; struct common_header *cmm_hdr = NULL; struct cam_control *ioctl_ctrl = NULL; struct cam_packet *csl_packet = NULL; @@ -431,11 +437,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, power_info = &soc_private->power_info; ioctl_ctrl = (struct cam_control *)arg; - if (copy_from_user(&config, (void __user *) ioctl_ctrl->handle, + if (copy_from_user(&config, + u64_to_user_ptr(ioctl_ctrl->handle), sizeof(config))) return -EFAULT; rc = cam_mem_get_cpu_buf(config.packet_handle, - (uint64_t *)&generic_ptr, &len_of_buff); + &generic_ptr, &len_of_buff); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %d", rc); @@ -449,7 +456,8 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, return -EINVAL; } - csl_packet = (struct cam_packet *)(generic_ptr + config.offset); + csl_packet = + (struct cam_packet *)(generic_ptr + (uint32_t)config.offset); CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code); switch (csl_packet->header.op_code & 0xFFFFFF) { @@ -464,7 +472,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, if (!total_cmd_buf_in_bytes) continue; rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, - (uint64_t *)&generic_ptr, &len_of_buff); + &generic_ptr, &len_of_buff); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf"); return rc; @@ -704,7 +712,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, goto release_mutex; } rc = copy_from_user(&actuator_acq_dev, - (void __user *) cmd->handle, + u64_to_user_ptr(cmd->handle), sizeof(actuator_acq_dev)); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Failed Copying from user\n"); @@ -725,7 +733,8 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, CAM_DBG(CAM_ACTUATOR, "Device Handle: %d", actuator_acq_dev.device_handle); - if (copy_to_user((void __user *) cmd->handle, &actuator_acq_dev, + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &actuator_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_ACTUATOR, "Failed Copy to User"); rc = -EFAULT; @@ -778,7 +787,8 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, struct cam_actuator_query_cap actuator_cap = {0}; actuator_cap.slot_info = a_ctrl->soc_info.index; - if (copy_to_user((void __user *) cmd->handle, &actuator_cap, + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &actuator_cap, sizeof(struct cam_actuator_query_cap))) { CAM_ERR(CAM_ACTUATOR, "Failed Copy to User"); rc = -EFAULT; @@ -891,7 +901,9 @@ int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req) continue; if (i2c_set->is_settings_valid == 1) { + mutex_lock(&(a_ctrl->actuator_mutex)); rc = delete_request(i2c_set); + mutex_unlock(&(a_ctrl->actuator_mutex)); if (rc < 0) CAM_ERR(CAM_ACTUATOR, "delete request: %lld rc: %d", diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 513e717eff49..cb0bcc292037 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -14,6 +14,7 @@ #include "cam_csiphy_core.h" #include "cam_csiphy_dev.h" #include "cam_csiphy_soc.h" +#include "cam_common_util.h" #include <soc/qcom/scm.h> #include <cam_mem_mgr.h> @@ -21,19 +22,23 @@ #define SCM_SVC_CAMERASS 0x18 #define SECURE_SYSCALL_ID 0x6 +#define SECURE_SYSCALL_ID_2 0x7 + static int csiphy_dump; module_param(csiphy_dump, int, 0644); -static int cam_csiphy_notify_secure_mode(int phy, bool protect) +static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, + bool protect, int32_t offset) { struct scm_desc desc = {0}; + if (offset >= CSIPHY_MAX_INSTANCES) + return -EINVAL; desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL); desc.args[0] = protect; - desc.args[1] = phy; + desc.args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset]; - CAM_DBG(CAM_CSIPHY, "phy : %d, protect : %d", phy, protect); - if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID), + if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID_2), &desc)) { CAM_ERR(CAM_CSIPHY, "scm call to hypervisor failed"); return -EINVAL; @@ -42,6 +47,27 @@ static int cam_csiphy_notify_secure_mode(int phy, bool protect) return 0; } +static int32_t cam_csiphy_get_instance_offset( + struct csiphy_device *csiphy_dev, + int32_t dev_handle) +{ + int32_t i; + + if (csiphy_dev->acquire_count > + CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); + return -EINVAL; + } + + for (i = 0; i < csiphy_dev->acquire_count; i++) { + if (dev_handle == + csiphy_dev->bridge_intf.device_hdl[i]) + break; + } + + return i; +} + void cam_csiphy_query_cap(struct csiphy_device *csiphy_dev, struct cam_csiphy_query_cap *csiphy_cap) { @@ -75,11 +101,56 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev) } } +static int32_t cam_csiphy_update_secure_info( + struct csiphy_device *csiphy_dev, + struct cam_csiphy_info *cam_cmd_csiphy_info, + struct cam_config_dev_cmd *cfg_dev) +{ + uint32_t clock_lane, adj_lane_mask, temp; + int32_t offset; + + if (csiphy_dev->acquire_count >= + CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); + return -EINVAL; + } + + offset = cam_csiphy_get_instance_offset(csiphy_dev, + cfg_dev->dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + return -EINVAL; + } + + if (cam_cmd_csiphy_info->combo_mode) + clock_lane = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_combo_clk_lane; + else + clock_lane = + csiphy_dev->ctrl_reg->csiphy_reg.csiphy_clock_lane; + + adj_lane_mask = cam_cmd_csiphy_info->lane_mask & 0x1F & + ~clock_lane; + temp = adj_lane_mask & (clock_lane - 1); + adj_lane_mask = + ((adj_lane_mask & (~((clock_lane - 1)))) >> 1) | temp; + + csiphy_dev->csiphy_info.secure_mode[offset] = 1; + + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = + adj_lane_mask << (csiphy_dev->soc_info.index * + (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) + + (!cam_cmd_csiphy_info->csiphy_3phase) * + (CAM_CSIPHY_MAX_CPHY_LANES)); + + return 0; +} + int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, struct cam_config_dev_cmd *cfg_dev) { int32_t rc = 0; - uint64_t generic_ptr; + uintptr_t generic_ptr; struct cam_packet *csl_packet = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; uint32_t *cmd_buf = NULL; @@ -92,7 +163,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, } rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle, - (uint64_t *)&generic_ptr, &len); + &generic_ptr, &len); if (rc < 0) { CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc); return rc; @@ -105,14 +176,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, return -EINVAL; } - csl_packet = (struct cam_packet *)(generic_ptr + cfg_dev->offset); + csl_packet = (struct cam_packet *) + (generic_ptr + (uint32_t)cfg_dev->offset); cmd_desc = (struct cam_cmd_buf_desc *) ((uint32_t *)&csl_packet->payload + csl_packet->cmd_buf_offset / 4); rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, - (uint64_t *)&generic_ptr, &len); + &generic_ptr, &len); if (rc < 0) { CAM_ERR(CAM_CSIPHY, "Failed to get cmd buf Mem address : %d", rc); @@ -136,7 +208,10 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, csiphy_dev->csiphy_info.settle_time = cam_cmd_csiphy_info->settle_time; csiphy_dev->csiphy_info.data_rate = cam_cmd_csiphy_info->data_rate; - csiphy_dev->csiphy_info.secure_mode = cam_cmd_csiphy_info->secure_mode; + + if (cam_cmd_csiphy_info->secure_mode == 1) + cam_csiphy_update_secure_info(csiphy_dev, + cam_cmd_csiphy_info, cfg_dev); return rc; } @@ -347,6 +422,7 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) { struct cam_hw_soc_info *soc_info; + int32_t i = 0; if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) return; @@ -354,13 +430,17 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { soc_info = &csiphy_dev->soc_info; - if (csiphy_dev->csiphy_info.secure_mode) - cam_csiphy_notify_secure_mode( - csiphy_dev->soc_info.index, - CAM_SECURE_MODE_NON_SECURE); + for (i = 0; i < csiphy_dev->acquire_count; i++) { + if (csiphy_dev->csiphy_info.secure_mode[i]) + cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, i); - csiphy_dev->csiphy_info.secure_mode = - CAM_SECURE_MODE_NON_SECURE; + csiphy_dev->csiphy_info.secure_mode[i] = + CAM_SECURE_MODE_NON_SECURE; + + csiphy_dev->csiphy_cpas_cp_reg_mask[i] = 0; + } cam_csiphy_reset(csiphy_dev); cam_soc_util_disable_platform_resource(soc_info, true, true); @@ -398,7 +478,7 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev, int32_t rc = 0; if (copy_from_user(&cam_cmd_csiphy_info, - (void __user *)p_submit_cmd->packet_handle, + u64_to_user_ptr(p_submit_cmd->packet_handle), sizeof(struct cam_csiphy_info))) { CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n"); rc = -EFAULT; @@ -458,7 +538,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, struct cam_create_dev_hdl bridge_params; rc = copy_from_user(&csiphy_acq_dev, - (void __user *)cmd->handle, + u64_to_user_ptr(cmd->handle), sizeof(csiphy_acq_dev)); if (rc < 0) { CAM_ERR(CAM_CSIPHY, "Failed copying from User"); @@ -468,7 +548,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_acq_params.combo_mode = 0; if (copy_from_user(&csiphy_acq_params, - (void __user *)csiphy_acq_dev.info_handle, + u64_to_user_ptr(csiphy_acq_dev.info_handle), sizeof(csiphy_acq_params))) { CAM_ERR(CAM_CSIPHY, "Failed copying from User"); @@ -524,7 +604,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, bridge_intf->session_hdl[csiphy_acq_params.combo_mode] = csiphy_acq_dev.session_handle; - if (copy_to_user((void __user *)cmd->handle, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &csiphy_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_CSIPHY, "Failed copying from User"); @@ -542,7 +622,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, struct cam_csiphy_query_cap csiphy_cap = {0}; cam_csiphy_query_cap(csiphy_dev, &csiphy_cap); - if (copy_to_user((void __user *)cmd->handle, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &csiphy_cap, sizeof(struct cam_csiphy_query_cap))) { CAM_ERR(CAM_CSIPHY, "Failed copying from User"); rc = -EINVAL; @@ -551,6 +631,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, } break; case CAM_STOP_DEV: { + int32_t offset, rc = 0; + struct cam_start_stop_dev_cmd config; + + rc = copy_from_user(&config, u64_to_user_ptr(cmd->handle), + sizeof(config)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + goto release_mutex; + } + if ((csiphy_dev->csiphy_state != CAM_CSIPHY_START) || !csiphy_dev->start_dev_count) { CAM_ERR(CAM_CSIPHY, "Not in right state to stop : %d", @@ -558,20 +648,38 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } + offset = cam_csiphy_get_instance_offset(csiphy_dev, + config.dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + goto release_mutex; + } + if (--csiphy_dev->start_dev_count) { CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d", csiphy_dev->start_dev_count); + if (csiphy_dev->csiphy_info.secure_mode[offset]) + cam_csiphy_notify_secure_mode( + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, offset); + + csiphy_dev->csiphy_info.secure_mode[offset] = + CAM_SECURE_MODE_NON_SECURE; + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0; + goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode) + if (csiphy_dev->csiphy_info.secure_mode[offset]) cam_csiphy_notify_secure_mode( - csiphy_dev->soc_info.index, - CAM_SECURE_MODE_NON_SECURE); + csiphy_dev, + CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode = + csiphy_dev->csiphy_info.secure_mode[offset] = CAM_SECURE_MODE_NON_SECURE; + csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; + rc = cam_csiphy_disable_hw(csiphy_dev); if (rc < 0) CAM_ERR(CAM_CSIPHY, "Failed in csiphy release"); @@ -592,7 +700,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (copy_from_user(&release, (void __user *) cmd->handle, + if (copy_from_user(&release, + u64_to_user_ptr(cmd->handle), sizeof(release))) { rc = -EFAULT; goto release_mutex; @@ -630,7 +739,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, case CAM_CONFIG_DEV: { struct cam_config_dev_cmd config; - if (copy_from_user(&config, (void __user *)cmd->handle, + if (copy_from_user(&config, + u64_to_user_ptr(cmd->handle), sizeof(config))) { rc = -EFAULT; } else { @@ -645,12 +755,28 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, case CAM_START_DEV: { struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote; + struct cam_start_stop_dev_cmd config; + int32_t offset; + + rc = copy_from_user(&config, u64_to_user_ptr(cmd->handle), + sizeof(config)); + if (rc < 0) { + CAM_ERR(CAM_CSIPHY, "Failed copying from User"); + goto release_mutex; + } if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { csiphy_dev->start_dev_count++; goto release_mutex; } + offset = cam_csiphy_get_instance_offset(csiphy_dev, + config.dev_handle); + if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { + CAM_ERR(CAM_CSIPHY, "Invalid offset"); + goto release_mutex; + } + ahb_vote.type = CAM_VOTE_ABSOLUTE; ahb_vote.vote.level = CAM_SVS_VOTE; axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW; @@ -663,12 +789,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode) { + if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) { rc = cam_csiphy_notify_secure_mode( - csiphy_dev->soc_info.index, - CAM_SECURE_MODE_SECURE); + csiphy_dev, + CAM_SECURE_MODE_SECURE, offset); if (rc < 0) - csiphy_dev->csiphy_info.secure_mode = + csiphy_dev->csiphy_info.secure_mode[offset] = CAM_SECURE_MODE_NON_SECURE; } @@ -696,7 +822,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, struct cam_config_dev_cmd submit_cmd; if (copy_from_user(&submit_cmd, - (void __user *)cmd->handle, + u64_to_user_ptr(cmd->handle), sizeof(struct cam_config_dev_cmd))) { CAM_ERR(CAM_CSIPHY, "failed copy config ext\n"); rc = -EFAULT; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index 9c85af39bd8c..ac9625501035 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -58,6 +58,11 @@ #define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3 #define CSIPHY_DNP_PARAMS 4 +#define CSIPHY_MAX_INSTANCES 2 + +#define CAM_CSIPHY_MAX_DPHY_LANES 4 +#define CAM_CSIPHY_MAX_CPHY_LANES 3 + #define ENABLE_IRQ false #undef CDBG @@ -101,6 +106,12 @@ struct csiphy_reg_parms_t { uint32_t csiphy_reset_array_size; uint32_t csiphy_2ph_config_array_size; uint32_t csiphy_3ph_config_array_size; + uint32_t csiphy_cpas_cp_bits_per_phy; + uint32_t csiphy_cpas_cp_is_interleaved; + uint32_t csiphy_cpas_cp_2ph_offset; + uint32_t csiphy_cpas_cp_3ph_offset; + uint32_t csiphy_clock_lane; + uint32_t csiphy_combo_clk_lane; }; /** @@ -111,9 +122,9 @@ struct csiphy_reg_parms_t { * @crm_cb: Callback API pointers */ struct intf_params { - int32_t device_hdl[2]; - int32_t session_hdl[2]; - int32_t link_hdl[2]; + int32_t device_hdl[CSIPHY_MAX_INSTANCES]; + int32_t session_hdl[CSIPHY_MAX_INSTANCES]; + int32_t link_hdl[CSIPHY_MAX_INSTANCES]; struct cam_req_mgr_kmd_ops ops; struct cam_req_mgr_crm_cb *crm_cb; }; @@ -175,7 +186,7 @@ struct cam_csiphy_param { uint8_t csiphy_3phase; uint8_t combo_mode; uint8_t lane_cnt; - uint8_t secure_mode; + uint8_t secure_mode[CSIPHY_MAX_INSTANCES]; uint64_t settle_time; uint64_t settle_time_combo_sensor; uint64_t data_rate; @@ -231,6 +242,7 @@ struct csiphy_device { struct cam_hw_soc_info soc_info; uint32_t cpas_handle; uint32_t config_count; + uint64_t csiphy_cpas_cp_reg_mask[CSIPHY_MAX_INSTANCES]; }; #endif /* _CAM_CSIPHY_DEV_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h index 324509340054..82cff279fec4 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h @@ -23,6 +23,8 @@ struct csiphy_reg_parms_t csiphy_v1_0 = { .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 14, .csiphy_3ph_config_array_size = 19, + .csiphy_clock_lane = 0x1, + .csiphy_combo_clk_lane = 0x10, }; struct csiphy_reg_t csiphy_common_reg_1_0[] = { diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index c8730cab765c..277418a46d3d 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -17,6 +17,7 @@ #include "cam_eeprom_core.h" #include "cam_eeprom_soc.h" #include "cam_debug_util.h" +#include "cam_common_util.h" /** * cam_eeprom_read_memory() - read map data into buffer @@ -221,7 +222,7 @@ static int cam_eeprom_power_down(struct cam_eeprom_ctrl_t *e_ctrl) CAM_ERR(CAM_EEPROM, "failed: power_info %pK", power_info); return -EINVAL; } - rc = msm_camera_power_down(power_info, soc_info); + rc = cam_sensor_util_power_down(power_info, soc_info); if (rc) { CAM_ERR(CAM_EEPROM, "power down the core is failed:%d", rc); return rc; @@ -341,7 +342,8 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl, CAM_ERR(CAM_EEPROM, "Device is already acquired"); return -EFAULT; } - if (copy_from_user(&eeprom_acq_dev, (void __user *) cmd->handle, + if (copy_from_user(&eeprom_acq_dev, + u64_to_user_ptr(cmd->handle), sizeof(eeprom_acq_dev))) { CAM_ERR(CAM_EEPROM, "EEPROM:ACQUIRE_DEV: copy from user failed"); @@ -360,8 +362,8 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl, e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle; CAM_DBG(CAM_EEPROM, "Device Handle: %d", eeprom_acq_dev.device_handle); - if (copy_to_user((void __user *) cmd->handle, &eeprom_acq_dev, - sizeof(struct cam_sensor_acquire_dev))) { + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &eeprom_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_EEPROM, "EEPROM:ACQUIRE_DEV: copy to user failed"); return -EFAULT; } @@ -530,7 +532,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_cmd_buf_desc *cmd_desc = NULL; uint32_t *offset = NULL; uint32_t *cmd_buf = NULL; - uint64_t generic_pkt_addr; + uintptr_t generic_pkt_addr; size_t pkt_len = 0; uint32_t total_cmd_buf_in_bytes = 0; uint32_t processed_cmd_buf_in_bytes = 0; @@ -564,7 +566,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl, if (!total_cmd_buf_in_bytes) continue; rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, - (uint64_t *)&generic_pkt_addr, &pkt_len); + &generic_pkt_addr, &pkt_len); if (rc) { CAM_ERR(CAM_EEPROM, "Failed to get cpu buf"); return rc; @@ -641,7 +643,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_buf_io_cfg *io_cfg; uint32_t i = 0; int rc = 0; - uint64_t buf_addr; + uintptr_t buf_addr; size_t buf_size; uint8_t *read_buffer; @@ -656,7 +658,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl, CAM_DBG(CAM_EEPROM, "Direction: %d:", io_cfg->direction); if (io_cfg->direction == CAM_BUF_OUTPUT) { rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0], - (uint64_t *)&buf_addr, &buf_size); + &buf_addr, &buf_size); CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n", (void *)buf_addr, buf_size); @@ -699,7 +701,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) int32_t rc = 0; struct cam_control *ioctl_ctrl = NULL; struct cam_config_dev_cmd dev_config; - uint64_t generic_pkt_addr; + uintptr_t generic_pkt_addr; size_t pkt_len; struct cam_packet *csl_packet = NULL; struct cam_eeprom_soc_private *soc_private = @@ -708,11 +710,12 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) ioctl_ctrl = (struct cam_control *)arg; - if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle, + if (copy_from_user(&dev_config, + u64_to_user_ptr(ioctl_ctrl->handle), sizeof(dev_config))) return -EFAULT; rc = cam_mem_get_cpu_buf(dev_config.packet_handle, - (uint64_t *)&generic_pkt_addr, &pkt_len); + &generic_pkt_addr, &pkt_len); if (rc) { CAM_ERR(CAM_EEPROM, "error in converting command Handle Error: %d", rc); @@ -727,7 +730,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) } csl_packet = (struct cam_packet *) - (generic_pkt_addr + dev_config.offset); + (generic_pkt_addr + (uint32_t)dev_config.offset); switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_EEPROM_PACKET_OPCODE_INIT: if (e_ctrl->userspace_probe == false) { @@ -880,7 +883,7 @@ int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg) else eeprom_cap.eeprom_kernel_probe = false; - if (copy_to_user((void __user *) cmd->handle, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &eeprom_cap, sizeof(struct cam_eeprom_query_cap_t))) { CAM_ERR(CAM_EEPROM, "Failed Copy to User"); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile index c7889a5fc2f5..4d1cbdc3c5a2 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile @@ -1,10 +1,11 @@ -ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils -ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync +ccflags-y += -Idrivers/media/platform/msm/camera/cam_core +ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include +ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr +ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr -ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io -ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci -ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr -ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/ +ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils +ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu +ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash_dev.o cam_flash_core.o cam_flash_soc.o diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c index 2820d7e353f7..8c075f576ce6 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c @@ -15,8 +15,9 @@ #include "cam_sensor_cmn_header.h" #include "cam_flash_core.h" #include "cam_res_mgr_api.h" +#include "cam_common_util.h" -int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, +static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, bool regulator_enable) { int rc = 0; @@ -55,7 +56,7 @@ int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, return rc; } -static int cam_flash_flush_nrt(struct cam_flash_ctrl *fctrl) +static int cam_flash_pmic_flush_nrt(struct cam_flash_ctrl *fctrl) { int j = 0; struct cam_flash_frame_setting *nrt_settings; @@ -86,20 +87,187 @@ static int cam_flash_flush_nrt(struct cam_flash_ctrl *fctrl) return 0; } -int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) +static int cam_flash_i2c_flush_nrt(struct cam_flash_ctrl *fctrl) +{ + int rc = 0; + + if (fctrl->i2c_data.init_settings.is_settings_valid == true) { + rc = delete_request(&fctrl->i2c_data.init_settings); + if (rc) { + CAM_WARN(CAM_FLASH, + "Failed to delete Init i2c_setting: %d", + rc); + return rc; + } + } + if (fctrl->i2c_data.config_settings.is_settings_valid == true) { + rc = delete_request(&fctrl->i2c_data.config_settings); + if (rc) { + CAM_WARN(CAM_FLASH, + "Failed to delete NRT i2c_setting: %d", + rc); + return rc; + } + } + + return rc; +} + +static int cam_flash_construct_default_power_setting( + struct cam_sensor_power_ctrl_t *power_info) +{ + int rc = 0; + + power_info->power_setting_size = 1; + power_info->power_setting = + (struct cam_sensor_power_setting *) + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_setting) + return -ENOMEM; + + power_info->power_setting[0].seq_type = SENSOR_CUSTOM_REG1; + power_info->power_setting[0].seq_val = CAM_V_CUSTOM1; + power_info->power_setting[0].config_val = 0; + power_info->power_setting[0].delay = 2; + + power_info->power_down_setting_size = 1; + power_info->power_down_setting = + (struct cam_sensor_power_setting *) + kzalloc(sizeof(struct cam_sensor_power_setting), + GFP_KERNEL); + if (!power_info->power_down_setting) { + rc = -ENOMEM; + goto free_power_settings; + } + + power_info->power_down_setting[0].seq_type = SENSOR_CUSTOM_REG1; + power_info->power_down_setting[0].seq_val = CAM_V_CUSTOM1; + power_info->power_down_setting[0].config_val = 0; + + return rc; + +free_power_settings: + kfree(power_info->power_setting); + power_info->power_setting = NULL; + power_info->power_setting_size = 0; + return rc; +} + +int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable) +{ + int rc = 0; + + if (!(fctrl->switch_trigger)) { + CAM_ERR(CAM_FLASH, "Invalid argument"); + return -EINVAL; + } + + if (regulator_enable) { + rc = cam_flash_prepare(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + } + + if (!regulator_enable) { + if ((fctrl->flash_state == CAM_FLASH_STATE_START) && + (fctrl->is_regulator_enabled == true)) { + rc = cam_flash_prepare(fctrl, false); + if (rc) + CAM_ERR(CAM_FLASH, + "Disable Regulator Failed rc: %d", rc); + } + } + + return rc; +} + +int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable) +{ + int rc = 0; + struct cam_hw_soc_info *soc_info = &fctrl->soc_info; + struct cam_sensor_power_ctrl_t *power_info = + &fctrl->power_info; + + if (!power_info || !soc_info) { + CAM_ERR(CAM_FLASH, "Power Info is NULL"); + return -EINVAL; + } + power_info->dev = soc_info->dev; + + if (regulator_enable && (fctrl->is_regulator_enabled == false)) { + if ((power_info->power_setting == NULL) && + (power_info->power_down_setting == NULL)) { + CAM_INFO(CAM_FLASH, + "Using default power settings"); + rc = cam_flash_construct_default_power_setting( + power_info); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "Construct default pwr setting failed rc: %d", + rc); + return rc; + } + } + + rc = cam_sensor_core_power_up(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "power up the core is failed:%d", + rc); + goto free_pwr_settings; + } + + rc = camera_io_init(&(fctrl->io_master_info)); + if (rc) { + CAM_ERR(CAM_FLASH, "cci_init failed: rc: %d", rc); + cam_sensor_util_power_down(power_info, soc_info); + goto free_pwr_settings; + } + fctrl->is_regulator_enabled = true; + } else if ((!regulator_enable) && + (fctrl->is_regulator_enabled == true)) { + rc = cam_sensor_util_power_down(power_info, soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "power down the core is failed:%d", + rc); + return rc; + } + camera_io_release(&(fctrl->io_master_info)); + fctrl->is_regulator_enabled = false; + goto free_pwr_settings; + } + return rc; + +free_pwr_settings: + kfree(power_info->power_setting); + kfree(power_info->power_down_setting); + power_info->power_setting = NULL; + power_info->power_down_setting = NULL; + power_info->power_setting_size = 0; + power_info->power_down_setting_size = 0; + + return rc; +} + +int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id) { int rc = 0; int i = 0, j = 0; - struct cam_flash_ctrl *fctrl = NULL; int frame_offset = 0; - fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(flush->dev_hdl); if (!fctrl) { CAM_ERR(CAM_FLASH, "Device data is NULL"); return -EINVAL; } - if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + if (type == FLUSH_ALL) { + cam_flash_off(fctrl); /* flush all requests*/ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { fctrl->per_frame[i].cmn_attr.request_id = 0; @@ -109,19 +277,105 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) fctrl->per_frame[i].led_current_ma[j] = 0; } - rc = cam_flash_flush_nrt(fctrl); - if (rc) - CAM_ERR(CAM_FLASH, "NonRealTime flush error"); - } else if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + cam_flash_pmic_flush_nrt(fctrl); + } else if ((type == FLUSH_REQ) && (req_id != 0)) { /* flush request with req_id*/ - frame_offset = flush->req_id % MAX_PER_FRAME_ARRAY; + frame_offset = req_id % MAX_PER_FRAME_ARRAY; fctrl->per_frame[frame_offset].cmn_attr.request_id = 0; fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid = false; fctrl->per_frame[frame_offset].cmn_attr.count = 0; for (i = 0; i < CAM_FLASH_MAX_LED_TRIGGERS; i++) fctrl->per_frame[frame_offset].led_current_ma[i] = 0; + } else if ((type == FLUSH_REQ) && (req_id == 0)) { + /* Handels NonRealTime usecase */ + cam_flash_pmic_flush_nrt(fctrl); + } else { + CAM_ERR(CAM_FLASH, "Invalid arguments"); + return -EINVAL; + } + + return rc; +} + +int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id) +{ + int rc = 0; + int i = 0; + uint32_t cancel_req_id_found = 0; + struct i2c_settings_array *i2c_set = NULL; + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Device data is NULL"); + return -EINVAL; + } + if ((type == FLUSH_REQ) && (req_id == 0)) { + /* This setting will be called only when NonRealTime + * settings needs to clean. + */ + cam_flash_i2c_flush_nrt(fctrl); + } else { + /* All other usecase will be handle here */ + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(fctrl->i2c_data.per_frame[i]); + + if ((type == FLUSH_REQ) && + (i2c_set->request_id != req_id)) + continue; + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_FLASH, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + + if (type == FLUSH_REQ) { + cancel_req_id_found = 1; + break; + } + } + } + } + + if ((type == FLUSH_REQ) && (req_id != 0) && + (!cancel_req_id_found)) + CAM_DBG(CAM_FLASH, + "Flush request id:%lld not found in the pending list", + req_id); + + return rc; +} + +int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) +{ + int rc = 0; + struct cam_flash_ctrl *fctrl = NULL; + + fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(flush->dev_hdl); + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Device data is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + rc = fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + if (rc) { + CAM_ERR(CAM_FLASH, "FLUSH_TYPE_ALL failed rc: %d", rc); + goto end; + } + } else if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + rc = fctrl->func_tbl.flush_req(fctrl, + FLUSH_REQ, flush->req_id); + if (rc) { + CAM_ERR(CAM_FLASH, "FLUSH_REQ failed rc: %d", rc); + goto end; + } } +end: + mutex_unlock(&fctrl->flash_mutex); return rc; } @@ -254,26 +508,51 @@ static int cam_flash_high( return rc; } -static int delete_req(struct cam_flash_ctrl *fctrl, uint64_t req_id) +static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl, + uint64_t req_id) +{ + int i = 0, rc = 0; + uint64_t top = 0, del_req_id = 0; + + if (req_id != 0) { + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + if ((req_id >= + fctrl->i2c_data.per_frame[i].request_id) && + (top < + fctrl->i2c_data.per_frame[i].request_id) && + (fctrl->i2c_data.per_frame[i].is_settings_valid + == 1)) { + del_req_id = top; + top = fctrl->i2c_data.per_frame[i].request_id; + } + } + + if (top < req_id) { + if ((((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) >= BATCH_SIZE_MAX) || + (((top % MAX_PER_FRAME_ARRAY) - (req_id % + MAX_PER_FRAME_ARRAY)) <= -BATCH_SIZE_MAX)) + del_req_id = req_id; + } + + if (!del_req_id) + return rc; + + CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", + top, del_req_id); + } + fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id); + return 0; +} + +static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl, + uint64_t req_id) { int i = 0; struct cam_flash_frame_setting *flash_data = NULL; uint64_t top = 0, del_req_id = 0; - if (req_id == 0) { - flash_data = &fctrl->nrt_info; - if ((fctrl->nrt_info.cmn_attr.cmd_type == - CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) || - (fctrl->nrt_info.cmn_attr.cmd_type == - CAMERA_SENSOR_FLASH_CMD_TYPE_RER)) { - flash_data->cmn_attr.is_settings_valid = false; - for (i = 0; i < flash_data->cmn_attr.count; i++) - flash_data->led_current_ma[i] = 0; - } else { - fctrl->flash_init_setting.cmn_attr.is_settings_valid - = false; - } - } else { + if (req_id != 0) { for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { flash_data = &fctrl->per_frame[i]; if (req_id >= flash_data->cmn_attr.request_id && @@ -305,28 +584,100 @@ static int delete_req(struct cam_flash_ctrl *fctrl, uint64_t req_id) CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", top, del_req_id); + } - for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { - flash_data = &fctrl->per_frame[i]; - if ((del_req_id == - flash_data->cmn_attr.request_id) && - (flash_data->cmn_attr. - is_settings_valid == 1)) { - CAM_DBG(CAM_FLASH, "Deleting request[%d] %llu", - i, flash_data->cmn_attr.request_id); - flash_data->cmn_attr.request_id = 0; - flash_data->cmn_attr.is_settings_valid = false; - flash_data->opcode = 0; - for (i = 0; i < flash_data->cmn_attr.count; i++) - flash_data->led_current_ma[i] = 0; + fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id); + return 0; +} + +static int32_t cam_flash_slaveInfo_pkt_parser(struct cam_flash_ctrl *fctrl, + uint32_t *cmd_buf) +{ + int32_t rc = 0; + struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf; + + if (fctrl->io_master_info.master_type == CCI_MASTER) { + fctrl->io_master_info.cci_client->cci_i2c_master = + fctrl->cci_i2c_master; + fctrl->io_master_info.cci_client->i2c_freq_mode = + i2c_info->i2c_freq_mode; + fctrl->io_master_info.cci_client->sid = + i2c_info->slave_addr >> 1; + CAM_DBG(CAM_FLASH, "Slave addr: 0x%x Freq Mode: %d", + i2c_info->slave_addr, i2c_info->i2c_freq_mode); + } else if (fctrl->io_master_info.master_type == I2C_MASTER) { + fctrl->io_master_info.client->addr = i2c_info->slave_addr; + CAM_DBG(CAM_FLASH, "Slave addr: 0x%x", i2c_info->slave_addr); + } else { + CAM_ERR(CAM_FLASH, "Invalid Master type: %d", + fctrl->io_master_info.master_type); + rc = -EINVAL; + } + + return rc; +} + +int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, + uint64_t req_id) +{ + struct i2c_settings_list *i2c_list; + struct i2c_settings_array *i2c_set = NULL; + int frame_offset = 0, rc = 0; + + if (req_id == 0) { + /* NonRealTime Init settings*/ + if (fctrl->i2c_data.init_settings.is_settings_valid == true) { + list_for_each_entry(i2c_list, + &(fctrl->i2c_data.init_settings.list_head), + list) { + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply init settings: %d", + rc); + return rc; + } + } + } + /* NonRealTime (Widget/RER/INIT_FIRE settings) */ + if (fctrl->i2c_data.config_settings.is_settings_valid == true) { + list_for_each_entry(i2c_list, + &(fctrl->i2c_data.config_settings.list_head), + list) { + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply NRT settings: %d", rc); + return rc; + } + } + } + } else { + /* RealTime */ + frame_offset = req_id % MAX_PER_FRAME_ARRAY; + i2c_set = &fctrl->i2c_data.per_frame[frame_offset]; + if ((i2c_set->is_settings_valid == true) && + (i2c_set->request_id == req_id)) { + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + rc = cam_sensor_util_i2c_apply_setting( + &(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply settings: %d", rc); + return rc; + } } } } - return 0; + cam_flash_i2c_delete_req(fctrl, req_id); + return rc; } -int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, +int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id) { int rc = 0, i = 0; @@ -428,7 +779,6 @@ int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, } else if (fctrl->nrt_info.cmn_attr.cmd_type == CAMERA_SENSOR_FLASH_CMD_TYPE_RER) { flash_data = &fctrl->nrt_info; - if (fctrl->flash_state != CAM_FLASH_STATE_START) { rc = cam_flash_off(fctrl); if (rc) { @@ -461,8 +811,7 @@ int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, rc = cam_flash_off(fctrl); if (rc) { CAM_ERR(CAM_FLASH, - "Flash off failed: %d", - rc); + "Flash off failed: %d", rc); continue; } fctrl->flash_state = CAM_FLASH_STATE_START; @@ -524,15 +873,325 @@ int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, } nrt_del_req: - delete_req(fctrl, req_id); + cam_flash_pmic_delete_req(fctrl, req_id); apply_setting_err: return rc; } -int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) +int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) { int rc = 0, i = 0; - uint64_t generic_ptr; + uintptr_t generic_ptr; + uint32_t total_cmd_buf_in_bytes = 0; + uint32_t processed_cmd_buf_in_bytes = 0; + uint16_t cmd_length_in_bytes = 0; + uint32_t *cmd_buf = NULL; + uint32_t *offset = NULL; + uint32_t frm_offset = 0; + size_t len_of_buffer; + struct cam_flash_init *flash_init = NULL; + struct common_header *cmn_hdr = NULL; + struct cam_control *ioctl_ctrl = NULL; + struct cam_packet *csl_packet = NULL; + struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_config_dev_cmd config; + struct cam_req_mgr_add_request add_req; + struct i2c_data_settings *i2c_data = NULL; + struct i2c_settings_array *i2c_reg_settings = NULL; + struct cam_sensor_power_ctrl_t *power_info = NULL; + + if (!fctrl || !arg) { + CAM_ERR(CAM_FLASH, "fctrl/arg is NULL"); + return -EINVAL; + } + /* getting CSL Packet */ + ioctl_ctrl = (struct cam_control *)arg; + + if (copy_from_user((&config), u64_to_user_ptr(ioctl_ctrl->handle), + sizeof(config))) { + CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed"); + return -EFAULT; + } + + rc = cam_mem_get_cpu_buf(config.packet_handle, + &generic_ptr, &len_of_buffer); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc); + return rc; + } + + if (config.offset > len_of_buffer) { + CAM_ERR(CAM_FLASH, + "offset is out of bounds: offset: %lld len: %zu", + config.offset, len_of_buffer); + return -EINVAL; + } + + /* Add offset to the flash csl header */ + csl_packet = (struct cam_packet *)(uintptr_t)(generic_ptr + + config.offset); + switch (csl_packet->header.op_code & 0xFFFFFF) { + case CAM_FLASH_PACKET_OPCODE_INIT: { + /* INIT packet*/ + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + + /* Loop through multiple command buffers */ + for (i = 1; i < csl_packet->num_cmd_buf; i++) { + total_cmd_buf_in_bytes = cmd_desc[i].length; + processed_cmd_buf_in_bytes = 0; + if (!total_cmd_buf_in_bytes) + continue; + rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, + &generic_ptr, &len_of_buffer); + if (rc < 0) { + CAM_ERR(CAM_FLASH, "Failed to get cpu buf"); + return rc; + } + cmd_buf = (uint32_t *)generic_ptr; + if (!cmd_buf) { + CAM_ERR(CAM_FLASH, "invalid cmd buf"); + return -EINVAL; + } + cmd_buf += cmd_desc[i].offset / sizeof(uint32_t); + cmn_hdr = (struct common_header *)cmd_buf; + + /* Loop through cmd formats in one cmd buffer */ + CAM_DBG(CAM_FLASH, + "command Type: %d,Processed: %d,Total: %d", + cmn_hdr->cmd_type, processed_cmd_buf_in_bytes, + total_cmd_buf_in_bytes); + switch (cmn_hdr->cmd_type) { + case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO: + flash_init = (struct cam_flash_init *)cmd_buf; + fctrl->flash_type = flash_init->flash_type; + cmd_length_in_bytes = + sizeof(struct cam_flash_init); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + break; + case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: + rc = cam_flash_slaveInfo_pkt_parser( + fctrl, cmd_buf); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "Failed parsing slave info: rc: %d", + rc); + return rc; + } + cmd_length_in_bytes = + sizeof(struct cam_cmd_i2c_info); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + break; + case CAMERA_SENSOR_CMD_TYPE_PWR_UP: + case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN: + CAM_DBG(CAM_FLASH, + "Received power settings"); + cmd_length_in_bytes = + total_cmd_buf_in_bytes; + rc = cam_sensor_update_power_settings( + cmd_buf, + total_cmd_buf_in_bytes, + &fctrl->power_info); + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed update power settings"); + return rc; + } + break; + default: + CAM_DBG(CAM_FLASH, + "Received initSettings"); + i2c_data = &(fctrl->i2c_data); + i2c_reg_settings = + &fctrl->i2c_data.init_settings; + + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + rc = cam_sensor_i2c_command_parser( + &fctrl->io_master_info, + i2c_reg_settings, + &cmd_desc[i], 1); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "pkt parsing failed: %d", rc); + return rc; + } + cmd_length_in_bytes = + cmd_desc[i].length; + processed_cmd_buf_in_bytes += + cmd_length_in_bytes; + cmd_buf += cmd_length_in_bytes/ + sizeof(uint32_t); + + break; + } + } + power_info = &fctrl->power_info; + if (!power_info) { + CAM_ERR(CAM_FLASH, "Power_info is NULL"); + return -EINVAL; + } + + /* Parse and fill vreg params for power up settings */ + rc = msm_camera_fill_vreg_params(&fctrl->soc_info, + power_info->power_setting, + power_info->power_setting_size); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed to fill vreg params for power up rc:%d", + rc); + return rc; + } + + /* Parse and fill vreg params for power down settings*/ + rc = msm_camera_fill_vreg_params( + &fctrl->soc_info, + power_info->power_down_setting, + power_info->power_down_setting_size); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed to fill vreg params power down rc:%d", + rc); + return rc; + } + + rc = fctrl->func_tbl.power_ops(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + + rc = fctrl->func_tbl.apply_setting(fctrl, 0); + if (rc) { + CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc); + return rc; + } + + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; + break; + } + case CAM_FLASH_PACKET_OPCODE_SET_OPS: { + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; + /* add support for handling i2c_data*/ + i2c_reg_settings = + &fctrl->i2c_data.per_frame[frm_offset]; + if (i2c_reg_settings->is_settings_valid == true) { + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = false; + goto update_req_mgr; + } + i2c_reg_settings->is_settings_valid = true; + i2c_reg_settings->request_id = + csl_packet->header.request_id; + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser( + &fctrl->io_master_info, + i2c_reg_settings, cmd_desc, 1); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in parsing i2c packets"); + return rc; + } + break; + } + case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: { + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + + /* add support for handling i2c_data*/ + i2c_reg_settings = &fctrl->i2c_data.config_settings; + if (i2c_reg_settings->is_settings_valid == true) { + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = false; + + rc = delete_request(i2c_reg_settings); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in Deleting the err: %d", rc); + return rc; + } + } + i2c_reg_settings->is_settings_valid = true; + i2c_reg_settings->request_id = + csl_packet->header.request_id; + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser( + &fctrl->io_master_info, + i2c_reg_settings, cmd_desc, 1); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in parsing i2c NRT packets"); + return rc; + } + rc = fctrl->func_tbl.apply_setting(fctrl, 0); + if (rc) + CAM_ERR(CAM_FLASH, + "Apply setting failed: %d", rc); + return rc; + } + case CAM_PKT_NOP_OPCODE: { + if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || + (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { + CAM_WARN(CAM_FLASH, + "Rxed NOP packets without linking"); + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; + fctrl->i2c_data.per_frame[frm_offset].is_settings_valid + = false; + return 0; + } + + CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u", + csl_packet->header.request_id); + goto update_req_mgr; + } + default: + CAM_ERR(CAM_FLASH, "Wrong Opcode : %d", + (csl_packet->header.op_code & 0xFFFFFF)); + return -EINVAL; + } +update_req_mgr: + if (((csl_packet->header.op_code & 0xFFFFF) == + CAM_PKT_NOP_OPCODE) || + ((csl_packet->header.op_code & 0xFFFFF) == + CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + add_req.link_hdl = fctrl->bridge_intf.link_hdl; + add_req.req_id = csl_packet->header.request_id; + add_req.dev_hdl = fctrl->bridge_intf.device_hdl; + + if ((csl_packet->header.op_code & 0xFFFFF) == + CAM_FLASH_PACKET_OPCODE_SET_OPS) + add_req.skip_before_applying = 1; + else + add_req.skip_before_applying = 0; + + if (fctrl->bridge_intf.crm_cb && + fctrl->bridge_intf.crm_cb->add_req) + fctrl->bridge_intf.crm_cb->add_req(&add_req); + CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); + } + return rc; +} + +int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) +{ + int rc = 0, i = 0; + uintptr_t generic_ptr; uint32_t *cmd_buf = NULL; uint32_t *offset = NULL; uint32_t frm_offset = 0; @@ -556,7 +1215,8 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) /* getting CSL Packet */ ioctl_ctrl = (struct cam_control *)arg; - if (copy_from_user((&config), (void __user *) ioctl_ctrl->handle, + if (copy_from_user((&config), + u64_to_user_ptr(ioctl_ctrl->handle), sizeof(config))) { CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed"); rc = -EFAULT; @@ -564,7 +1224,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) } rc = cam_mem_get_cpu_buf(config.packet_handle, - (uint64_t *)&generic_ptr, &len_of_buffer); + &generic_ptr, &len_of_buffer); if (rc) { CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc); return rc; @@ -578,57 +1238,69 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) } /* Add offset to the flash csl header */ - csl_packet = (struct cam_packet *)(generic_ptr + config.offset); + csl_packet = + (struct cam_packet *)(generic_ptr + (uint32_t)config.offset); switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_FLASH_PACKET_OPCODE_INIT: { /* INIT packet*/ offset = (uint32_t *)((uint8_t *)&csl_packet->payload + csl_packet->cmd_buf_offset); - fctrl->flash_init_setting.cmn_attr.request_id = 0; - fctrl->flash_init_setting.cmn_attr.is_settings_valid = true; cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, - (uint64_t *)&generic_ptr, &len_of_buffer); + &generic_ptr, &len_of_buffer); cmd_buf = (uint32_t *)((uint8_t *)generic_ptr + cmd_desc->offset); cam_flash_info = (struct cam_flash_init *)cmd_buf; switch (cam_flash_info->cmd_type) { - case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO: + case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO: { + CAM_DBG(CAM_FLASH, "INIT_INFO CMD CALLED"); + fctrl->flash_init_setting.cmn_attr.request_id = 0; + fctrl->flash_init_setting.cmn_attr.is_settings_valid = + true; fctrl->flash_type = cam_flash_info->flash_type; fctrl->is_regulator_enabled = false; fctrl->nrt_info.cmn_attr.cmd_type = CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO; + + rc = fctrl->func_tbl.power_ops(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; break; - case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE: - CAM_DBG(CAM_FLASH, "INIT Fire Operation"); - flash_operation_info = - (struct cam_flash_set_on_off *) cmd_buf; - fctrl->nrt_info.cmn_attr.count = - flash_operation_info->count; - fctrl->nrt_info.cmn_attr.request_id = 0; - fctrl->nrt_info.opcode = - flash_operation_info->opcode; - fctrl->nrt_info.cmn_attr.cmd_type = - CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE; - for (i = 0; - i < flash_operation_info->count; i++) - fctrl->nrt_info.led_current_ma[i] = - flash_operation_info->led_current_ma[i]; + } + case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE: { + CAM_DBG(CAM_FLASH, "INIT_FIRE Operation"); - mutex_lock(&fctrl->flash_wq_mutex); - rc = cam_flash_apply_setting(fctrl, 0); - if (rc) - CAM_ERR(CAM_FLASH, - "Apply setting failed: %d", - rc); - mutex_unlock(&fctrl->flash_wq_mutex); - fctrl->flash_state = - CAM_FLASH_STATE_CONFIG; + flash_operation_info = + (struct cam_flash_set_on_off *) cmd_buf; + fctrl->nrt_info.cmn_attr.count = + flash_operation_info->count; + fctrl->nrt_info.cmn_attr.request_id = 0; + fctrl->nrt_info.opcode = + flash_operation_info->opcode; + fctrl->nrt_info.cmn_attr.cmd_type = + CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE; + for (i = 0; + i < flash_operation_info->count; i++) + fctrl->nrt_info.led_current_ma[i] = + flash_operation_info->led_current_ma[i]; + + rc = fctrl->func_tbl.apply_setting(fctrl, 0); + if (rc) + CAM_ERR(CAM_FLASH, + "Apply setting failed: %d", + rc); + + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; break; + } default: CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d", cam_flash_info->cmd_type); @@ -654,7 +1326,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) flash_data->cmn_attr.is_settings_valid = true; cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, - (uint64_t *)&generic_ptr, &len_of_buffer); + &generic_ptr, &len_of_buffer); cmd_buf = (uint32_t *)((uint8_t *)generic_ptr + cmd_desc->offset); @@ -666,7 +1338,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) switch (cmn_hdr->cmd_type) { case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: { CAM_DBG(CAM_FLASH, - "CAMERA_FLASH_CMD_TYPE_OPS case called"); + "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called"); if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { @@ -690,8 +1362,8 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) for (i = 0; i < flash_operation_info->count; i++) flash_data->led_current_ma[i] = flash_operation_info->led_current_ma[i]; - } - break; + } + break; default: CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d", cmn_hdr->cmd_type); @@ -705,7 +1377,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) fctrl->nrt_info.cmn_attr.is_settings_valid = true; cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle, - (uint64_t *)&generic_ptr, &len_of_buffer); + &generic_ptr, &len_of_buffer); cmd_buf = (uint32_t *)((uint8_t *)generic_ptr + cmd_desc->offset); cmn_hdr = (struct common_header *)cmd_buf; @@ -727,12 +1399,10 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) fctrl->nrt_info.led_current_ma[i] = flash_operation_info->led_current_ma[i]; - mutex_lock(&fctrl->flash_wq_mutex); - rc = cam_flash_apply_setting(fctrl, 0); + rc = fctrl->func_tbl.apply_setting(fctrl, 0); if (rc) CAM_ERR(CAM_FLASH, "Apply setting failed: %d", rc); - mutex_unlock(&fctrl->flash_wq_mutex); return rc; } case CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR: { @@ -773,12 +1443,10 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) flash_rer_info->led_current_ma[i]; - mutex_lock(&fctrl->flash_wq_mutex); - rc = cam_flash_apply_setting(fctrl, 0); + rc = fctrl->func_tbl.apply_setting(fctrl, 0); if (rc) CAM_ERR(CAM_FLASH, "apply_setting failed: %d", rc); - mutex_unlock(&fctrl->flash_wq_mutex); return rc; } default: @@ -786,7 +1454,6 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) cmn_hdr->cmd_type); return -EINVAL; } - break; } case CAM_PKT_NOP_OPCODE: { @@ -804,7 +1471,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid = false; fctrl->per_frame[frm_offset].cmn_attr.request_id = 0; fctrl->per_frame[frm_offset].opcode = CAM_PKT_NOP_OPCODE; - CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u", + CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %llu", csl_packet->header.request_id); goto update_req_mgr; } @@ -858,7 +1525,7 @@ int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link) CAM_ERR(CAM_FLASH, " Device data is NULL"); return -EINVAL; } - + mutex_lock(&fctrl->flash_mutex); if (link->link_enable) { fctrl->bridge_intf.link_hdl = link->link_hdl; fctrl->bridge_intf.crm_cb = link->crm_cb; @@ -866,43 +1533,11 @@ int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link) fctrl->bridge_intf.link_hdl = -1; fctrl->bridge_intf.crm_cb = NULL; } + mutex_unlock(&fctrl->flash_mutex); return 0; } - -int cam_flash_stop_dev(struct cam_flash_ctrl *fctrl) -{ - int rc = 0, i, j; - - cam_flash_off(fctrl); - - for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { - fctrl->per_frame[i].cmn_attr.request_id = 0; - fctrl->per_frame[i].cmn_attr.is_settings_valid = false; - fctrl->per_frame[i].cmn_attr.count = 0; - for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++) - fctrl->per_frame[i].led_current_ma[j] = 0; - } - - rc = cam_flash_flush_nrt(fctrl); - if (rc) { - CAM_ERR(CAM_FLASH, - "NonRealTime Dev flush failed rc: %d", rc); - return rc; - } - - if ((fctrl->flash_state == CAM_FLASH_STATE_START) && - (fctrl->is_regulator_enabled == true)) { - rc = cam_flash_prepare(fctrl, false); - if (rc) - CAM_ERR(CAM_FLASH, "Disable Regulator Failed rc: %d", - rc); - } - - return rc; -} - int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) { int rc = 0; @@ -930,9 +1565,11 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || (fctrl->flash_state == CAM_FLASH_STATE_START)) { - rc = cam_flash_stop_dev(fctrl); + fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + rc = fctrl->func_tbl.power_ops(fctrl, false); if (rc) - CAM_ERR(CAM_FLASH, "Stop Failed rc: %d", rc); + CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", + rc); } rc = cam_flash_release_dev(fctrl); @@ -956,12 +1593,12 @@ int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply) return -EINVAL; } - mutex_lock(&fctrl->flash_wq_mutex); - rc = cam_flash_apply_setting(fctrl, apply->request_id); + mutex_lock(&fctrl->flash_mutex); + rc = fctrl->func_tbl.apply_setting(fctrl, apply->request_id); if (rc) CAM_ERR(CAM_FLASH, "apply_setting failed with rc=%d", rc); - mutex_unlock(&fctrl->flash_wq_mutex); + mutex_unlock(&fctrl->flash_mutex); return rc; } diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h index f73409a0a935..1bd3b31c1668 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,20 +16,12 @@ #include <linux/leds-qpnp-flash.h> #include <media/cam_sensor.h> #include "cam_flash_dev.h" -#include "cam_sync_api.h" -#include "cam_mem_mgr_api.h" -int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg); int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info); int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link); -int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id); int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply); int cam_flash_process_evt(struct cam_req_mgr_link_evt_data *event_data); int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush); -int cam_flash_off(struct cam_flash_ctrl *fctrl); -int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, - bool regulator_enable); -void cam_flash_shutdown(struct cam_flash_ctrl *flash_ctrl); -int cam_flash_stop_dev(struct cam_flash_ctrl *flash_ctrl); -int cam_flash_release_dev(struct cam_flash_ctrl *fctrl); + + #endif /*_CAM_FLASH_CORE_H_*/ diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c index f8be3de85708..4a6307da01b0 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -15,6 +15,7 @@ #include "cam_flash_dev.h" #include "cam_flash_soc.h" #include "cam_flash_core.h" +#include "cam_common_util.h" static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, void *arg, struct cam_flash_private_soc *soc_private) @@ -57,7 +58,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, goto release_mutex; } - rc = copy_from_user(&flash_acq_dev, (void __user *)cmd->handle, + rc = copy_from_user(&flash_acq_dev, + u64_to_user_ptr(cmd->handle), sizeof(flash_acq_dev)); if (rc) { CAM_ERR(CAM_FLASH, "Failed Copying from User"); @@ -77,7 +79,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, fctrl->bridge_intf.session_hdl = flash_acq_dev.session_handle; - rc = copy_to_user((void __user *) cmd->handle, &flash_acq_dev, + rc = copy_to_user(u64_to_user_ptr(cmd->handle), + &flash_acq_dev, sizeof(struct cam_sensor_acquire_dev)); if (rc) { CAM_ERR(CAM_FLASH, "Failed Copy to User with rc = %d", @@ -93,7 +96,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || (fctrl->flash_state == CAM_FLASH_STATE_START)) { CAM_WARN(CAM_FLASH, - "Cannot apply Release dev: Prev state:%d", + "Wrong state for Release dev: Prev state:%d", fctrl->flash_state); } @@ -106,11 +109,18 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, rc = -EINVAL; goto release_mutex; } - rc = cam_flash_release_dev(fctrl); - if (rc) - CAM_ERR(CAM_FLASH, - "Failed in destroying the device Handle rc= %d", - rc); + + if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || + (fctrl->flash_state == CAM_FLASH_STATE_START)) + fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + + if (cam_flash_release_dev(fctrl)) + CAM_WARN(CAM_FLASH, + "Failed in destroying the device Handle"); + + if (fctrl->func_tbl.power_ops(fctrl, false)) + CAM_WARN(CAM_FLASH, "Power Down Failed"); + fctrl->flash_state = CAM_FLASH_STATE_INIT; break; } @@ -130,8 +140,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, flash_cap.max_current_torch[i] = soc_private->torch_max_current[i]; - if (copy_to_user((void __user *) cmd->handle, &flash_cap, - sizeof(struct cam_flash_query_cap_info))) { + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &flash_cap, sizeof(struct cam_flash_query_cap_info))) { CAM_ERR(CAM_FLASH, "Failed Copy to User"); rc = -EFAULT; goto release_mutex; @@ -149,15 +159,6 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, goto release_mutex; } - if (fctrl->is_regulator_enabled == false) { - rc = cam_flash_prepare(fctrl, true); - if (rc) { - CAM_ERR(CAM_FLASH, - "Enable Regulator Failed rc = %d", rc); - goto release_mutex; - } - } - fctrl->flash_state = CAM_FLASH_STATE_START; break; } @@ -171,18 +172,13 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, goto release_mutex; } - rc = cam_flash_stop_dev(fctrl); - if (rc) { - CAM_ERR(CAM_FLASH, "Stop Dev Failed rc = %d", - rc); - goto release_mutex; - } + fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE; break; } case CAM_CONFIG_DEV: { CAM_DBG(CAM_FLASH, "CAM_CONFIG_DEV"); - rc = cam_flash_parser(fctrl, arg); + rc = fctrl->func_tbl.parser(fctrl, arg); if (rc) { CAM_ERR(CAM_FLASH, "Failed Flash Config: rc=%d\n", rc); goto release_mutex; @@ -199,6 +195,35 @@ release_mutex: return rc; } +static int32_t cam_flash_init_default_params(struct cam_flash_ctrl *fctrl) +{ + /* Validate input parameters */ + if (!fctrl) { + CAM_ERR(CAM_FLASH, "failed: invalid params fctrl %pK", + fctrl); + return -EINVAL; + } + + CAM_DBG(CAM_FLASH, + "master_type: %d", fctrl->io_master_info.master_type); + /* Initialize cci_client */ + if (fctrl->io_master_info.master_type == CCI_MASTER) { + fctrl->io_master_info.cci_client = kzalloc(sizeof( + struct cam_sensor_cci_client), GFP_KERNEL); + if (!(fctrl->io_master_info.cci_client)) + return -ENOMEM; + } else if (fctrl->io_master_info.master_type == I2C_MASTER) { + if (!(fctrl->io_master_info.client)) + return -EINVAL; + } else { + CAM_ERR(CAM_FLASH, + "Invalid master / Master type Not supported"); + return -EINVAL; + } + + return 0; +} + static const struct of_device_id cam_flash_dt_match[] = { {.compatible = "qcom,camera-flash", .data = NULL}, {} @@ -289,20 +314,36 @@ static int cam_flash_platform_remove(struct platform_device *pdev) return 0; } +static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) +{ + int32_t rc = 0; + struct cam_flash_ctrl *fctrl = i2c_get_clientdata(client); + /* Handle I2C Devices */ + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash device is NULL"); + return -EINVAL; + } + /*Free Allocated Mem */ + kfree(fctrl->i2c_data.per_frame); + fctrl->i2c_data.per_frame = NULL; + kfree(fctrl); + return rc; +} + static int cam_flash_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { - struct cam_flash_ctrl *flash_ctrl = + struct cam_flash_ctrl *fctrl = v4l2_get_subdevdata(sd); - if (!flash_ctrl) { + if (!fctrl) { CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); return -EINVAL; } - mutex_lock(&flash_ctrl->flash_mutex); - cam_flash_shutdown(flash_ctrl); - mutex_unlock(&flash_ctrl->flash_mutex); + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); return 0; } @@ -322,10 +363,30 @@ static const struct v4l2_subdev_internal_ops cam_flash_internal_ops = { .close = cam_flash_subdev_close, }; +static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) +{ + int rc = 0; + + fctrl->v4l2_dev_str.internal_ops = + &cam_flash_internal_ops; + fctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops; + fctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME; + fctrl->v4l2_dev_str.sd_flags = + V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; + fctrl->v4l2_dev_str.token = fctrl; + + rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); + if (rc) + CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc); + + return rc; +} + static int32_t cam_flash_platform_probe(struct platform_device *pdev) { - int32_t rc = 0; - struct cam_flash_ctrl *flash_ctrl = NULL; + int32_t rc = 0, i = 0; + struct cam_flash_ctrl *fctrl = NULL; CAM_DBG(CAM_FLASH, "Enter"); if (!pdev->dev.of_node) { @@ -333,53 +394,181 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) return -EINVAL; } - flash_ctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL); - if (!flash_ctrl) + fctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL); + if (!fctrl) return -ENOMEM; - flash_ctrl->pdev = pdev; - flash_ctrl->soc_info.pdev = pdev; - flash_ctrl->soc_info.dev = &pdev->dev; - flash_ctrl->soc_info.dev_name = pdev->name; + fctrl->pdev = pdev; + fctrl->soc_info.pdev = pdev; + fctrl->soc_info.dev = &pdev->dev; + fctrl->soc_info.dev_name = pdev->name; + + platform_set_drvdata(pdev, fctrl); - rc = cam_flash_get_dt_data(flash_ctrl, &flash_ctrl->soc_info); + rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info); if (rc) { CAM_ERR(CAM_FLASH, "cam_flash_get_dt_data failed with %d", rc); - kfree(flash_ctrl); + kfree(fctrl); return -EINVAL; } - flash_ctrl->v4l2_dev_str.internal_ops = - &cam_flash_internal_ops; - flash_ctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops; - flash_ctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME; - flash_ctrl->v4l2_dev_str.sd_flags = - V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; - flash_ctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; - flash_ctrl->v4l2_dev_str.token = flash_ctrl; + if (of_find_property(pdev->dev.of_node, "cci-master", NULL)) { + /* Get CCI master */ + rc = of_property_read_u32(pdev->dev.of_node, "cci-master", + &fctrl->cci_i2c_master); + CAM_DBG(CAM_FLASH, "cci-master %d, rc %d", + fctrl->cci_i2c_master, rc); + if (rc < 0) { + /* Set default master 0 */ + fctrl->cci_i2c_master = MASTER_0; + rc = 0; + } + + fctrl->io_master_info.master_type = CCI_MASTER; + rc = cam_flash_init_default_params(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed: cam_flash_init_default_params rc %d", + rc); + return rc; + } - rc = cam_register_subdev(&(flash_ctrl->v4l2_dev_str)); + fctrl->i2c_data.per_frame = (struct i2c_settings_array *) + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (fctrl->i2c_data.per_frame == NULL) { + CAM_ERR(CAM_FLASH, "No Memory"); + rc = -ENOMEM; + goto free_cci_resource; + } + + INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD( + &(fctrl->i2c_data.per_frame[i].list_head)); + + fctrl->func_tbl.parser = cam_flash_i2c_pkt_parser; + fctrl->func_tbl.apply_setting = cam_flash_i2c_apply_setting; + fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops; + fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request; + } else { + /* PMIC Flash */ + fctrl->func_tbl.parser = cam_flash_pmic_pkt_parser; + fctrl->func_tbl.apply_setting = cam_flash_pmic_apply_setting; + fctrl->func_tbl.power_ops = cam_flash_pmic_power_ops; + fctrl->func_tbl.flush_req = cam_flash_pmic_flush_request; + } + + rc = cam_flash_init_subdev(fctrl); if (rc) { - CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc); - goto free_resource; + if (fctrl->io_master_info.cci_client != NULL) + goto free_cci_resource; + else + goto free_resource; } - flash_ctrl->bridge_intf.device_hdl = -1; - flash_ctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; - flash_ctrl->bridge_intf.ops.link_setup = cam_flash_establish_link; - flash_ctrl->bridge_intf.ops.apply_req = cam_flash_apply_request; - flash_ctrl->bridge_intf.ops.flush_req = cam_flash_flush_request; - platform_set_drvdata(pdev, flash_ctrl); - v4l2_set_subdevdata(&flash_ctrl->v4l2_dev_str.sd, flash_ctrl); + fctrl->bridge_intf.device_hdl = -1; + fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; + fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link; + fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request; + fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request; - mutex_init(&(flash_ctrl->flash_mutex)); - mutex_init(&(flash_ctrl->flash_wq_mutex)); + mutex_init(&(fctrl->flash_mutex)); - flash_ctrl->flash_state = CAM_FLASH_STATE_INIT; + fctrl->flash_state = CAM_FLASH_STATE_INIT; CAM_DBG(CAM_FLASH, "Probe success"); return rc; + +free_cci_resource: + kfree(fctrl->io_master_info.cci_client); + fctrl->io_master_info.cci_client = NULL; free_resource: - kfree(flash_ctrl); + kfree(fctrl->i2c_data.per_frame); + kfree(fctrl->soc_info.soc_private); + cam_soc_util_release_platform_resource(&fctrl->soc_info); + fctrl->i2c_data.per_frame = NULL; + fctrl->soc_info.soc_private = NULL; + kfree(fctrl); + fctrl = NULL; + return rc; +} + +static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int32_t rc = 0, i = 0; + struct cam_flash_ctrl *fctrl; + + if (client == NULL || id == NULL) { + CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK", + client, id); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed", + client->name); + return -EFAULT; + } + + /* Create sensor control structure */ + fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL); + if (!fctrl) + return -ENOMEM; + + i2c_set_clientdata(client, fctrl); + + fctrl->io_master_info.client = client; + fctrl->soc_info.dev = &client->dev; + fctrl->soc_info.dev_name = client->name; + fctrl->io_master_info.master_type = I2C_MASTER; + + rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc); + goto free_ctrl; + } + + rc = cam_flash_init_subdev(fctrl); + if (rc) + goto free_ctrl; + + fctrl->i2c_data.per_frame = + (struct i2c_settings_array *) + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (fctrl->i2c_data.per_frame == NULL) { + rc = -ENOMEM; + goto unreg_subdev; + } + + INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head)); + + fctrl->func_tbl.parser = cam_flash_i2c_pkt_parser; + fctrl->func_tbl.apply_setting = cam_flash_i2c_apply_setting; + fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops; + fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request; + + fctrl->bridge_intf.device_hdl = -1; + fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; + fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link; + fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request; + fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request; + + mutex_init(&(fctrl->flash_mutex)); + fctrl->flash_state = CAM_FLASH_STATE_INIT; + + return rc; + +unreg_subdev: + cam_unregister_subdev(&(fctrl->v4l2_dev_str)); +free_ctrl: + kfree(fctrl); + fctrl = NULL; return rc; } @@ -396,20 +585,40 @@ static struct platform_driver cam_flash_platform_driver = { }, }; -static int __init cam_flash_init_module(void) +static const struct i2c_device_id i2c_id[] = { + {FLASH_DRIVER_I2C, (kernel_ulong_t)NULL}, + { } +}; + +static struct i2c_driver cam_flash_i2c_driver = { + .id_table = i2c_id, + .probe = cam_flash_i2c_driver_probe, + .remove = cam_flash_i2c_driver_remove, + .driver = { + .name = FLASH_DRIVER_I2C, + }, +}; + +static int32_t __init cam_flash_init_module(void) { int32_t rc = 0; rc = platform_driver_register(&cam_flash_platform_driver); - if (rc) - CAM_ERR(CAM_FLASH, "platform probe for flash failed"); + if (rc == 0) { + CAM_DBG(CAM_FLASH, "platform probe success"); + return 0; + } + rc = i2c_add_driver(&cam_flash_i2c_driver); + if (rc) + CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc); return rc; } static void __exit cam_flash_exit_module(void) { platform_driver_unregister(&cam_flash_platform_driver); + i2c_del_driver(&cam_flash_i2c_driver); } module_init(cam_flash_init_module); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h index 4adc1b2e32a9..cb542395df38 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -33,15 +33,21 @@ #include "cam_sensor_cmn_header.h" #include "cam_soc_util.h" #include "cam_debug_util.h" +#include "cam_sensor_io.h" +#include "cam_flash_core.h" #define CAMX_FLASH_DEV_NAME "cam-flash-dev" #define CAM_FLASH_PIPELINE_DELAY 1 +#define FLASH_DRIVER_I2C "i2c_flash" + #define CAM_FLASH_PACKET_OPCODE_INIT 0 #define CAM_FLASH_PACKET_OPCODE_SET_OPS 1 #define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2 +struct cam_flash_ctrl; + enum cam_flash_switch_trigger_ops { LED_SWITCH_OFF = 0, LED_SWITCH_ON, @@ -54,6 +60,12 @@ enum cam_flash_state { CAM_FLASH_STATE_START, }; +enum cam_flash_flush_type { + FLUSH_ALL = 0, + FLUSH_REQ, + FLUSH_MAX, +}; + /** * struct cam_flash_intf_params * @device_hdl : Device Handle @@ -136,6 +148,14 @@ struct cam_flash_private_soc { uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; }; +struct cam_flash_func_tbl { + int (*parser)(struct cam_flash_ctrl *fctrl, void *arg); + int (*apply_setting)(struct cam_flash_ctrl *fctrl, uint64_t req_id); + int (*power_ops)(struct cam_flash_ctrl *fctrl, bool regulator_enable); + int (*flush_req)(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id); +}; + /** * struct cam_flash_ctrl * @soc_info : Soc related information @@ -150,32 +170,57 @@ struct cam_flash_private_soc { * @flash_num_sources : Number of flash sources * @torch_num_source : Number of torch sources * @flash_mutex : Mutex for flash operations - * @flash_wq_mutex : Mutex for flash apply setting - * @flash_state : Current flash state (LOW/OFF/ON/INIT) + * @flash_state : Current flash state (LOW/OFF/ON/INIT) * @flash_type : Flash types (PMIC/I2C/GPIO) * @is_regulator_enable : Regulator disable/enable notifier + * @func_tbl : Function table for different HW + * (e.g. i2c/pmic/gpio) * @flash_trigger : Flash trigger ptr * @torch_trigger : Torch trigger ptr + * @cci_i2c_master : I2C structure + * @io_master_info : Information about the communication master + * @i2c_data : I2C register settings */ struct cam_flash_ctrl { - struct cam_hw_soc_info soc_info; - struct platform_device *pdev; - struct cam_flash_frame_setting per_frame[MAX_PER_FRAME_ARRAY]; - struct cam_flash_frame_setting nrt_info; - struct device_node *of_node; - struct cam_subdev v4l2_dev_str; - struct cam_flash_intf_params bridge_intf; - struct cam_flash_init_packet flash_init_setting; - struct led_trigger *switch_trigger; - uint32_t flash_num_sources; - uint32_t torch_num_sources; - struct mutex flash_mutex; - struct mutex flash_wq_mutex; - enum cam_flash_state flash_state; - uint8_t flash_type; - bool is_regulator_enabled; + struct cam_hw_soc_info soc_info; + struct platform_device *pdev; + struct cam_sensor_power_ctrl_t power_info; + struct cam_flash_frame_setting per_frame[MAX_PER_FRAME_ARRAY]; + struct cam_flash_frame_setting nrt_info; + struct device_node *of_node; + struct cam_subdev v4l2_dev_str; + struct cam_flash_intf_params bridge_intf; + struct cam_flash_init_packet flash_init_setting; + struct led_trigger *switch_trigger; + uint32_t flash_num_sources; + uint32_t torch_num_sources; + struct mutex flash_mutex; + enum cam_flash_state flash_state; + uint8_t flash_type; + bool is_regulator_enabled; + struct cam_flash_func_tbl func_tbl; struct led_trigger *flash_trigger[CAM_FLASH_MAX_LED_TRIGGERS]; struct led_trigger *torch_trigger[CAM_FLASH_MAX_LED_TRIGGERS]; +/* I2C related setting */ + enum cci_i2c_master_t cci_i2c_master; + struct camera_io_master io_master_info; + struct i2c_data_settings i2c_data; }; +int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg); +int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg); +int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id); +int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id); +int cam_flash_off(struct cam_flash_ctrl *fctrl); +int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable); +int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl, + bool regulator_enable); +int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type type, uint64_t req_id); +int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, + enum cam_flash_flush_type, uint64_t req_id); +void cam_flash_shutdown(struct cam_flash_ctrl *fctrl); +int cam_flash_release_dev(struct cam_flash_ctrl *fctrl); + #endif /*_CAM_FLASH_DEV_H_*/ diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c index a195762c249f..22a124d86f93 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -193,32 +193,31 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, return -EINVAL; } - of_node = fctrl->pdev->dev.of_node; - - rc = cam_soc_util_get_dt_properties(soc_info); - if (rc < 0) { - CAM_ERR(CAM_FLASH, "Get_dt_properties failed rc %d", rc); - return rc; - } - soc_info->soc_private = kzalloc(sizeof(struct cam_flash_private_soc), GFP_KERNEL); if (!soc_info->soc_private) { rc = -ENOMEM; goto release_soc_res; } + of_node = fctrl->pdev->dev.of_node; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_FLASH, "Get_dt_properties failed rc %d", rc); + goto free_soc_private; + } rc = cam_get_source_node_info(of_node, fctrl, soc_info->soc_private); - if (rc < 0) { + if (rc) { CAM_ERR(CAM_FLASH, "cam_flash_get_pmic_source_info failed rc %d", rc); goto free_soc_private; } - return rc; free_soc_private: kfree(soc_info->soc_private); + soc_info->soc_private = NULL; release_soc_res: cam_soc_util_release_platform_resource(soc_info); return rc; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c index 05706556d9db..850b315c26a7 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c @@ -18,6 +18,7 @@ #include "cam_sensor_util.h" #include "cam_debug_util.h" #include "cam_res_mgr_api.h" +#include "cam_common_util.h" int32_t cam_ois_construct_default_power_setting( struct cam_sensor_power_ctrl_t *power_info) @@ -79,7 +80,7 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, CAM_ERR(CAM_OIS, "Device is already acquired"); return -EFAULT; } - if (copy_from_user(&ois_acq_dev, (void __user *) cmd->handle, + if (copy_from_user(&ois_acq_dev, u64_to_user_ptr(cmd->handle), sizeof(ois_acq_dev))) return -EFAULT; @@ -95,7 +96,7 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle; CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle); - if (copy_to_user((void __user *) cmd->handle, &ois_acq_dev, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &ois_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed"); return -EFAULT; @@ -193,7 +194,7 @@ static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl) return -EINVAL; } - rc = msm_camera_power_down(power_info, soc_info); + rc = cam_sensor_util_power_down(power_info, soc_info); if (rc) { CAM_ERR(CAM_OIS, "power down the core is failed:%d", rc); return rc; @@ -425,12 +426,12 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) int32_t i = 0; uint32_t total_cmd_buf_in_bytes = 0; struct common_header *cmm_hdr = NULL; - uint64_t generic_ptr; + uintptr_t generic_ptr; struct cam_control *ioctl_ctrl = NULL; struct cam_config_dev_cmd dev_config; struct i2c_settings_array *i2c_reg_settings = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; - uint64_t generic_pkt_addr; + uintptr_t generic_pkt_addr; size_t pkt_len; struct cam_packet *csl_packet = NULL; size_t len_of_buff = 0; @@ -440,11 +441,12 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; ioctl_ctrl = (struct cam_control *)arg; - if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle, + if (copy_from_user(&dev_config, + u64_to_user_ptr(ioctl_ctrl->handle), sizeof(dev_config))) return -EFAULT; rc = cam_mem_get_cpu_buf(dev_config.packet_handle, - (uint64_t *)&generic_pkt_addr, &pkt_len); + &generic_pkt_addr, &pkt_len); if (rc) { CAM_ERR(CAM_OIS, "error in converting command Handle Error: %d", rc); @@ -459,7 +461,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } csl_packet = (struct cam_packet *) - (generic_pkt_addr + dev_config.offset); + (generic_pkt_addr + (uint32_t)dev_config.offset); switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_OIS_PACKET_OPCODE_INIT: offset = (uint32_t *)&csl_packet->payload; @@ -473,7 +475,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) continue; rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, - (uint64_t *)&generic_ptr, &len_of_buff); + &generic_ptr, &len_of_buff); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed to get cpu buf"); return rc; @@ -716,7 +718,7 @@ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg) case CAM_QUERY_CAP: ois_cap.slot_info = o_ctrl->soc_info.index; - if (copy_to_user((void __user *) cmd->handle, + if (copy_to_user(u64_to_user_ptr(cmd->handle), &ois_cap, sizeof(struct cam_ois_query_cap_t))) { CAM_ERR(CAM_OIS, "Failed Copy to User"); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c index a2431be71176..c88e96980ff9 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -16,6 +16,7 @@ #include "cam_sensor_util.h" #include "cam_soc_util.h" #include "cam_trace.h" +#include "cam_common_util.h" static void cam_sensor_update_req_mgr( struct cam_sensor_ctrl_t *s_ctrl, @@ -62,30 +63,12 @@ static void cam_sensor_release_stream_rsc( } } -static void cam_sensor_release_resource( +static void cam_sensor_release_per_frame_resource( struct cam_sensor_ctrl_t *s_ctrl) { struct i2c_settings_array *i2c_set = NULL; int i, rc; - i2c_set = &(s_ctrl->i2c_data.init_settings); - if (i2c_set->is_settings_valid == 1) { - i2c_set->is_settings_valid = -1; - rc = delete_request(i2c_set); - if (rc < 0) - CAM_ERR(CAM_SENSOR, - "failed while deleting Init settings"); - } - - i2c_set = &(s_ctrl->i2c_data.config_settings); - if (i2c_set->is_settings_valid == 1) { - i2c_set->is_settings_valid = -1; - rc = delete_request(i2c_set); - if (rc < 0) - CAM_ERR(CAM_SENSOR, - "failed while deleting Res settings"); - } - if (s_ctrl->i2c_data.per_frame != NULL) { for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { i2c_set = &(s_ctrl->i2c_data.per_frame[i]); @@ -105,7 +88,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, void *arg) { int32_t rc = 0; - uint64_t generic_ptr; + uintptr_t generic_ptr; struct cam_control *ioctl_ctrl = NULL; struct cam_packet *csl_packet = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; @@ -122,13 +105,14 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, return -EINVAL; } - if (copy_from_user(&config, (void __user *) ioctl_ctrl->handle, + if (copy_from_user(&config, + u64_to_user_ptr(ioctl_ctrl->handle), sizeof(config))) return -EFAULT; rc = cam_mem_get_cpu_buf( config.packet_handle, - (uint64_t *)&generic_ptr, + &generic_ptr, &len_of_buff); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed in getting the buffer: %d", rc); @@ -136,7 +120,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, } csl_packet = (struct cam_packet *)(generic_ptr + - config.offset); + (uint32_t)config.offset); if (config.offset > len_of_buff) { CAM_ERR(CAM_SENSOR, "offset is out of bounds: off: %lld len: %zu", @@ -403,15 +387,16 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf, int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl) { int rc = 0, i; - void *packet = NULL, *cmd_buf1 = NULL; uint32_t *cmd_buf; void *ptr; size_t len; struct cam_packet *pkt; struct cam_cmd_buf_desc *cmd_desc; + uintptr_t cmd_buf1 = 0; + uintptr_t packet = 0; rc = cam_mem_get_cpu_buf(handle, - (uint64_t *)&packet, &len); + &packet, &len); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed to get the command Buffer"); return -EINVAL; @@ -432,7 +417,7 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl) if (!(cmd_desc[i].length)) continue; rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, - (uint64_t *)&cmd_buf1, &len); + &cmd_buf1, &len); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed to parse the command Buffer Header"); @@ -503,10 +488,9 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl) (s_ctrl->is_probe_succeed == 0)) return; - cam_sensor_release_resource(s_ctrl); cam_sensor_release_stream_rsc(s_ctrl); - if (s_ctrl->sensor_state >= CAM_SENSOR_ACQUIRE) - cam_sensor_power_down(s_ctrl); + cam_sensor_release_per_frame_resource(s_ctrl); + cam_sensor_power_down(s_ctrl); rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl); if (rc < 0) @@ -676,7 +660,8 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, goto release_mutex; } rc = copy_from_user(&sensor_acq_dev, - (void __user *) cmd->handle, sizeof(sensor_acq_dev)); + u64_to_user_ptr(cmd->handle), + sizeof(sensor_acq_dev)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); goto release_mutex; @@ -695,7 +680,8 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, CAM_DBG(CAM_SENSOR, "Device Handle: %d", sensor_acq_dev.device_handle); - if (copy_to_user((void __user *) cmd->handle, &sensor_acq_dev, + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &sensor_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_SENSOR, "Failed Copy to User"); rc = -EFAULT; @@ -731,7 +717,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, goto release_mutex; } - cam_sensor_release_resource(s_ctrl); + cam_sensor_release_per_frame_resource(s_ctrl); cam_sensor_release_stream_rsc(s_ctrl); if (s_ctrl->bridge_intf.device_hdl == -1) { CAM_ERR(CAM_SENSOR, @@ -762,8 +748,8 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, struct cam_sensor_query_cap sensor_cap; cam_sensor_query_cap(s_ctrl, &sensor_cap); - if (copy_to_user((void __user *) cmd->handle, &sensor_cap, - sizeof(struct cam_sensor_query_cap))) { + if (copy_to_user(u64_to_user_ptr(cmd->handle), + &sensor_cap, sizeof(struct cam_sensor_query_cap))) { CAM_ERR(CAM_SENSOR, "Failed Copy to User"); rc = -EFAULT; goto release_mutex; @@ -816,7 +802,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } } - cam_sensor_release_resource(s_ctrl); + cam_sensor_release_per_frame_resource(s_ctrl); s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; CAM_INFO(CAM_SENSOR, "CAM_STOP_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", @@ -918,6 +904,8 @@ int cam_sensor_establish_link(struct cam_req_mgr_core_dev_link_setup *link) CAM_ERR(CAM_SENSOR, "Device data is NULL"); return -EINVAL; } + + mutex_lock(&s_ctrl->cam_sensor_mutex); if (link->link_enable) { s_ctrl->bridge_intf.link_hdl = link->link_hdl; s_ctrl->bridge_intf.crm_cb = link->crm_cb; @@ -925,6 +913,7 @@ int cam_sensor_establish_link(struct cam_req_mgr_core_dev_link_setup *link) s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.crm_cb = NULL; } + mutex_unlock(&s_ctrl->cam_sensor_mutex); return 0; } @@ -1005,7 +994,7 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl) CAM_ERR(CAM_SENSOR, "failed: power_info %pK", power_info); return -EINVAL; } - rc = msm_camera_power_down(power_info, soc_info); + rc = cam_sensor_util_power_down(power_info, soc_info); if (rc < 0) { CAM_ERR(CAM_SENSOR, "power down the core is failed:%d", rc); return rc; @@ -1155,8 +1144,10 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply) } CAM_DBG(CAM_REQ, " Sensor update req id: %lld", apply->request_id); trace_cam_apply_req("Sensor", apply->request_id); + mutex_lock(&(s_ctrl->cam_sensor_mutex)); rc = cam_sensor_apply_settings(s_ctrl, apply->request_id, CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); return rc; } @@ -1190,7 +1181,9 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) continue; if (i2c_set->is_settings_valid == 1) { + mutex_lock(&(s_ctrl->cam_sensor_mutex)); rc = delete_request(i2c_set); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); if (rc < 0) CAM_ERR(CAM_SENSOR, "delete request: %lld rc: %d", diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 46bda0589c52..5c1143ece162 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -296,7 +296,7 @@ int cam_sensor_i2c_command_parser( { int16_t rc = 0, i = 0; size_t len_of_buff = 0; - uint64_t generic_ptr; + uintptr_t generic_ptr; uint16_t cmd_length_in_bytes = 0; for (i = 0; i < num_cmd_buffers; i++) { @@ -318,11 +318,11 @@ int cam_sensor_i2c_command_parser( continue; rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, - (uint64_t *)&generic_ptr, &len_of_buff); + &generic_ptr, &len_of_buff); cmd_buf = (uint32_t *)generic_ptr; if (rc < 0) { CAM_ERR(CAM_SENSOR, - "cmd hdl failed:%d, Err: %d, Buffer_len: %ld", + "cmd hdl failed:%d, Err: %d, Buffer_len: %zd", cmd_desc[i].mem_handle, rc, len_of_buff); return rc; } @@ -439,6 +439,75 @@ int cam_sensor_i2c_command_parser( return rc; } +int cam_sensor_util_i2c_apply_setting( + struct camera_io_master *io_master_info, + struct i2c_settings_list *i2c_list) +{ + int32_t rc = 0; + uint32_t i, size; + + switch (i2c_list->op_code) { + case CAM_SENSOR_I2C_WRITE_RANDOM: { + rc = camera_io_dev_write(io_master_info, + &(i2c_list->i2c_settings)); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to random write I2C settings: %d", + rc); + return rc; + } + break; + } + case CAM_SENSOR_I2C_WRITE_SEQ: { + rc = camera_io_dev_write_continuous( + io_master_info, &(i2c_list->i2c_settings), 0); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to seq write I2C settings: %d", + rc); + return rc; + } + break; + } + case CAM_SENSOR_I2C_WRITE_BURST: { + rc = camera_io_dev_write_continuous( + io_master_info, &(i2c_list->i2c_settings), 1); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed to burst write I2C settings: %d", + rc); + return rc; + } + break; + } + case CAM_SENSOR_I2C_POLL: { + size = i2c_list->i2c_settings.size; + for (i = 0; i < size; i++) { + rc = camera_io_dev_poll( + io_master_info, + i2c_list->i2c_settings.reg_setting[i].reg_addr, + i2c_list->i2c_settings.reg_setting[i].reg_data, + i2c_list->i2c_settings.reg_setting[i].data_mask, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.reg_setting[i].delay); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "i2c poll apply setting Fail: %d", rc); + return rc; + } + } + break; + } + default: + CAM_ERR(CAM_SENSOR, "Wrong Opcode: %d", i2c_list->op_code); + rc = -EINVAL; + break; + } + + return rc; +} + int32_t msm_camera_fill_vreg_params( struct cam_hw_soc_info *soc_info, struct cam_sensor_power_setting *power_setting, @@ -1710,7 +1779,7 @@ msm_camera_get_power_settings(struct cam_sensor_power_ctrl_t *ctrl, return ps; } -int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl, +int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info) { int index = 0, ret = 0, num_vreg = 0, i; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 6c0287e48487..583ddb14243b 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -39,6 +39,9 @@ int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers); +int cam_sensor_util_i2c_apply_setting(struct camera_io_master *io_master_info, + struct i2c_settings_list *i2c_list); + int32_t delete_request(struct i2c_settings_array *i2c_array); int cam_sensor_util_request_gpio_table( struct cam_hw_soc_info *soc_info, int gpio_en); @@ -49,7 +52,7 @@ int cam_sensor_util_init_gpio_pin_tbl( int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info); -int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl, +int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, struct cam_hw_soc_info *soc_info); int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info, diff --git a/drivers/media/platform/msm/camera/cam_smmu/Makefile b/drivers/media/platform/msm/camera/cam_smmu/Makefile index e17dac6c0d9d..96f39680fd0c 100644 --- a/drivers/media/platform/msm/camera/cam_smmu/Makefile +++ b/drivers/media/platform/msm/camera/cam_smmu/Makefile @@ -1,3 +1,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils +ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu_api.o diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c index 52da37f8239b..56209c67255e 100644 --- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c @@ -23,6 +23,7 @@ #include <linux/genalloc.h> #include <soc/qcom/scm.h> #include <soc/qcom/secure_buffer.h> +#include <uapi/media/cam_req_mgr.h> #include "cam_smmu_api.h" #include "cam_debug_util.h" @@ -34,11 +35,14 @@ #define COOKIE_SIZE (BYTE_SIZE*COOKIE_NUM_BYTE) #define COOKIE_MASK ((1<<COOKIE_SIZE)-1) #define HANDLE_INIT (-1) -#define CAM_SMMU_CB_MAX 2 +#define CAM_SMMU_CB_MAX 5 #define GET_SMMU_HDL(x, y) (((x) << COOKIE_SIZE) | ((y) & COOKIE_MASK)) #define GET_SMMU_TABLE_IDX(x) (((x) >> COOKIE_SIZE) & COOKIE_MASK) +static int g_num_pf_handled = 4; +module_param(g_num_pf_handled, int, 0644); + struct firmware_alloc_info { struct device *fw_dev; void *fw_kva; @@ -129,12 +133,11 @@ struct cam_context_bank_info { int handle; enum cam_smmu_ops_param state; - void (*handler[CAM_SMMU_CB_MAX])(struct iommu_domain *, - struct device *, unsigned long, - int, void*); + cam_smmu_client_page_fault_handler handler[CAM_SMMU_CB_MAX]; void *token[CAM_SMMU_CB_MAX]; int cb_count; int secure_count; + int pf_count; }; struct cam_iommu_cb_set { @@ -252,13 +255,14 @@ static void cam_smmu_print_table(void); static int cam_smmu_probe(struct platform_device *pdev); -static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr); +static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr); static void cam_smmu_page_fault_work(struct work_struct *work) { int j; int idx; struct cam_smmu_work_payload *payload; + uint32_t buf_info; mutex_lock(&iommu_cb_set.payload_list_lock); if (list_empty(&iommu_cb_set.payload_list)) { @@ -275,8 +279,11 @@ static void cam_smmu_page_fault_work(struct work_struct *work) /* Dereference the payload to call the handler */ idx = payload->idx; - mutex_lock(&iommu_cb_set.cb_info[idx].lock); - cam_smmu_check_vaddr_in_range(idx, (void *)payload->iova); + buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova); + if (buf_info != 0) { + CAM_INFO(CAM_SMMU, "closest buf 0x%x idx %d", buf_info, idx); + } + for (j = 0; j < CAM_SMMU_CB_MAX; j++) { if ((iommu_cb_set.cb_info[idx].handler[j])) { iommu_cb_set.cb_info[idx].handler[j]( @@ -284,10 +291,10 @@ static void cam_smmu_page_fault_work(struct work_struct *work) payload->dev, payload->iova, payload->flags, - iommu_cb_set.cb_info[idx].token[j]); + iommu_cb_set.cb_info[idx].token[j], + buf_info); } } - mutex_unlock(&iommu_cb_set.cb_info[idx].lock); kfree(payload); } @@ -333,10 +340,13 @@ static void cam_smmu_print_table(void) } } -static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr) +static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr) { - struct cam_dma_buff_info *mapping; + struct cam_dma_buff_info *mapping, *closest_mapping = NULL; unsigned long start_addr, end_addr, current_addr; + uint32_t buf_handle = 0; + + long delta = 0, lowest_delta = 0; current_addr = (unsigned long)vaddr; list_for_each_entry(mapping, @@ -344,31 +354,51 @@ static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr) start_addr = (unsigned long)mapping->paddr; end_addr = (unsigned long)mapping->paddr + mapping->len; - if (start_addr <= current_addr && current_addr < end_addr) { - CAM_ERR(CAM_SMMU, - "va %pK valid: range:%pK-%pK, fd = %d cb: %s", - vaddr, (void *)start_addr, (void *)end_addr, - mapping->ion_fd, + if (start_addr <= current_addr && current_addr <= end_addr) { + closest_mapping = mapping; + CAM_INFO(CAM_SMMU, + "Found va 0x%lx in:0x%lx-0x%lx, fd %d cb:%s", + current_addr, start_addr, + end_addr, mapping->ion_fd, iommu_cb_set.cb_info[idx].name); goto end; } else { + if (start_addr > current_addr) + delta = start_addr - current_addr; + else + delta = current_addr - end_addr - 1; + + if (delta < lowest_delta || lowest_delta == 0) { + lowest_delta = delta; + closest_mapping = mapping; + } CAM_DBG(CAM_SMMU, - "va %pK is not in this range: %pK-%pK, fd = %d", - vaddr, (void *)start_addr, (void *)end_addr, - mapping->ion_fd); + "approx va %lx not in range: %lx-%lx fd = %0x", + current_addr, start_addr, + end_addr, mapping->ion_fd); } } - CAM_ERR(CAM_SMMU, - "Cannot find vaddr:%pK in SMMU %s uses invalid virt address", - vaddr, iommu_cb_set.cb_info[idx].name); -end: - return; -} -void cam_smmu_reg_client_page_fault_handler(int handle, - void (*client_page_fault_handler)(struct iommu_domain *, - struct device *, unsigned long, - int, void*), void *token) +end: + if (closest_mapping) { + buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd); + CAM_INFO(CAM_SMMU, + "Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x", + closest_mapping->ion_fd, current_addr, + (unsigned long)closest_mapping->paddr, + (unsigned long)closest_mapping->paddr + mapping->len, + closest_mapping->buf, + buf_handle); + } else + CAM_INFO(CAM_SMMU, + "Cannot find vaddr:%lx in SMMU %s virt address", + current_addr, iommu_cb_set.cb_info[idx].name); + + return buf_handle; +} + +void cam_smmu_set_client_page_fault_handler(int handle, + cam_smmu_client_page_fault_handler handler_cb, void *token) { int idx, i = 0; @@ -394,7 +424,7 @@ void cam_smmu_reg_client_page_fault_handler(int handle, return; } - if (client_page_fault_handler) { + if (handler_cb) { if (iommu_cb_set.cb_info[idx].cb_count == CAM_SMMU_CB_MAX) { CAM_ERR(CAM_SMMU, "%s Should not regiester more handlers", @@ -402,12 +432,14 @@ void cam_smmu_reg_client_page_fault_handler(int handle, mutex_unlock(&iommu_cb_set.cb_info[idx].lock); return; } + iommu_cb_set.cb_info[idx].cb_count++; + for (i = 0; i < iommu_cb_set.cb_info[idx].cb_count; i++) { if (iommu_cb_set.cb_info[idx].token[i] == NULL) { iommu_cb_set.cb_info[idx].token[i] = token; iommu_cb_set.cb_info[idx].handler[i] = - client_page_fault_handler; + handler_cb; break; } } @@ -429,6 +461,47 @@ void cam_smmu_reg_client_page_fault_handler(int handle, mutex_unlock(&iommu_cb_set.cb_info[idx].lock); } +void cam_smmu_unset_client_page_fault_handler(int handle, void *token) +{ + int idx, i = 0; + + if (!token || (handle == HANDLE_INIT)) { + CAM_ERR(CAM_SMMU, "Error: token is NULL or invalid handle"); + return; + } + + idx = GET_SMMU_TABLE_IDX(handle); + if (idx < 0 || idx >= iommu_cb_set.cb_num) { + CAM_ERR(CAM_SMMU, + "Error: handle or index invalid. idx = %d hdl = %x", + idx, handle); + return; + } + + mutex_lock(&iommu_cb_set.cb_info[idx].lock); + if (iommu_cb_set.cb_info[idx].handle != handle) { + CAM_ERR(CAM_SMMU, + "Error: hdl is not valid, table_hdl = %x, hdl = %x", + iommu_cb_set.cb_info[idx].handle, handle); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); + return; + } + + for (i = 0; i < CAM_SMMU_CB_MAX; i++) { + if (iommu_cb_set.cb_info[idx].token[i] == token) { + iommu_cb_set.cb_info[idx].token[i] = NULL; + iommu_cb_set.cb_info[idx].handler[i] = + NULL; + iommu_cb_set.cb_info[idx].cb_count--; + break; + } + } + if (i == CAM_SMMU_CB_MAX) + CAM_ERR(CAM_SMMU, "Error: hdl %x no matching tokens: %s", + handle, iommu_cb_set.cb_info[idx].name); + mutex_unlock(&iommu_cb_set.cb_info[idx].lock); +} + static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *token) @@ -459,6 +532,13 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, return -EINVAL; } + if (++iommu_cb_set.cb_info[idx].pf_count > g_num_pf_handled) { + CAM_INFO(CAM_SMMU, "PF already handled %d %d %d", + g_num_pf_handled, idx, + iommu_cb_set.cb_info[idx].pf_count); + return -EINVAL; + } + payload = kzalloc(sizeof(struct cam_smmu_work_payload), GFP_ATOMIC); if (!payload) return -EINVAL; @@ -474,7 +554,7 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, list_add_tail(&payload->list, &iommu_cb_set.payload_list); mutex_unlock(&iommu_cb_set.payload_list_lock); - schedule_work(&iommu_cb_set.smmu_work); + cam_smmu_page_fault_work(&iommu_cb_set.smmu_work); return -EINVAL; } @@ -528,6 +608,7 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops) iommu_cb_set.cb_info[i].state = CAM_SMMU_DETACH; iommu_cb_set.cb_info[i].dev = NULL; iommu_cb_set.cb_info[i].cb_count = 0; + iommu_cb_set.cb_info[i].pf_count = 0; for (j = 0; j < CAM_SMMU_CB_MAX; j++) { iommu_cb_set.cb_info[i].token[j] = NULL; iommu_cb_set.cb_info[i].handler[j] = NULL; @@ -1009,7 +1090,7 @@ get_addr_end: int cam_smmu_alloc_firmware(int32_t smmu_hdl, dma_addr_t *iova, - uint64_t *cpuva, + uintptr_t *cpuva, size_t *len) { int rc; @@ -1078,7 +1159,7 @@ int cam_smmu_alloc_firmware(int32_t smmu_hdl, iommu_cb_set.cb_info[idx].is_fw_allocated = true; *iova = iommu_cb_set.cb_info[idx].firmware_info.iova_start; - *cpuva = (uint64_t)icp_fw.fw_kva; + *cpuva = (uintptr_t)icp_fw.fw_kva; *len = firmware_len; mutex_unlock(&iommu_cb_set.cb_info[idx].lock); diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h index 254e382a99ad..caf326d6c716 100644 --- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h +++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -51,6 +51,21 @@ enum cam_smmu_region_id { }; /** + * @brief : Callback function type that gets called back on cam + * smmu page fault. + * + * @param domain : Iommu domain received in iommu page fault handler + * @param dev : Device received in iommu page fault handler + * @param iova : IOVA where page fault occurred + * @param flags : Flags received in iommu page fault handler + * @param token : Userdata given during callback registration + * @param buf_info : Closest mapped buffer info + */ +typedef void (*cam_smmu_client_page_fault_handler)(struct iommu_domain *domain, + struct device *dev, unsigned long iova, int flags, void *token, + uint32_t buf_info); + +/** * @brief : Structure to store region information * * @param iova_start : Start address of region @@ -215,13 +230,19 @@ int cam_smmu_find_index_by_handle(int hdl); * @brief : Registers smmu fault handler for client * * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) - * @param client_page_fault_handler: It is triggered in IOMMU page fault + * @param handler_cb: It is triggered in IOMMU page fault + * @param token: It is input param when trigger page fault handler + */ +void cam_smmu_set_client_page_fault_handler(int handle, + cam_smmu_client_page_fault_handler handler_cb, void *token); + +/** + * @brief : Unregisters smmu fault handler for client + * + * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.) * @param token: It is input param when trigger page fault handler */ -void cam_smmu_reg_client_page_fault_handler(int handle, - void (*client_page_fault_handler)(struct iommu_domain *, - struct device *, unsigned long, - int, void*), void *token); +void cam_smmu_unset_client_page_fault_handler(int handle, void *token); /** * @brief Maps memory from an ION fd into IOVA space @@ -297,7 +318,7 @@ int cam_smmu_unmap_stage2_iova(int handle, int ion_fd); */ int cam_smmu_alloc_firmware(int32_t smmu_hdl, dma_addr_t *iova, - uint64_t *kvaddr, + uintptr_t *kvaddr, size_t *len); /** diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c index 4525bb5bce25..c9e6e5fe7f61 100644 --- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c +++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c @@ -426,7 +426,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl) return -EINVAL; if (copy_from_user(&sync_create, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; @@ -434,7 +434,8 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl) sync_create.name); if (!result) - if (copy_to_user((void *)k_ioctl->ioctl_ptr, + if (copy_to_user( + u64_to_user_ptr(k_ioctl->ioctl_ptr), &sync_create, k_ioctl->size)) return -EFAULT; @@ -453,7 +454,7 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl) return -EINVAL; if (copy_from_user(&sync_signal, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; @@ -478,7 +479,7 @@ static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl) return -EINVAL; if (copy_from_user(&sync_merge, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; @@ -492,8 +493,8 @@ static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl) return -ENOMEM; if (copy_from_user(sync_objs, - (void *)sync_merge.sync_objs, - sizeof(uint32_t) * sync_merge.num_objs)) { + u64_to_user_ptr(sync_merge.sync_objs), + sizeof(uint32_t) * sync_merge.num_objs)) { kfree(sync_objs); return -EFAULT; } @@ -505,7 +506,8 @@ static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl) &sync_merge.merged); if (!result) - if (copy_to_user((void *)k_ioctl->ioctl_ptr, + if (copy_to_user( + u64_to_user_ptr(k_ioctl->ioctl_ptr), &sync_merge, k_ioctl->size)) { kfree(sync_objs); @@ -528,7 +530,7 @@ static int cam_sync_handle_wait(struct cam_private_ioctl_arg *k_ioctl) return -EINVAL; if (copy_from_user(&sync_wait, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; @@ -549,7 +551,7 @@ static int cam_sync_handle_destroy(struct cam_private_ioctl_arg *k_ioctl) return -EINVAL; if (copy_from_user(&sync_create, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; @@ -573,7 +575,7 @@ static int cam_sync_handle_register_user_payload( return -EINVAL; if (copy_from_user(&userpayload_info, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; @@ -654,7 +656,7 @@ static int cam_sync_handle_deregister_user_payload( } if (copy_from_user(&userpayload_info, - (void *)k_ioctl->ioctl_ptr, + u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h index 3e1281b62567..47d441fe3aa1 100644 --- a/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h +++ b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h @@ -13,8 +13,14 @@ #ifndef _CAM_COMMON_UTIL_H_ #define _CAM_COMMON_UTIL_H_ +#include <linux/types.h> +#include <linux/kernel.h> + #define CAM_BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift) +#define PTR_TO_U64(ptr) ((uint64_t)(uintptr_t)ptr) +#define U64_TO_PTR(ptr) ((void *)(uintptr_t)ptr) + /** * cam_common_util_get_string_index() * diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c index a88ccdb93641..66a4487af172 100644 --- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c +++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c @@ -21,7 +21,7 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr, size_t *len) { int rc = 0; - uint64_t kmd_buf_addr = 0; + uintptr_t kmd_buf_addr = 0; rc = cam_mem_get_cpu_buf(handle, &kmd_buf_addr, len); if (rc) { @@ -30,7 +30,7 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr, if (kmd_buf_addr && *len) { *buf_addr = (uint32_t *)kmd_buf_addr; } else { - CAM_ERR(CAM_UTIL, "Invalid addr and length :%ld", *len); + CAM_ERR(CAM_UTIL, "Invalid addr and length :%zd", *len); rc = -ENOMEM; } } @@ -101,7 +101,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet, return rc; if (len < cmd_desc->size) { - CAM_ERR(CAM_UTIL, "invalid memory len:%ld and cmd desc size:%d", + CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d", len, cmd_desc->size); return -EINVAL; } @@ -128,7 +128,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet, { struct cam_patch_desc *patch_desc = NULL; dma_addr_t iova_addr; - uint64_t cpu_addr; + uintptr_t cpu_addr; uint32_t temp; uint32_t *dst_cpu_addr; uint32_t *src_buf_iova_addr; @@ -209,7 +209,7 @@ int cam_packet_util_process_generic_cmd_buffer( cam_packet_generic_blob_handler blob_handler_cb, void *user_data) { int rc; - uint64_t cpu_addr; + uintptr_t cpu_addr; size_t buf_size; uint32_t *blob_ptr; uint32_t blob_type, blob_size, blob_block_size, len_read; @@ -233,7 +233,8 @@ int cam_packet_util_process_generic_cmd_buffer( return rc; } - blob_ptr = (uint32_t *)((uint8_t *)cpu_addr + cmd_buf->offset); + blob_ptr = (uint32_t *)(((uint8_t *)cpu_addr) + + cmd_buf->offset); CAM_DBG(CAM_UTIL, "GenericCmdBuffer cpuaddr=%pK, blobptr=%pK, len=%d", diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index eaa06deb0e32..e522c829d47a 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -1172,7 +1172,7 @@ static int __iface_cmdq_write_relaxed(struct venus_hfi_device *device, __strict_check(device); if (!__core_in_valid_state(device)) { - dprintk(VIDC_DBG, "%s - fw not in init state\n", __func__); + dprintk(VIDC_ERR, "%s - fw not in init state\n", __func__); result = -EINVAL; goto err_q_null; } @@ -2901,8 +2901,6 @@ static void __process_sys_error(struct venus_hfi_device *device) { struct hfi_sfr_struct *vsfr = NULL; - __set_state(device, VENUS_STATE_DEINIT); - if (__halt_axi(device)) dprintk(VIDC_WARN, "Failed to halt AXI after SYS_ERROR\n"); @@ -3160,6 +3158,10 @@ static int __response_handler(struct venus_hfi_device *device) "Too many packets in message queue to handle at once, deferring read\n"); break; } + + /* do not read packets after sys error packet */ + if (info->response_type == HAL_SYS_ERROR) + break; } if (requeue_pm_work && device->res->sw_power_collapsible) { diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index e6d91605905e..e04a24a363ef 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -182,6 +182,7 @@ struct qseecom_registered_listener_list { size_t sb_length; struct ion_handle *ihandle; /* Retrieve phy addr */ wait_queue_head_t rcv_req_wq; + /* rcv_req_flag: -1: not ready; 0: ready and empty; 1: received req */ int rcv_req_flag; int send_resp_flag; bool listener_in_use; @@ -199,6 +200,7 @@ struct qseecom_registered_app_list { char app_name[MAX_APP_NAME_SIZE]; u32 app_arch; bool app_blocked; + u32 check_block; u32 blocked_on_listener_id; }; @@ -1190,9 +1192,10 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, rcvd_lstnr.sb_size)) return -EFAULT; - data->listener.id = 0; + data->listener.id = rcvd_lstnr.listener_id; if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) { - pr_err("Service is not unique and is already registered\n"); + pr_err("Service %d is not unique and failed to register\n", + rcvd_lstnr.listener_id); data->released = true; return -EBUSY; } @@ -1201,18 +1204,18 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, if (!new_entry) return -ENOMEM; memcpy(&new_entry->svc, &rcvd_lstnr, sizeof(rcvd_lstnr)); - new_entry->rcv_req_flag = 0; + new_entry->rcv_req_flag = -1; new_entry->svc.listener_id = rcvd_lstnr.listener_id; new_entry->sb_length = rcvd_lstnr.sb_size; new_entry->user_virt_sb_base = rcvd_lstnr.virt_sb_base; if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) { - pr_err("qseecom_set_sb_memoryfailed\n"); + pr_err("qseecom_set_sb_memory failed for listener %d, size %d\n", + rcvd_lstnr.listener_id, rcvd_lstnr.sb_size); kzfree(new_entry); return -ENOMEM; } - data->listener.id = rcvd_lstnr.listener_id; init_waitqueue_head(&new_entry->rcv_req_wq); init_waitqueue_head(&new_entry->listener_block_app_wq); new_entry->send_resp_flag = 0; @@ -1221,6 +1224,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head); spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags); + pr_warn("Service %d is registered\n", rcvd_lstnr.listener_id); return ret; } @@ -1244,13 +1248,17 @@ static void __qseecom_listener_abort_all(int abort) static int qseecom_unregister_listener(struct qseecom_dev_handle *data) { int ret = 0; - unsigned long flags; - uint32_t unmap_mem = 0; struct qseecom_register_listener_ireq req; struct qseecom_registered_listener_list *ptr_svc = NULL; struct qseecom_command_scm_resp resp; struct ion_handle *ihandle = NULL; /* Retrieve phy addr */ + ptr_svc = __qseecom_find_svc(data->listener.id); + if (!ptr_svc) { + pr_err("Unregiser invalid listener ID %d\n", data->listener.id); + return -ENODATA; + } + req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER; req.listener_id = data->listener.id; resp.result = QSEOS_RESULT_INCOMPLETE; @@ -1260,59 +1268,41 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data) if (ret) { pr_err("scm_call() failed with err: %d (lstnr id=%d)\n", ret, data->listener.id); - return ret; + goto exit; } if (resp.result != QSEOS_RESULT_SUCCESS) { pr_err("Failed resp.result=%d,(lstnr id=%d)\n", resp.result, data->listener.id); - return -EPERM; + ret = -EPERM; + goto exit; } data->abort = 1; - spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags); - list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head, - list) { - if (ptr_svc->svc.listener_id == data->listener.id) { - ptr_svc->abort = 1; - wake_up_all(&ptr_svc->rcv_req_wq); - break; - } - } - spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags); + ptr_svc->abort = 1; + wake_up_all(&ptr_svc->rcv_req_wq); while (atomic_read(&data->ioctl_count) > 1) { if (wait_event_freezable(data->abort_wq, atomic_read(&data->ioctl_count) <= 1)) { pr_err("Interrupted from abort\n"); ret = -ERESTARTSYS; - return ret; - } - } - - spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags); - list_for_each_entry(ptr_svc, - &qseecom.registered_listener_list_head, list) { - if (ptr_svc->svc.listener_id == data->listener.id) { - if (ptr_svc->sb_virt) { - unmap_mem = 1; - ihandle = ptr_svc->ihandle; - } - list_del(&ptr_svc->list); - kzfree(ptr_svc); - break; } } - spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags); - /* Unmap the memory */ - if (unmap_mem) { +exit: + if (ptr_svc->sb_virt) { + ihandle = ptr_svc->ihandle; if (!IS_ERR_OR_NULL(ihandle)) { ion_unmap_kernel(qseecom.ion_clnt, ihandle); ion_free(qseecom.ion_clnt, ihandle); } } + list_del(&ptr_svc->list); + kzfree(ptr_svc); + data->released = true; + pr_warn("Service %d is unregistered\n", data->listener.id); return ret; } @@ -1650,6 +1640,12 @@ static void __qseecom_clean_listener_sglistinfo( } } +static int __is_listener_rcv_wq_not_ready( + struct qseecom_registered_listener_list *ptr_svc) +{ + return ptr_svc->rcv_req_flag == -1; +} + static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) { @@ -1667,6 +1663,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, void *cmd_buf = NULL; size_t cmd_len; struct sglist_info *table = NULL; + bool not_ready = false; while (resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1678,6 +1675,10 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head, list) { if (ptr_svc->svc.listener_id == lstnr) { + if (__is_listener_rcv_wq_not_ready(ptr_svc)) { + not_ready = true; + break; + } ptr_svc->listener_in_use = true; ptr_svc->rcv_req_flag = 1; wake_up_interruptible(&ptr_svc->rcv_req_wq); @@ -1717,6 +1718,16 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, status = QSEOS_RESULT_FAILURE; goto err_resp; } + + if (not_ready) { + pr_err("Service %d is not ready to receive request\n", + lstnr); + rc = -ENOENT; + status = QSEOS_RESULT_FAILURE; + goto err_resp; + + } + pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n"); /* initialize the new signal mask with all signals*/ @@ -1978,6 +1989,7 @@ static int __qseecom_reentrancy_process_incomplete_cmd( void *cmd_buf = NULL; size_t cmd_len; struct sglist_info *table = NULL; + bool not_ready = false; while (ret == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1989,6 +2001,10 @@ static int __qseecom_reentrancy_process_incomplete_cmd( list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head, list) { if (ptr_svc->svc.listener_id == lstnr) { + if (__is_listener_rcv_wq_not_ready(ptr_svc)) { + not_ready = true; + break; + } ptr_svc->listener_in_use = true; ptr_svc->rcv_req_flag = 1; wake_up_interruptible(&ptr_svc->rcv_req_wq); @@ -2028,6 +2044,16 @@ static int __qseecom_reentrancy_process_incomplete_cmd( status = QSEOS_RESULT_FAILURE; goto err_resp; } + + if (not_ready) { + pr_err("Service %d is not ready to receive request\n", + lstnr); + rc = -ENOENT; + status = QSEOS_RESULT_FAILURE; + goto err_resp; + + } + pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n"); /* initialize the new signal mask with all signals*/ @@ -2203,6 +2229,7 @@ static void __qseecom_reentrancy_check_if_this_app_blocked( sigset_t new_sigset, old_sigset; if (qseecom.qsee_reentrancy_support) { + ptr_app->check_block++; while (ptr_app->app_blocked || qseecom.app_block_ref_cnt > 1) { /* thread sleep until this app unblocked */ sigfillset(&new_sigset); @@ -2217,6 +2244,7 @@ static void __qseecom_reentrancy_check_if_this_app_blocked( mutex_lock(&app_access_lock); sigprocmask(SIG_SETMASK, &old_sigset, NULL); } + ptr_app->check_block--; } } @@ -2485,6 +2513,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) MAX_APP_NAME_SIZE); entry->app_blocked = false; entry->blocked_on_listener_id = 0; + entry->check_block = 0; /* Deallocate the handle */ if (!IS_ERR_OR_NULL(ihandle)) @@ -2595,7 +2624,8 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data, if (!strcmp((void *)ptr_app->app_name, (void *)data->client.app_name)) { found_app = true; - if (ptr_app->app_blocked) + if (ptr_app->app_blocked || + ptr_app->check_block) app_crash = false; if (app_crash || ptr_app->ref_cnt == 1) unload = true; @@ -3831,7 +3861,7 @@ static int __qseecom_listener_has_rcvd_req(struct qseecom_dev_handle *data, { int ret; - ret = (svc->rcv_req_flag != 0); + ret = (svc->rcv_req_flag == 1); return ret || data->abort || svc->abort; } @@ -3846,13 +3876,17 @@ static int qseecom_receive_req(struct qseecom_dev_handle *data) return -ENODATA; } + if (this_lstnr->rcv_req_flag == -1) + this_lstnr->rcv_req_flag = 0; + while (1) { if (wait_event_freezable(this_lstnr->rcv_req_wq, __qseecom_listener_has_rcvd_req(data, this_lstnr))) { - pr_debug("Interrupted: exiting Listener Service = %d\n", + pr_warn("Interrupted: exiting Listener Service = %d\n", (uint32_t)data->listener.id); /* woken up for different reason */ + this_lstnr->rcv_req_flag = -1; return -ERESTARTSYS; } @@ -4535,6 +4569,7 @@ int qseecom_start_app(struct qseecom_handle **handle, entry->app_arch = app_arch; entry->app_blocked = false; entry->blocked_on_listener_id = 0; + entry->check_block = 0; spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_add_tail(&entry->list, &qseecom.registered_app_list_head); spin_unlock_irqrestore(&qseecom.registered_app_list_lock, @@ -5449,6 +5484,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, MAX_APP_NAME_SIZE); entry->app_blocked = false; entry->blocked_on_listener_id = 0; + entry->check_block = 0; spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_add_tail(&entry->list, @@ -7681,6 +7717,7 @@ static int qseecom_release(struct inode *inode, struct file *file) data->type, data->mode, data); switch (data->type) { case QSEECOM_LISTENER_SERVICE: + pr_warn("release lsnr svc %d\n", data->listener.id); __qseecom_listener_abort_all(1); mutex_lock(&app_access_lock); ret = qseecom_unregister_listener(data); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c index c90561d0cdfc..b7606775bdb8 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c @@ -89,6 +89,7 @@ const char *ipa_event_name[] = { __stringify(DEL_L2TP_VLAN_MAPPING), __stringify(IPA_PER_CLIENT_STATS_CONNECT_EVENT), __stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT), + __stringify(WLAN_FWR_SSR_BEFORE_SHUTDOWN), }; const char *ipa_hdr_l2_type_name[] = { diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c index 579ab1ce40d0..81e98f2c8697 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c @@ -35,6 +35,13 @@ enum nat_table_type { #define NAT_TABLE_ENTRY_SIZE_BYTE 32 #define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 +/* + * Max NAT table entries is limited 1000 entries. + * Limit the memory size required by user to prevent kernel memory starvation + */ +#define IPA_TABLE_MAX_ENTRIES 1000 +#define MAX_ALLOC_NAT_SIZE (IPA_TABLE_MAX_ENTRIES * NAT_TABLE_ENTRY_SIZE_BYTE) + static int ipa_nat_vma_fault_remap( struct vm_area_struct *vma, struct vm_fault *vmf) { @@ -270,6 +277,13 @@ int ipa2_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) goto bail; } + if (mem->size > MAX_ALLOC_NAT_SIZE) { + IPAERR("Trying allocate more size = %zu, Max allowed = %d\n", + mem->size, MAX_ALLOC_NAT_SIZE); + result = -EPERM; + goto bail; + } + if (mem->size <= 0 || nat_ctx->is_dev_init == true) { IPAERR_RL("Invalid Parameters or device is already init\n"); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index 41b1783b9f64..f041be906446 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -1325,6 +1325,8 @@ int ipa2_reset_rt(enum ipa_ip_type ip) struct ipa_rt_entry *rule_next; struct ipa_rt_tbl_set *rset; u32 apps_start_idx; + struct ipa_hdr_entry *hdr_entry; + struct ipa_hdr_proc_ctx_entry *hdr_proc_entry; int id; if (ip >= IPA_IP_MAX) { @@ -1369,6 +1371,27 @@ int ipa2_reset_rt(enum ipa_ip_type ip) continue; list_del(&rule->link); + if (rule->hdr) { + hdr_entry = ipa_id_find( + rule->rule.hdr_hdl); + if (!hdr_entry || + hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL( + "Header already deleted\n"); + return -EINVAL; + } + } else if (rule->proc_ctx) { + hdr_proc_entry = + ipa_id_find( + rule->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != + IPA_PROC_HDR_COOKIE) { + IPAERR_RL( + "Proc entry already deleted\n"); + return -EINVAL; + } + } tbl->rule_cnt--; if (rule->hdr) __ipa_release_hdr(rule->hdr->id); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index edc5c2cb3d08..752658cb9317 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -73,6 +73,7 @@ const char *ipa3_event_name[] = { __stringify(DEL_L2TP_VLAN_MAPPING), __stringify(IPA_PER_CLIENT_STATS_CONNECT_EVENT), __stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT), + __stringify(WLAN_FWR_SSR_BEFORE_SHUTDOWN), }; const char *ipa3_hdr_l2_type_name[] = { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index dacccbc4d033..d17f8098552c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -1046,13 +1046,12 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, goto error; } /* - * do not allow any rules to be added at end of the "default" routing - * tables + * do not allow any rule to be added at "default" routing + * table */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && - (tbl->rule_cnt > 0) && (at_rear != 0)) { - IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d at_rear=%d" - , tbl->rule_cnt, at_rear); + (tbl->rule_cnt > 0)) { + IPAERR_RL("cannot add rules to default rt table\n"); goto error; } @@ -1258,13 +1257,12 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) } /* - * do not allow any rules to be added at end of the "default" routing - * tables + * do not allow any rule to be added at "default" routing + * table */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && - (&entry->link == tbl->head_rt_rule_list.prev)) { - IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d\n", - tbl->rule_cnt); + (tbl->rule_cnt > 0)) { + IPAERR_RL("cannot add rules to default rt table\n"); ret = -EINVAL; goto bail; } @@ -1470,6 +1468,8 @@ int ipa3_reset_rt(enum ipa_ip_type ip) struct ipa3_rt_entry *rule; struct ipa3_rt_entry *rule_next; struct ipa3_rt_tbl_set *rset; + struct ipa3_hdr_entry *hdr_entry; + struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; u32 apps_start_idx; int id; @@ -1513,13 +1513,35 @@ int ipa3_reset_rt(enum ipa_ip_type ip) continue; list_del(&rule->link); + if (rule->hdr) { + hdr_entry = ipa3_id_find( + rule->rule.hdr_hdl); + if (!hdr_entry || + hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL( + "Header already deleted\n"); + return -EINVAL; + } + } else if (rule->proc_ctx) { + hdr_proc_entry = + ipa3_id_find( + rule->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != + IPA_PROC_HDR_COOKIE) { + IPAERR_RL( + "Proc entry already deleted\n"); + return -EINVAL; + } + } tbl->rule_cnt--; if (rule->hdr) __ipa3_release_hdr(rule->hdr->id); else if (rule->proc_ctx) __ipa3_release_hdr_proc_ctx(rule->proc_ctx->id); rule->cookie = 0; - idr_remove(tbl->rule_ids, rule->rule_id); + if (!rule->rule_id_valid) + idr_remove(tbl->rule_ids, rule->rule_id); id = rule->id; kmem_cache_free(ipa3_ctx->rt_rule_cache, rule); @@ -1697,6 +1719,10 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } + if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) { + IPAERR_RL("Default tbl rule cannot be modified\n"); + return -EINVAL; + } /* Adding check to confirm still * header entry present in header table or not */ diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c index 8ac7a3b3c719..05a8c66d57aa 100644 --- a/drivers/platform/msm/sps/sps.c +++ b/drivers/platform/msm/sps/sps.c @@ -2334,8 +2334,11 @@ int sps_deregister_bam_device(unsigned long dev_handle) mutex_lock(&bam->lock); sps_bam_device_de_init(bam); mutex_unlock(&bam->lock); + ipc_log_context_destroy(bam->ipc_log0); ipc_log_context_destroy(bam->ipc_log1); ipc_log_context_destroy(bam->ipc_log2); + ipc_log_context_destroy(bam->ipc_log3); + ipc_log_context_destroy(bam->ipc_log4); if (bam->props.virt_size) (void)iounmap(bam->props.virt_addr); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index d284d30910fc..01680c8a9498 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -3094,7 +3094,9 @@ static int smblib_cc2_sink_removal_exit(struct smb_charger *chg) return 0; chg->cc2_detach_wa_active = false; + chg->in_chg_lock = true; cancel_work_sync(&chg->rdstd_cc2_detach_work); + chg->in_chg_lock = false; smblib_reg_block_restore(chg, cc2_detach_settings); return 0; } @@ -4641,7 +4643,6 @@ static void rdstd_cc2_detach_work(struct work_struct *work) { int rc; u8 stat4, stat5; - bool lock = false; struct smb_charger *chg = container_of(work, struct smb_charger, rdstd_cc2_detach_work); @@ -4710,22 +4711,15 @@ static void rdstd_cc2_detach_work(struct work_struct *work) * during pd_hard_reset from the function smblib_cc2_sink_removal_exit * which is called in the same lock context that we try to acquire in * this work routine. - * Check if this work is running during pd_hard_reset and use trylock - * instead of mutex_lock to prevent any deadlock if mutext is already - * held. + * Check if this work is running during pd_hard_reset and skip holding + * mutex if lock is already held. */ - if (chg->pd_hard_reset) { - if (mutex_trylock(&chg->lock)) - lock = true; - } else { + if (!chg->in_chg_lock) mutex_lock(&chg->lock); - lock = true; - } - smblib_usb_typec_change(chg); - - if (lock) + if (!chg->in_chg_lock) mutex_unlock(&chg->lock); + return; rerun: diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index d6189db72e3a..233ab50f4a79 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -349,6 +349,7 @@ struct smb_charger { bool use_extcon; bool otg_present; bool is_audio_adapter; + bool in_chg_lock; /* workaround flag */ u32 wa_flags; diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 1ec6202bec8d..e8d41f1f274f 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -727,6 +727,11 @@ static int ufs_qcom_config_vreg(struct device *dev, reg = vreg->reg; if (regulator_count_voltages(reg) > 0) { + uA_load = on ? vreg->max_uA : 0; + ret = regulator_set_load(vreg->reg, uA_load); + if (ret) + goto out; + min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); if (ret) { @@ -734,11 +739,6 @@ static int ufs_qcom_config_vreg(struct device *dev, __func__, vreg->name, ret); goto out; } - - uA_load = on ? vreg->max_uA : 0; - ret = regulator_set_load(vreg->reg, uA_load); - if (ret) - goto out; } out: return ret; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index acd170d04db6..ce411897c886 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3382,6 +3382,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, int tag; struct completion wait; unsigned long flags; + bool has_read_lock = false; /* * May get invoked from shutdown and IOCTL contexts. @@ -3389,8 +3390,10 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, * In error recovery context, it may come with lock acquired. */ - if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) + if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) { down_read(&hba->lock); + has_read_lock = true; + } /* * Get free slot, sleep if slots are unavailable. @@ -3423,7 +3426,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, out_put_tag: ufshcd_put_dev_cmd_tag(hba, tag); wake_up(&hba->dev_cmd.tag_wq); - if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) + if (has_read_lock) up_read(&hba->lock); return err; } @@ -7431,7 +7434,7 @@ static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) dev_err(hba->dev, "%s: Failed reading power descriptor.len = %d ret = %d", __func__, buff_len, ret); - return; + goto out; } icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf, @@ -7445,6 +7448,9 @@ static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) dev_err(hba->dev, "%s: Failed configuring bActiveICCLevel = %d ret = %d", __func__, icc_level, ret); + +out: + kfree(desc_buf); } /** @@ -7802,7 +7808,7 @@ out: static int ufs_read_device_desc_data(struct ufs_hba *hba) { - int err; + int err = 0; u8 *desc_buf = NULL; if (hba->desc_size.dev_desc) { @@ -7816,7 +7822,7 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba) } err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc); if (err) - return err; + goto out; /* * getting vendor (manufacturerID) and Bank Index in big endian @@ -7828,8 +7834,9 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba) hba->dev_info.b_device_sub_class = desc_buf[DEVICE_DESC_PARAM_DEVICE_SUB_CLASS]; hba->dev_info.i_product_name = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; - - return 0; +out: + kfree(desc_buf); + return err; } static void ufshcd_init_desc_sizes(struct ufs_hba *hba) @@ -8528,6 +8535,11 @@ static int ufshcd_config_vreg(struct device *dev, BUG_ON(!vreg); if (regulator_count_voltages(reg) > 0) { + uA_load = on ? vreg->max_uA : 0; + ret = ufshcd_config_vreg_load(dev, vreg, uA_load); + if (ret) + goto out; + min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); if (ret) { @@ -8535,11 +8547,6 @@ static int ufshcd_config_vreg(struct device *dev, __func__, name, ret); goto out; } - - uA_load = on ? vreg->max_uA : 0; - ret = ufshcd_config_vreg_load(dev, vreg, uA_load); - if (ret) - goto out; } out: return ret; diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 4aab90904f07..161257b17446 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -3125,6 +3125,8 @@ EXPORT_SYMBOL(icnss_disable_irq); int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info) { + char *fw_build_timestamp = NULL; + if (!penv || !dev) { icnss_pr_err("Platform driver not initialized\n"); return -EINVAL; @@ -3137,6 +3139,8 @@ int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info) info->board_id = penv->board_info.board_id; info->soc_id = penv->soc_info.soc_id; info->fw_version = penv->fw_version_info.fw_version; + fw_build_timestamp = penv->fw_version_info.fw_build_timestamp; + fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01] = '\0'; strlcpy(info->fw_build_timestamp, penv->fw_version_info.fw_build_timestamp, QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1); diff --git a/drivers/soc/qcom/ipc_router_glink_xprt.c b/drivers/soc/qcom/ipc_router_glink_xprt.c index cef3c7716e8f..ada7d5efbc6c 100644 --- a/drivers/soc/qcom/ipc_router_glink_xprt.c +++ b/drivers/soc/qcom/ipc_router_glink_xprt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -31,6 +31,7 @@ static int ipc_router_glink_xprt_debug_mask; module_param_named(debug_mask, ipc_router_glink_xprt_debug_mask, int, 0664); +#define IPCRTR_INTENT_REQ_TIMEOUT_MS 5000 #if defined(DEBUG) #define D(x...) do { \ if (ipc_router_glink_xprt_debug_mask) \ @@ -602,6 +603,7 @@ static void glink_xprt_ch_open(struct ipc_router_glink_xprt *glink_xprtp) open_cfg.notify_state = glink_xprt_notify_state; open_cfg.notify_rx_intent_req = glink_xprt_notify_rx_intent_req; open_cfg.priv = glink_xprtp; + open_cfg.rx_intent_req_timeout_ms = IPCRTR_INTENT_REQ_TIMEOUT_MS; glink_xprtp->pil = msm_ipc_load_subsystem(glink_xprtp); glink_xprtp->ch_hndl = glink_open(&open_cfg); diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c index 9cd9309fd433..d15a6048d530 100644 --- a/drivers/soc/qcom/pil-msa.c +++ b/drivers/soc/qcom/pil-msa.c @@ -827,7 +827,7 @@ int pil_mss_debug_reset(struct pil_desc *pil) * complete before returning */ pr_info("Minidump: waiting encryption to complete\n"); - msleep(10000); + msleep(13000); if (pil->minidump) { writel_relaxed(0x2, drv->reg_base + QDSP6SS_NMI_CFG); /* Let write complete before proceeding */ diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index f7902e18b05c..06002485070e 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -258,21 +258,28 @@ existing: switch (state) { case RPMH_ACTIVE_ONLY_STATE: case RPMH_AWAKE_STATE: - if (req->sleep_val != UINT_MAX) + if (req->sleep_val != UINT_MAX) { req->wake_val = cmd->data; + rpm->dirty = true; + } break; case RPMH_WAKE_ONLY_STATE: - req->wake_val = cmd->data; + if (req->wake_val != cmd->data) { + req->wake_val = cmd->data; + rpm->dirty = true; + } break; case RPMH_SLEEP_STATE: - req->sleep_val = cmd->data; + if (req->sleep_val != cmd->data) { + req->sleep_val = cmd->data; + rpm->dirty = true; + } break; default: break; }; unlock: - rpm->dirty = true; spin_unlock_irqrestore(&rpm->lock, flags); return req; diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 71e076badc9a..2112d14f5945 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -1173,12 +1173,12 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas) mas->rx_rem_bytes -= rx_bytes; } -static irqreturn_t geni_spi_irq(int irq, void *dev) +static irqreturn_t geni_spi_irq(int irq, void *data) { - struct spi_geni_master *mas = dev; + struct spi_geni_master *mas = data; u32 m_irq = 0; - if (pm_runtime_status_suspended(dev)) { + if (pm_runtime_status_suspended(mas->dev)) { GENI_SE_DBG(mas->ipc, false, mas->dev, "%s: device is suspended\n", __func__); goto exit_geni_spi_irq; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 72f2b6a1b9ed..3f0ebe861e2f 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -4,7 +4,7 @@ * Copyright (C) Linaro 2012 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson. * - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -390,14 +390,37 @@ out: return ret; } +static void *ion_secure_cma_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + if (!is_buffer_hlos_assigned(buffer)) { + pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n", + __func__); + return NULL; + } + return ion_cma_map_kernel(heap, buffer); +} + +static int ion_secure_cma_map_user(struct ion_heap *mapper, + struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + if (!is_buffer_hlos_assigned(buffer)) { + pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n", + __func__); + return -EINVAL; + } + return ion_cma_mmap(mapper, buffer, vma); +} + static struct ion_heap_ops ion_secure_cma_ops = { .allocate = ion_secure_cma_allocate, .free = ion_secure_cma_free, .map_dma = ion_cma_heap_map_dma, .unmap_dma = ion_cma_heap_unmap_dma, .phys = ion_cma_phys, - .map_user = ion_cma_mmap, - .map_kernel = ion_cma_map_kernel, + .map_user = ion_secure_cma_map_user, + .map_kernel = ion_secure_cma_map_kernel, .unmap_kernel = ion_cma_unmap_kernel, .print_debug = ion_cma_print_debug, }; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 37b6ad4235f5..eb7c61b8d375 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -102,6 +102,11 @@ size_t ion_system_heap_secure_page_pool_total(struct ion_heap *heap, return total << PAGE_SHIFT; } +static int ion_heap_is_system_heap_type(enum ion_heap_type type) +{ + return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM); +} + static struct page *alloc_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, unsigned long order, @@ -357,6 +362,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap, int vmid = get_secure_vmid(buffer->flags); struct device *dev = heap->priv; + if (ion_heap_is_system_heap_type(buffer->heap->type) && + is_secure_vmid_valid(vmid)) { + pr_info("%s: System heap doesn't support secure allocations\n", + __func__); + return -EINVAL; + } + if (align > PAGE_SIZE) return -EINVAL; diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c index 5bf484beed96..cf86ea21838a 100644 --- a/drivers/staging/android/ion/ion_system_secure_heap.c +++ b/drivers/staging/android/ion/ion_system_secure_heap.c @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016,2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -171,14 +171,15 @@ out: sys_heap->ops->free(&buffer); } -static void process_one_shrink(struct ion_heap *sys_heap, +static void process_one_shrink(struct ion_system_secure_heap *secure_heap, + struct ion_heap *sys_heap, struct prefetch_info *info) { struct ion_buffer buffer; size_t pool_size, size; int ret; - buffer.heap = sys_heap; + buffer.heap = &secure_heap->heap; buffer.flags = info->vmid; pool_size = ion_system_heap_secure_page_pool_total(sys_heap, @@ -193,6 +194,7 @@ static void process_one_shrink(struct ion_heap *sys_heap, } buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE; + buffer.heap = sys_heap; sys_heap->ops->free(&buffer); } @@ -212,7 +214,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work) spin_unlock_irqrestore(&secure_heap->work_lock, flags); if (info->shrink) - process_one_shrink(sys_heap, info); + process_one_shrink(secure_heap, sys_heap, info); else process_one_prefetch(sys_heap, info); diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 7e4e7ceb25a6..257cb88b7edc 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -675,6 +675,11 @@ static void ipa_work_handler(struct work_struct *w) log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY", __func__); } else if (event == EVT_CONNECTED) { + if (peek_event(d_port) == EVT_SUSPEND) { + log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND", + __func__); + break; + } ipa_data_path_enable(d_port); d_port->sm_state = STATE_CONNECTED; log_event_dbg("%s: ST_CON_IN_PROG_EVT_CON %d", diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7198328253cd..1cfe036e061b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3655,6 +3655,7 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); } + virt_dev->udev = NULL; spin_lock_irqsave(&xhci->lock, flags); /* Don't disable the slot if the host controller is dead. */ state = readl(&xhci->op_regs->status); diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 5ac0b0bbb0ec..399531bc1f6f 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -115,7 +115,11 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, goto out; /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file))); + saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data); + if (!saved_cred) { + err = -ENOMEM; + goto out; + } if (lower_file->f_op->unlocked_ioctl) err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); @@ -124,7 +128,7 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, if (!err) sdcardfs_copy_and_fix_attrs(file_inode(file), file_inode(lower_file)); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out: return err; } @@ -146,12 +150,16 @@ static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd, goto out; /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file))); + saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data); + if (!saved_cred) { + err = -ENOMEM; + goto out; + } if (lower_file->f_op->compat_ioctl) err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out: return err; } @@ -238,7 +246,11 @@ static int sdcardfs_open(struct inode *inode, struct file *file) } /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(inode)); + saved_cred = override_fsids(sbi, SDCARDFS_I(inode)->data); + if (!saved_cred) { + err = -ENOMEM; + goto out_err; + } file->private_data = kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); @@ -268,7 +280,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode)); out_revert_cred: - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_err: dput(parent); return err; diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 8ed0ea17de5a..4af7c87c40ac 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -22,7 +22,6 @@ #include <linux/fs_struct.h> #include <linux/ratelimit.h> -/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_data *data) { @@ -50,7 +49,6 @@ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, return old_cred; } -/* Do not directly use this function, use REVERT_CRED() instead. */ void revert_fsids(const struct cred *old_cred) { const struct cred *cur_cred; @@ -78,7 +76,10 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; @@ -95,8 +96,11 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, err = -ENOMEM; goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); + err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); if (err) goto out; @@ -110,58 +114,18 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, fixup_lower_ownership(dentry, dentry->d_name.name); out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); free_fs_struct(copied_fs); out_unlock: unlock_dir(lower_parent_dentry); sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } -#if 0 -static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) -{ - struct dentry *lower_old_dentry; - struct dentry *lower_new_dentry; - struct dentry *lower_dir_dentry; - u64 file_size_save; - int err; - struct path lower_old_path, lower_new_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - file_size_save = i_size_read(d_inode(old_dentry)); - sdcardfs_get_lower_path(old_dentry, &lower_old_path); - sdcardfs_get_lower_path(new_dentry, &lower_new_path); - lower_old_dentry = lower_old_path.dentry; - lower_new_dentry = lower_new_path.dentry; - lower_dir_dentry = lock_parent(lower_new_dentry); - - err = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry), - lower_new_dentry, NULL); - if (err || !d_inode(lower_new_dentry)) - goto out; - - err = sdcardfs_interpose(new_dentry, dir->i_sb, &lower_new_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, d_inode(lower_new_dentry)); - fsstack_copy_inode_size(dir, d_inode(lower_new_dentry)); - set_nlink(d_inode(old_dentry), - sdcardfs_lower_inode(d_inode(old_dentry))->i_nlink); - i_size_write(d_inode(new_dentry), file_size_save); -out: - unlock_dir(lower_dir_dentry); - sdcardfs_put_lower_path(old_dentry, &lower_old_path); - sdcardfs_put_lower_path(new_dentry, &lower_new_path); - REVERT_CRED(); - return err; -} -#endif - static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) { int err; @@ -178,7 +142,10 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; @@ -209,43 +176,11 @@ out: unlock_dir(lower_dir_dentry); dput(lower_dentry); sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } -#if 0 -static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = vfs_symlink(d_inode(lower_parent_dentry), lower_dentry, symname); - if (err) - goto out; - err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); - -out: - unlock_dir(lower_parent_dentry); - sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(); - return err; -} -#endif - static int touch(char *abs_path, mode_t mode) { struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode); @@ -286,7 +221,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; /* check disk space */ if (!check_min_free_space(dentry, 0, 1)) { @@ -312,8 +250,11 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode unlock_dir(lower_parent_dentry); goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); + err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); if (err) { @@ -362,23 +303,34 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode if (make_nomedia_in_obb || ((pd->perm == PERM_ANDROID) && (qstr_case_eq(&dentry->d_name, &q_data)))) { - REVERT_CRED(saved_cred); - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry))); + revert_fsids(saved_cred); + saved_cred = override_fsids(sbi, + SDCARDFS_I(d_inode(dentry))->data); + if (!saved_cred) { + pr_err("sdcardfs: failed to set up .nomedia in %s: %d\n", + lower_path.dentry->d_name.name, + -ENOMEM); + goto out; + } set_fs_pwd(current->fs, &lower_path); touch_err = touch(".nomedia", 0664); if (touch_err) { pr_err("sdcardfs: failed to create .nomedia in %s: %d\n", - lower_path.dentry->d_name.name, touch_err); + lower_path.dentry->d_name.name, + touch_err); goto out; } } out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); + free_fs_struct(copied_fs); out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); out_revert: - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } @@ -398,7 +350,10 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) + return -ENOMEM; /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry * the dentry on the original path should be deleted. @@ -423,44 +378,11 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) out: unlock_dir(lower_dir_dentry); sdcardfs_put_real_lower(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } -#if 0 -static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev) -{ - int err; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = vfs_mknod(d_inode(lower_parent_dentry), lower_dentry, mode, dev); - if (err) - goto out; - - err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); - -out: - unlock_dir(lower_parent_dentry); - sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(); - return err; -} -#endif - /* * The locking rules in sdcardfs_rename are complex. We could use a simpler * superblock-level name-space lock for renames and copy-ups. @@ -489,7 +411,10 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry, } /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred, SDCARDFS_I(new_dir)); + saved_cred = override_fsids(SDCARDFS_SB(old_dir->i_sb), + SDCARDFS_I(new_dir)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_real_lower(old_dentry, &lower_old_path); sdcardfs_get_lower_path(new_dentry, &lower_new_path); @@ -536,7 +461,7 @@ out: dput(lower_new_dir_dentry); sdcardfs_put_real_lower(old_dentry, &lower_old_path); sdcardfs_put_lower_path(new_dentry, &lower_new_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_eacces: return err; } @@ -653,33 +578,7 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma if (IS_POSIXACL(inode)) pr_warn("%s: This may be undefined behavior...\n", __func__); err = generic_permission(&tmp, mask); - /* XXX - * Original sdcardfs code calls inode_permission(lower_inode,.. ) - * for checking inode permission. But doing such things here seems - * duplicated work, because the functions called after this func, - * such as vfs_create, vfs_unlink, vfs_rename, and etc, - * does exactly same thing, i.e., they calls inode_permission(). - * So we just let they do the things. - * If there are any security hole, just uncomment following if block. - */ -#if 0 - if (!err) { - /* - * Permission check on lower_inode(=EXT4). - * we check it with AID_MEDIA_RW permission - */ - struct inode *lower_inode; - - OVERRIDE_CRED(SDCARDFS_SB(inode->sb)); - - lower_inode = sdcardfs_lower_inode(inode); - err = inode_permission(lower_inode, mask); - - REVERT_CRED(); - } -#endif return err; - } static int sdcardfs_setattr_wrn(struct dentry *dentry, struct iattr *ia) @@ -757,7 +656,10 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct goto out_err; /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dentry->d_sb), saved_cred, SDCARDFS_I(inode)); + saved_cred = override_fsids(SDCARDFS_SB(dentry->d_sb), + SDCARDFS_I(inode)->data); + if (!saved_cred) + return -ENOMEM; sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; @@ -816,7 +718,7 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct out: sdcardfs_put_lower_path(dentry, &lower_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_err: return err; } @@ -899,13 +801,6 @@ const struct inode_operations sdcardfs_dir_iops = { .setattr = sdcardfs_setattr_wrn, .setattr2 = sdcardfs_setattr, .getattr = sdcardfs_getattr, - /* XXX Following operations are implemented, - * but FUSE(sdcard) or FAT does not support them - * These methods are *NOT* perfectly tested. - .symlink = sdcardfs_symlink, - .link = sdcardfs_link, - .mknod = sdcardfs_mknod, - */ }; const struct inode_operations sdcardfs_main_iops = { diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index 843fcd216116..e1bff0da1925 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -428,7 +428,12 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, } /* save current_cred and override it */ - OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); + saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), + SDCARDFS_I(dir)->data); + if (!saved_cred) { + ret = ERR_PTR(-ENOMEM); + goto out_err; + } sdcardfs_get_lower_path(parent, &lower_parent_path); @@ -459,7 +464,7 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, out: sdcardfs_put_lower_path(parent, &lower_parent_path); - REVERT_CRED(saved_cred); + revert_fsids(saved_cred); out_err: dput(parent); return ret; diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index eda8e7aa6911..b2e7db857dcf 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -88,31 +88,6 @@ (x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\ } while (0) -/* OVERRIDE_CRED() and REVERT_CRED() - * OVERRIDE_CRED() - * backup original task->cred - * and modifies task->cred->fsuid/fsgid to specified value. - * REVERT_CRED() - * restore original task->cred->fsuid/fsgid. - * These two macro should be used in pair, and OVERRIDE_CRED() should be - * placed at the beginning of a function, right after variable declaration. - */ -#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info) \ - do { \ - saved_cred = override_fsids(sdcardfs_sbi, info->data); \ - if (!saved_cred) \ - return -ENOMEM; \ - } while (0) - -#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info) \ - do { \ - saved_cred = override_fsids(sdcardfs_sbi, info->data); \ - if (!saved_cred) \ - return ERR_PTR(-ENOMEM); \ - } while (0) - -#define REVERT_CRED(saved_cred) revert_fsids(saved_cred) - /* Android 5.0 support */ /* Permission mode for a specific node. Controls how file permissions diff --git a/include/net/sock.h b/include/net/sock.h index 97f8ed2202bf..76b170af1b0b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2290,4 +2290,15 @@ extern int sysctl_optmem_max; extern __u32 sysctl_wmem_default; extern __u32 sysctl_rmem_default; +/* SOCKEV Notifier Events */ +#define SOCKEV_SOCKET 0x00 +#define SOCKEV_BIND 0x01 +#define SOCKEV_LISTEN 0x02 +#define SOCKEV_ACCEPT 0x03 +#define SOCKEV_CONNECT 0x04 +#define SOCKEV_SHUTDOWN 0x05 + +int sockev_register_notify(struct notifier_block *nb); +int sockev_unregister_notify(struct notifier_block *nb); + #endif /* _SOCK_H */ diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index ef07f7825101..7c8a02d5286f 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -507,7 +507,13 @@ enum ipa_per_client_stats_event { IPA_PER_CLIENT_STATS_EVENT_MAX }; -#define IPA_EVENT_MAX_NUM (IPA_PER_CLIENT_STATS_EVENT_MAX) +enum ipa_wlan_fw_ssr_event { + WLAN_FWR_SSR_BEFORE_SHUTDOWN = IPA_PER_CLIENT_STATS_EVENT_MAX, + IPA_WLAN_FW_SSR_EVENT_MAX +#define IPA_WLAN_FW_SSR_EVENT_MAX IPA_WLAN_FW_SSR_EVENT_MAX +}; + +#define IPA_EVENT_MAX_NUM (IPA_WLAN_FW_SSR_EVENT_MAX) #define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM) /** diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index 841c40af4d47..ae65649964ff 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -262,6 +262,9 @@ struct cam_req_mgr_link_control { ((idx & CAM_MEM_MGR_HDL_IDX_MASK) | \ (fd << (CAM_MEM_MGR_HDL_FD_END_POS - CAM_MEM_MGR_HDL_FD_SIZE))) \ +#define GET_FD_FROM_HANDLE(hdl) \ + (hdl >> (CAM_MEM_MGR_HDL_FD_END_POS - CAM_MEM_MGR_HDL_FD_SIZE)) \ + #define CAM_MEM_MGR_GET_HDL_IDX(hdl) (hdl & CAM_MEM_MGR_HDL_IDX_MASK) #define CAM_MEM_MGR_SET_SECURE_HDL(hdl, flag) \ diff --git a/include/uapi/media/cam_sync.h b/include/uapi/media/cam_sync.h index 003c9ad5ce20..4a8781fc823d 100644 --- a/include/uapi/media/cam_sync.h +++ b/include/uapi/media/cam_sync.h @@ -117,7 +117,7 @@ struct cam_private_ioctl_arg { __u32 size; __u32 result; __u32 reserved; - __user __u64 ioctl_ptr; + __u64 ioctl_ptr; }; #define CAM_PRIVATE_IOCTL_CMD \ diff --git a/kernel/events/core.c b/kernel/events/core.c index 712ba4ea4d00..14bc686f6afa 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4275,7 +4275,7 @@ static DEFINE_SPINLOCK(zombie_list_lock); * object, it will not preserve its functionality. Once the last 'user' * gives up the object, we'll destroy the thing. */ -int perf_event_release_kernel(struct perf_event *event) +static int __perf_event_release_kernel(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; struct perf_event *child, *tmp; @@ -4286,7 +4286,7 @@ int perf_event_release_kernel(struct perf_event *event) * back online. */ #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE - if (!cpu_online(event->cpu)) { + if (event->cpu != -1 && per_cpu(is_hotplugging, event->cpu)) { if (event->state == PERF_EVENT_STATE_ZOMBIE) return 0; @@ -4403,6 +4403,17 @@ no_ctx: put_event(event); /* Must be the 'last' reference */ return 0; } + +int perf_event_release_kernel(struct perf_event *event) +{ + int ret; + + mutex_lock(&pmus_lock); + ret = __perf_event_release_kernel(event); + mutex_unlock(&pmus_lock); + + return ret; +} EXPORT_SYMBOL_GPL(perf_event_release_kernel); /* @@ -11090,7 +11101,7 @@ static void perf_event_zombie_cleanup(unsigned int cpu) * PMU expects it to be in an active state */ event->state = PERF_EVENT_STATE_ACTIVE; - perf_event_release_kernel(event); + __perf_event_release_kernel(event); spin_lock(&zombie_list_lock); } @@ -11105,6 +11116,7 @@ static int perf_event_start_swevents(unsigned int cpu) struct perf_event *event; int idx; + mutex_lock(&pmus_lock); perf_event_zombie_cleanup(cpu); idx = srcu_read_lock(&pmus_srcu); @@ -11119,6 +11131,8 @@ static int perf_event_start_swevents(unsigned int cpu) } srcu_read_unlock(&pmus_srcu, idx); per_cpu(is_hotplugging, cpu) = false; + mutex_unlock(&pmus_lock); + return 0; } @@ -11180,8 +11194,10 @@ static void perf_event_exit_cpu_context(int cpu) { } int perf_event_exit_cpu(unsigned int cpu) { + mutex_lock(&pmus_lock); per_cpu(is_hotplugging, cpu) = true; perf_event_exit_cpu_context(cpu); + mutex_unlock(&pmus_lock); return 0; } diff --git a/net/core/dst.c b/net/core/dst.c index b5de3663926f..39cc11968cf9 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -349,15 +349,8 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old) new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY; prev = cmpxchg(&dst->_metrics, old, new); - if (prev == old) { - struct dst_metrics *old_p = (struct dst_metrics *) - __DST_METRICS_PTR(old); - - if (prev & DST_METRICS_REFCOUNTED) { - if (atomic_dec_and_test(&old_p->refcnt)) - kfree(old_p); - } - } + if (prev == old) + kfree(__DST_METRICS_PTR(old)); } EXPORT_SYMBOL(__dst_destroy_metrics_generic); diff --git a/net/key/af_key.c b/net/key/af_key.c index 94bf810ad242..a30d87c5de76 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock) return 0; } -static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - gfp_t allocation, struct sock *sk) +static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation, + struct sock *sk) { int err = -ENOBUFS; - sock_hold(sk); - if (*skb2 == NULL) { - if (atomic_read(&skb->users) != 1) { - *skb2 = skb_clone(skb, allocation); - } else { - *skb2 = skb; - atomic_inc(&skb->users); - } - } - if (*skb2 != NULL) { - if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { - skb_set_owner_r(*skb2, sk); - skb_queue_tail(&sk->sk_receive_queue, *skb2); - sk->sk_data_ready(sk); - *skb2 = NULL; - err = 0; - } + if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) + return err; + + skb = skb_clone(skb, allocation); + + if (skb) { + skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk); + err = 0; } - sock_put(sk); return err; } @@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; - struct sk_buff *skb2 = NULL; int err = -ESRCH; /* XXX Do we need something like netlink_overrun? I think @@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, * socket. */ if (pfk->promisc) - pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* the exact target will be processed later */ if (sk == one_sk) @@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, continue; } - err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* Error is cleared after successful sending to at least one * registered KM */ @@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, rcu_read_unlock(); if (one_sk != NULL) - err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, allocation, one_sk); - kfree_skb(skb2); kfree_skb(skb); return err; } diff --git a/net/socket.c b/net/socket.c index a4fb47262f0b..0678601ec720 100644 --- a/net/socket.c +++ b/net/socket.c @@ -117,6 +117,8 @@ unsigned int sysctl_net_busy_poll __read_mostly; static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); +static BLOCKING_NOTIFIER_HEAD(sockev_notifier_list); + static int sock_mmap(struct file *file, struct vm_area_struct *vma); static int sock_close(struct inode *inode, struct file *file); @@ -171,6 +173,14 @@ static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; static DEFINE_PER_CPU(int, sockets_in_use); /* + * Socket Event framework helpers + */ +static void sockev_notify(unsigned long event, struct socket *sk) +{ + blocking_notifier_call_chain(&sockev_notifier_list, event, sk); +} + +/** * Support routines. * Move socket addresses back and forth across the kernel/user * divide and look after the messy bits. @@ -1255,6 +1265,9 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) if (retval < 0) goto out; + if (retval == 0) + sockev_notify(SOCKEV_SOCKET, sock); + retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); if (retval < 0) goto out_release; @@ -1400,6 +1413,8 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) &address, addrlen); } fput_light(sock->file, fput_needed); + if (!err) + sockev_notify(SOCKEV_BIND, sock); } return err; } @@ -1427,6 +1442,8 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog) err = sock->ops->listen(sock, backlog); fput_light(sock->file, fput_needed); + if (!err) + sockev_notify(SOCKEV_LISTEN, sock); } return err; } @@ -1513,7 +1530,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, fd_install(newfd, newfile); err = newfd; - + if (!err) + sockev_notify(SOCKEV_ACCEPT, sock); out_put: fput_light(sock->file, fput_needed); out: @@ -1563,6 +1581,8 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, sock->file->f_flags); + if (!err) + sockev_notify(SOCKEV_CONNECT, sock); out_put: fput_light(sock->file, fput_needed); out: @@ -1822,6 +1842,7 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how) sock = sockfd_lookup_light(fd, &err, &fput_needed); if (sock != NULL) { + sockev_notify(SOCKEV_SHUTDOWN, sock); err = security_socket_shutdown(sock, how); if (!err) err = sock->ops->shutdown(sock, how); @@ -3330,3 +3351,15 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) return sock->ops->shutdown(sock, how); } EXPORT_SYMBOL(kernel_sock_shutdown); + +int sockev_register_notify(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&sockev_notifier_list, nb); +} +EXPORT_SYMBOL(sockev_register_notify); + +int sockev_unregister_notify(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&sockev_notifier_list, nb); +} +EXPORT_SYMBOL(sockev_unregister_notify); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 3ce53cf82df5..dc0a82cc59c8 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1411,6 +1411,9 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) (ut[i].family != prev_family)) return -EINVAL; + if (ut[i].mode >= XFRM_MODE_MAX) + return -EINVAL; + prev_family = ut[i].family; switch (ut[i].family) { |