From 9bf5a8aaa80be89c8cfd8feb5c6da3a616786af3 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Tue, 8 Nov 2016 11:49:15 +0530 Subject: [PATCH 001/210] arm64: avoid segfault on el0 cache maintenance It is found that "dc civac" from el0 on a non-COW RO VA results in a segmentation fault, while as per ARM ARM, for el0 only read access permission is needed on a VA to perform clean and invalidate. This bug was introduced by commit 3fbe6bc28a6b ("arm64: Allow cache maintenance operations to trigger write faults"), which enabled write faults on all cache maintenance faults. The original intention of the above commit was to trigger write faults only for cache maintenance operations performed by EL1 on user VA. But it introduced this side effect of generating a write fault on EL0 cache maintenance ops also when a read permission is sufficient for operation to succeed. This results in a segmentation fault when the VA is part of region marked as PROT_READ. So trigger write faults only when the cache maintenance fault is generated in non-user mode. Still, there can be a case where kernel performs a cache maintenance op on a PROT_READ mapped VA which will result in a kernel fault. But that looks invalid since there is no need for a kernel driver to perform a cache maintenance on a RO buffer and such cases if they exist need to be fixed. Change-Id: I001ca0473c37fcf713201386b5ed6a6244f6b37d Signed-off-by: Vinayak Menon --- arch/arm64/mm/fault.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 8287ac72ec13..eae76dbb22d4 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -223,7 +223,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, if (esr & ESR_LNX_EXEC) { vm_flags = VM_EXEC; - } else if (esr & ESR_EL1_WRITE) { + } else if (((esr & ESR_EL1_WRITE) && !(esr & ESR_EL1_CM)) || + ((esr & ESR_EL1_CM) && !(mm_flags & FAULT_FLAG_USER))) { vm_flags = VM_WRITE; mm_flags |= FAULT_FLAG_WRITE; } From 7a3b0814a37625d29375cd338b442033081301dc Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Mon, 19 Dec 2016 17:19:58 +0530 Subject: [PATCH 002/210] defconfig: Enable config IP_NF_MATCH_RPFILTER Enable config IP_NF_MATCH_RPFILTER. This option allows you to match packets whose replies would go out via the interface the packet came in Change-Id: I2a23346e726a8df8487aeb664d6316b3cf2b9d77 Signed-off-by: Bharat Pawar --- arch/arm/configs/msm8916-perf_defconfig | 2 ++ arch/arm/configs/msm8916_defconfig | 2 ++ arch/arm64/configs/msm-perf_defconfig | 2 ++ arch/arm64/configs/msm_defconfig | 2 ++ 4 files changed, 8 insertions(+) diff --git a/arch/arm/configs/msm8916-perf_defconfig b/arch/arm/configs/msm8916-perf_defconfig index 6f1068a59b54..08a43dec0f4c 100644 --- a/arch/arm/configs/msm8916-perf_defconfig +++ b/arch/arm/configs/msm8916-perf_defconfig @@ -176,6 +176,7 @@ CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y @@ -191,6 +192,7 @@ CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y CONFIG_NF_CONNTRACK_IPV6=y CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_MANGLE=y diff --git a/arch/arm/configs/msm8916_defconfig b/arch/arm/configs/msm8916_defconfig index 200760b4623c..b7caf59b54ee 100644 --- a/arch/arm/configs/msm8916_defconfig +++ b/arch/arm/configs/msm8916_defconfig @@ -174,6 +174,7 @@ CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y @@ -189,6 +190,7 @@ CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y CONFIG_NF_CONNTRACK_IPV6=y CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_MANGLE=y diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 033cdc26fc65..98d07a4b87f4 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -159,6 +159,7 @@ CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y @@ -174,6 +175,7 @@ CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y CONFIG_NF_CONNTRACK_IPV6=y CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_MANGLE=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index 74bec5713bf9..4a26793486ee 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -158,6 +158,7 @@ CONFIG_NF_CONNTRACK_IPV4=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y @@ -173,6 +174,7 @@ CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y CONFIG_NF_CONNTRACK_IPV6=y CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_MANGLE=y From 6f6c4cebc79485ae92d8c5b288475efd0514c2c9 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 7 Oct 2016 11:13:55 -0700 Subject: [PATCH 003/210] binder: blacklist %p kptr_restrict Bug: 31495231 Change-Id: Iebc150f6bc939b56e021424ee44fb30ce8d732fd [d-cagle@codeaurora.org: Applied to correct file location] Git-repo: https://android.googlesource.com/kernel/msm.git Git-commit: 0804d7840364fc1a93652632bd43a93c055c658e Signed-off-by: Dennis Cagle --- drivers/android/binder.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f79695a3fcd6..278b00c5aa7d 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -477,7 +477,7 @@ static void binder_insert_free_buffer(struct binder_proc *proc, new_buffer_size = binder_buffer_size(proc, new_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: add free buffer, size %zd, at %p\n", + "%d: add free buffer, size %zd, at %pK\n", proc->pid, new_buffer_size, new_buffer); while (*p) { @@ -555,7 +555,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, struct mm_struct *mm; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s pages %p-%p\n", proc->pid, + "%d: %s pages %pK-%pK\n", proc->pid, allocate ? "allocate" : "free", start, end); if (end <= start) @@ -595,7 +595,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, BUG_ON(*page); *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { - pr_err("%d: binder_alloc_buf failed for page at %p\n", + pr_err("%d: binder_alloc_buf failed for page at %pK\n", proc->pid, page_addr); goto err_alloc_page_failed; } @@ -604,7 +604,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, flush_cache_vmap((unsigned long)page_addr, (unsigned long)page_addr + PAGE_SIZE); if(ret != 1){ - pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n", + pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", proc->pid, page_addr); goto err_map_kernel_failed; } @@ -708,7 +708,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", + "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", proc->pid, size, buffer, buffer_size); has_page_addr = @@ -738,7 +738,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, binder_insert_free_buffer(proc, new_buffer); } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got %p\n", + "%d: binder_alloc_buf size %zd got %pK\n", proc->pid, size, buffer); buffer->data_size = data_size; buffer->offsets_size = offsets_size; @@ -778,7 +778,7 @@ static void binder_delete_free_buffer(struct binder_proc *proc, if (buffer_end_page(prev) == buffer_end_page(buffer)) free_page_end = 0; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p share page with %p\n", + "%d: merge free, buffer %pK share page with %pK\n", proc->pid, buffer, prev); } @@ -791,14 +791,14 @@ static void binder_delete_free_buffer(struct binder_proc *proc, buffer_start_page(buffer)) free_page_start = 0; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p share page with %p\n", + "%d: merge free, buffer %pK share page with %pK\n", proc->pid, buffer, prev); } } list_del(&buffer->entry); if (free_page_start || free_page_end) { binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p do not share page%s%s with %p or %p\n", + "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n", proc->pid, buffer, free_page_start ? "" : " end", free_page_end ? "" : " start", prev, next); binder_update_page_range(proc, 0, free_page_start ? @@ -819,7 +819,7 @@ static void binder_free_buf(struct binder_proc *proc, ALIGN(buffer->offsets_size, sizeof(void *)); binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_free_buf %p size %zd buffer_size %zd\n", + "%d: binder_free_buf %pK size %zd buffer_size %zd\n", proc->pid, buffer, size, buffer_size); BUG_ON(buffer->free); @@ -1252,7 +1252,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, int debug_id = buffer->debug_id; binder_debug(BINDER_DEBUG_TRANSACTION, - "%d buffer release %d, size %zd-%zd, failed at %p\n", + "%d buffer release %d, size %zd-%zd, failed at %pK\n", proc->pid, buffer->debug_id, buffer->data_size, buffer->offsets_size, failed_at); @@ -2092,9 +2092,8 @@ int binder_thread_write(struct binder_proc *proc, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", - proc->pid, thread->pid, (u64)cookie, - death); + "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", + proc->pid, thread->pid, (u64)cookie, death); if (death == NULL) { binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", proc->pid, thread->pid, (u64)cookie); @@ -2892,7 +2891,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) #ifdef CONFIG_CPU_CACHE_VIPT if (cache_is_vipt_aliasing()) { while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) { - pr_info("binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); + pr_info("binder_mmap: %d %lx-%lx maps %pK bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); vma->vm_start += PAGE_SIZE; } } @@ -2924,7 +2923,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) proc->vma = vma; proc->vma_vm_mm = vma->vm_mm; - /*pr_info("binder_mmap: %d %lx-%lx maps %p\n", + /*pr_info("binder_mmap: %d %lx-%lx maps %pK\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ return 0; @@ -3150,7 +3149,7 @@ static void binder_deferred_release(struct binder_proc *proc) page_addr = proc->buffer + i * PAGE_SIZE; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %p not freed\n", + "%s: %d: page %d at %pK not freed\n", __func__, proc->pid, i, page_addr); unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); __free_page(proc->pages[i]); @@ -3229,7 +3228,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, struct binder_transaction *t) { seq_printf(m, - "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", + "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", prefix, t->debug_id, t, t->from ? t->from->proc->pid : 0, t->from ? t->from->pid : 0, @@ -3243,7 +3242,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, if (t->buffer->target_node) seq_printf(m, " node %d", t->buffer->target_node->debug_id); - seq_printf(m, " size %zd:%zd data %p\n", + seq_printf(m, " size %zd:%zd data %pK\n", t->buffer->data_size, t->buffer->offsets_size, t->buffer->data); } @@ -3251,7 +3250,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, static void print_binder_buffer(struct seq_file *m, const char *prefix, struct binder_buffer *buffer) { - seq_printf(m, "%s %d: %p size %zd:%zd %s\n", + seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", prefix, buffer->debug_id, buffer->data, buffer->data_size, buffer->offsets_size, buffer->transaction ? "active" : "delivered"); From 06c2feb8af12426ac8fff4b922ff905cc625d6e6 Mon Sep 17 00:00:00 2001 From: Vikram Mulukutla Date: Wed, 6 Jan 2016 16:18:02 -0800 Subject: [PATCH 004/210] sched: core: Fix possible hotplug race in set_cpus_allowed_ptr Since a CPU may go offline after cpu_active_mask is used to query active CPUs, set_cpus_allowed_ptr might inadverntently pass an invalid cpu number to move_queued_task. Fix this by ensuring that the cpumask op that uses cpu_active_mask checks the return value. CRs-Fixed: 1029014 Change-Id: Id43a629b40b72cc47773e4027d30953b3a94058d Signed-off-by: Vikram Mulukutla [clingutla@codeaurora.org: Resolved merge conflicts] Signed-off-by: Lingutla Chandrasekhar --- kernel/sched/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index dd85ef023ed3..d4304ad3ca81 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7722,7 +7722,8 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) if (cpumask_equal(&p->cpus_allowed, new_mask)) goto out; - if (!cpumask_intersects(new_mask, cpu_active_mask)) { + dest_cpu = cpumask_any_and(cpu_active_mask, new_mask); + if (dest_cpu >= nr_cpu_ids) { ret = -EINVAL; goto out; } @@ -7733,7 +7734,6 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) if (cpumask_test_cpu(task_cpu(p), new_mask)) goto out; - dest_cpu = cpumask_any_and(cpu_active_mask, new_mask); if (p->on_rq) { struct migration_arg arg = { p, dest_cpu }; /* Need help from migration thread: drop lock and wait. */ From a46016a79005d846811d0b0584b14a57cdf677ff Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Fri, 16 Dec 2016 10:01:58 -0800 Subject: [PATCH 005/210] soc: qcom: pil/ssr: fix issue with logs The drivers uses %p to print the Kernel pointers. Replace %p with appropriate format to stop revealing Kernel pointers. Change-Id: Ic7d77e920ccfe779b979f732d506d59dcdfe885a Signed-off-by: Satya Durga Srinivasu Prabhala --- drivers/soc/qcom/pil-q6v5.c | 4 ++-- drivers/soc/qcom/subsystem_notif.c | 6 +++--- drivers/soc/qcom/subsystem_restart.c | 27 +++++++++++++++------------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/soc/qcom/pil-q6v5.c b/drivers/soc/qcom/pil-q6v5.c index 3f65726ae2b1..135263141e20 100644 --- a/drivers/soc/qcom/pil-q6v5.c +++ b/drivers/soc/qcom/pil-q6v5.c @@ -180,9 +180,9 @@ void pil_q6v5_halt_axi_port(struct pil_desc *pil, void __iomem *halt_base) ret = readl_poll_timeout(halt_base + AXI_HALTACK, status, status != 0, 50, HALT_ACK_TIMEOUT_US); if (ret) - dev_warn(pil->dev, "Port %p halt timeout\n", halt_base); + dev_warn(pil->dev, "Port %pK halt timeout\n", halt_base); else if (!readl_relaxed(halt_base + AXI_IDLE)) - dev_warn(pil->dev, "Port %p halt failed\n", halt_base); + dev_warn(pil->dev, "Port %pK halt failed\n", halt_base); /* Clear halt request (port will remain halted until reset) */ writel_relaxed(0, halt_base + AXI_HALTREQ); diff --git a/drivers/soc/qcom/subsystem_notif.c b/drivers/soc/qcom/subsystem_notif.c index 431bbd8cee6f..8b24008b5abe 100644 --- a/drivers/soc/qcom/subsystem_notif.c +++ b/drivers/soc/qcom/subsystem_notif.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011, 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 @@ -196,7 +196,7 @@ static int subsys_notifier_test_call(struct notifier_block *this, switch (code) { default: - printk(KERN_WARNING "%s: Notification %s from subsystem %p\n", + pr_warn("%s: Notification %s from subsystem %pK\n", __func__, notif_to_string(code), data); break; @@ -212,7 +212,7 @@ static struct notifier_block nb = { static void subsys_notif_reg_test_notifier(const char *subsys_name) { void *handle = subsys_notif_register_notifier(subsys_name, &nb); - printk(KERN_WARNING "%s: Registered test notifier, handle=%p", + pr_warn("%s: Registered test notifier, handle=%pK", __func__, handle); } #endif diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index c6dbf2e19619..b429fa9170ac 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -596,10 +596,11 @@ static void subsystem_shutdown(struct subsys_device *dev, void *data) { const char *name = dev->desc->name; - pr_info("[%p]: Shutting down %s\n", current, name); + pr_info("[%s:%d]: Shutting down %s\n", + current->comm, current->pid, name); if (dev->desc->shutdown(dev->desc, true) < 0) - panic("subsys-restart: [%p]: Failed to shutdown %s!", - current, name); + panic("subsys-restart: [%s:%d]: Failed to shutdown %s!", + current->comm, current->pid, name); dev->crash_count++; subsys_set_state(dev, SUBSYS_OFFLINE); disable_all_irqs(dev); @@ -611,7 +612,8 @@ static void subsystem_ramdump(struct subsys_device *dev, void *data) if (dev->desc->ramdump) if (dev->desc->ramdump(is_ramdump_enabled(dev), dev->desc) < 0) - pr_warn("%s[%p]: Ramdump failed.\n", name, current); + pr_warn("%s[%s:%d]: Ramdump failed.\n", + name, current->comm, current->pid); dev->do_ramdump_on_put = false; } @@ -626,13 +628,14 @@ static void subsystem_powerup(struct subsys_device *dev, void *data) const char *name = dev->desc->name; int ret; - pr_info("[%p]: Powering up %s\n", current, name); + pr_info("[%s:%d]: Powering up %s\n", current->comm, current->pid, name); init_completion(&dev->err_ready); if (dev->desc->powerup(dev->desc) < 0) { notify_each_subsys_device(&dev, 1, SUBSYS_POWERUP_FAILURE, NULL); - panic("[%p]: Powerup error: %s!", current, name); + panic("[%s:%d]: Powerup error: %s!", + current->comm, current->pid, name); } enable_all_irqs(dev); @@ -640,8 +643,8 @@ static void subsystem_powerup(struct subsys_device *dev, void *data) if (ret) { notify_each_subsys_device(&dev, 1, SUBSYS_POWERUP_FAILURE, NULL); - panic("[%p]: Timed out waiting for error ready: %s!", - current, name); + panic("[%s:%d]: Timed out waiting for error ready: %s!", + current->comm, current->pid, name); } subsys_set_state(dev, SUBSYS_ONLINE); subsys_set_crash_status(dev, false); @@ -890,8 +893,8 @@ static void subsystem_restart_wq_func(struct work_struct *work) */ mutex_lock(&soc_order_reg_lock); - pr_debug("[%p]: Starting restart sequence for %s\n", current, - desc->name); + pr_debug("[%s:%d]: Starting restart sequence for %s\n", + current->comm, current->pid, desc->name); notify_each_subsys_device(list, count, SUBSYS_BEFORE_SHUTDOWN, NULL); for_each_subsys_device(list, count, NULL, subsystem_shutdown); notify_each_subsys_device(list, count, SUBSYS_AFTER_SHUTDOWN, NULL); @@ -912,8 +915,8 @@ static void subsystem_restart_wq_func(struct work_struct *work) for_each_subsys_device(list, count, NULL, subsystem_powerup); notify_each_subsys_device(list, count, SUBSYS_AFTER_POWERUP, NULL); - pr_info("[%p]: Restart sequence for %s completed.\n", - current, desc->name); + pr_info("[%s:%d]: Restart sequence for %s completed.\n", + current->comm, current->pid, desc->name); mutex_unlock(&soc_order_reg_lock); mutex_unlock(&track->lock); From c182ffa63a48f2f73170f9d02e27a8f5e54ccade Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Fri, 25 Nov 2016 10:41:55 +0530 Subject: [PATCH 006/210] soc: qcom: add support to append suffix to socinfo Some targets may share same msm-id, but they can have different product name. To differentiate them, add support to append suffix to soc_id_string. Change-Id: Id0272cc4bd776c9872680a218f445160125d6faf Signed-off-by: Lingutla Chandrasekhar --- drivers/soc/qcom/socinfo.c | 15 +++++++++++---- include/soc/qcom/socinfo.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 5786b3724f2a..838c6dd895fb 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -509,11 +509,11 @@ static struct msm_soc_info cpu_of_id[] = { [289] = {MSM_CPU_8952, "APQ8052"}, /* 8976 ID */ - [278] = {MSM_CPU_8976, "MSM8976"}, - [277] = {MSM_CPU_8976, "APQ8076"}, + [278] = {MSM_CPU_8976, "MSM8976", "SG"}, + [277] = {MSM_CPU_8976, "APQ8076", "SG"}, /* 8956 ID */ - [266] = {MSM_CPU_8956, "MSM8956"}, - [274] = {MSM_CPU_8956, "APQ8056"}, + [266] = {MSM_CPU_8956, "MSM8956", "SG"}, + [274] = {MSM_CPU_8956, "APQ8056", "SG"}, /* 8929 IDs */ [268] = {MSM_CPU_8929, "MSM8929"}, @@ -577,6 +577,13 @@ static char *msm_read_hardware_id(void) if (ret > sizeof(msm_soc_str)) goto err_path; + /* Add suffix if need to be */ + if ((socinfo->v2.raw_version == 2) && strlen(cpu_of_id[socinfo->v1.id].suffix)) { + ret = strlcat(msm_soc_str, cpu_of_id[socinfo->v1.id].suffix, + sizeof(msm_soc_str)); + if (ret > sizeof(msm_soc_str)) + goto err_path; + } string_generated = true; return msm_soc_str; err_path: diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index 4e9c1681f871..3ef006aa8e4d 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -188,6 +188,7 @@ enum msm_cpu { struct msm_soc_info { enum msm_cpu generic_soc_type; char *soc_id_string; + char *suffix; }; enum pmic_model { From bf9c19e8ce4e691bd29aa1d18be3be39e11a59df Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 28 Dec 2015 20:47:08 -0500 Subject: [PATCH 007/210] [PATCH] arm: fix handling of F_OFD_... in oabi_fcntl64() Change-Id: I4809d4887caf26bcfad505d6a378369b217b5a9e Cc: stable@vger.kernel.org # 3.15+ Reviewed-by: Jeff Layton Signed-off-by: Al Viro Git-repo: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git Git-commit: 76cc404bfdc0d419c720de4daaf2584542734f42 Signed-off-by: Dennis Cagle --- arch/arm/kernel/sys_oabi-compat.c | 77 ++++++++++++++++--------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 3e94811690ce..20a6f3a7376f 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -193,52 +193,53 @@ struct oabi_flock64 { pid_t l_pid; } __attribute__ ((packed,aligned(4))); +static long do_locks(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + struct flock64 kernel; + struct oabi_flock64 user; + mm_segment_t fs; + long ret; + + if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, + sizeof(user))) + return -EFAULT; + kernel.l_type = user.l_type; + kernel.l_whence = user.l_whence; + kernel.l_start = user.l_start; + kernel.l_len = user.l_len; + kernel.l_pid = user.l_pid; + + fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_fcntl64(fd, cmd, (unsigned long)&kernel); + set_fs(fs); + + if (!ret && (cmd == F_GETLK64 || cmd == F_OFD_GETLK)) { + user.l_type = kernel.l_type; + user.l_whence = kernel.l_whence; + user.l_start = kernel.l_start; + user.l_len = kernel.l_len; + user.l_pid = kernel.l_pid; + if (copy_to_user((struct oabi_flock64 __user *)arg, + &user, sizeof(user))) + ret = -EFAULT; + } + return ret; +} + asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct oabi_flock64 user; - struct flock64 kernel; - mm_segment_t fs = USER_DS; /* initialized to kill a warning */ - unsigned long local_arg = arg; - int ret; - switch (cmd) { case F_GETLK64: case F_SETLK64: case F_SETLKW64: - if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, - sizeof(user))) - return -EFAULT; - kernel.l_type = user.l_type; - kernel.l_whence = user.l_whence; - kernel.l_start = user.l_start; - kernel.l_len = user.l_len; - kernel.l_pid = user.l_pid; - local_arg = (unsigned long)&kernel; - fs = get_fs(); - set_fs(KERNEL_DS); + return do_locks(fd, cmd, arg); + + default: + return sys_fcntl64(fd, cmd, arg); } - - ret = sys_fcntl64(fd, cmd, local_arg); - - switch (cmd) { - case F_GETLK64: - if (!ret) { - user.l_type = kernel.l_type; - user.l_whence = kernel.l_whence; - user.l_start = kernel.l_start; - user.l_len = kernel.l_len; - user.l_pid = kernel.l_pid; - if (copy_to_user((struct oabi_flock64 __user *)arg, - &user, sizeof(user))) - ret = -EFAULT; - } - case F_SETLK64: - case F_SETLKW64: - set_fs(fs); - } - - return ret; } struct oabi_epoll_event { From a26642209516b2a5ba292d2454568972f2a05e9e Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Tue, 25 Oct 2016 10:21:22 -0700 Subject: [PATCH 008/210] qseecom: check error return value of ion_map_kernel ion_map_kernel() is called without checking for or acting upon the possible error conditions this function may return, make change to check its error return value. CRs-fixed: 1081637 Change-Id: I0a34f0bbc9f2049b826777a31e14d2cf62cdc211 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index f132b60b6788..03bb86dda519 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -989,6 +989,10 @@ static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc, } /* Populate the structure for sending scm call to load image */ svc->sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt, svc->ihandle); + if (IS_ERR_OR_NULL(svc->sb_virt)) { + pr_err("ION memory mapping for listener shared buffer failed\n"); + return -ENOMEM; + } svc->sb_phys = (phys_addr_t)pa; if (qseecom.qsee_version < QSEE_VERSION_40) { @@ -1445,6 +1449,10 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, /* Populate the structure for sending scm call to load image */ data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt, data->client.ihandle); + if (IS_ERR_OR_NULL(data->client.sb_virt)) { + pr_err("ION memory mapping for client shared buf failed\n"); + return -ENOMEM; + } data->client.sb_phys = (phys_addr_t)pa; data->client.sb_length = req.sb_len; data->client.user_virt_sb_base = (uintptr_t)req.virt_sb_base; @@ -3975,6 +3983,11 @@ int qseecom_start_app(struct qseecom_handle **handle, /* Populate the structure for sending scm call to load image */ data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt, data->client.ihandle); + if (IS_ERR_OR_NULL(data->client.sb_virt)) { + pr_err("ION memory mapping for client shared buf failed\n"); + ret = -ENOMEM; + goto err; + } data->client.user_virt_sb_base = (uintptr_t)data->client.sb_virt; data->client.sb_phys = (phys_addr_t)pa; (*handle)->dev = (void *)data; From 89e19b43f98d41d1b704d469dccd88a6f2512a00 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Thu, 20 Oct 2016 17:34:20 -0700 Subject: [PATCH 009/210] qseecom: check buffer size when loading firmware images Make change in __qseecom_load_fw() and qseecom_load_commonlib_image() to check buffer size before copying img to buffer. CRs-fixed: 1080290 Change-Id: I0f48666ac948a9571e249598ae7cc19df9036b1d Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index f132b60b6788..c13567dd9ca2 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -3389,7 +3389,7 @@ static bool __qseecom_is_fw_image_valid(const struct firmware *fw_entry) return true; } -static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size, +static int __qseecom_get_fw_size(const char *appname, uint32_t *fw_size, uint32_t *app_arch) { int ret = -1; @@ -3427,14 +3427,21 @@ static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size, } pr_debug("QSEE %s app, arch %u\n", appname, *app_arch); release_firmware(fw_entry); + fw_entry = NULL; for (i = 0; i < num_images; i++) { memset(fw_name, 0, sizeof(fw_name)); snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i); ret = request_firmware(&fw_entry, fw_name, qseecom.pdev); if (ret) goto err; + if (*fw_size > U32_MAX - fw_entry->size) { + pr_err("QSEE %s app file size overflow\n", appname); + ret = -EINVAL; + goto err; + } *fw_size += fw_entry->size; release_firmware(fw_entry); + fw_entry = NULL; } return ret; @@ -3445,8 +3452,9 @@ err: return ret; } -static int __qseecom_get_fw_data(char *appname, u8 *img_data, - struct qseecom_load_app_ireq *load_req) +static int __qseecom_get_fw_data(const char *appname, u8 *img_data, + uint32_t fw_size, + struct qseecom_load_app_ireq *load_req) { int ret = -1; int i = 0, rc = 0; @@ -3466,6 +3474,12 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, } load_req->img_len = fw_entry->size; + if (load_req->img_len > fw_size) { + pr_err("app %s size %zu is larger than buf size %u\n", + appname, fw_entry->size, fw_size); + ret = -EINVAL; + goto err; + } memcpy(img_data_ptr, fw_entry->data, fw_entry->size); img_data_ptr = img_data_ptr + fw_entry->size; load_req->mdt_len = fw_entry->size; /*Get MDT LEN*/ @@ -3484,6 +3498,7 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, goto err; } release_firmware(fw_entry); + fw_entry = NULL; for (i = 0; i < num_images; i++) { snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i); ret = request_firmware(&fw_entry, fw_name, qseecom.pdev); @@ -3491,10 +3506,17 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, pr_err("Failed to locate blob %s\n", fw_name); goto err; } + if ((fw_entry->size > U32_MAX - load_req->img_len) || + (fw_entry->size + load_req->img_len > fw_size)) { + pr_err("Invalid file size for %s\n", fw_name); + ret = -EINVAL; + goto err; + } memcpy(img_data_ptr, fw_entry->data, fw_entry->size); img_data_ptr = img_data_ptr + fw_entry->size; load_req->img_len += fw_entry->size; release_firmware(fw_entry); + fw_entry = NULL; } return ret; err: @@ -3599,7 +3621,7 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) if (ret) return ret; - ret = __qseecom_get_fw_data(appname, img_data, &load_req); + ret = __qseecom_get_fw_data(appname, img_data, fw_size, &load_req); if (ret) { ret = -EIO; goto exit_free_img_data; @@ -3721,7 +3743,7 @@ static int qseecom_load_commonlib_image(struct qseecom_dev_handle *data, if (ret) return -EIO; - ret = __qseecom_get_fw_data(cmnlib_name, img_data, &load_req); + ret = __qseecom_get_fw_data(cmnlib_name, img_data, fw_size, &load_req); if (ret) { ret = -EIO; goto exit_free_img_data; From c681ca265e7e1f7ae06508ca14f02beefab0af22 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 23 Jan 2015 12:24:14 +0100 Subject: [PATCH 010/210] perf: Fix event->ctx locking There have been a few reported issues wrt. the lack of locking around changing event->ctx. This patch tries to address those. It avoids the whole rwsem thing and while it appears to work, please give it some thought in review. What I did fail at is sensible runtime checks on the use of event->ctx, the RCU use makes it very hard. Signed-off-by: Peter Zijlstra (Intel) Cc: Paul E. McKenney Cc: Jiri Olsa Cc: Arnaldo Carvalho de Melo Cc: Linus Torvalds Link: http://lkml.kernel.org/r/20150123125834.209535886@infradead.org Signed-off-by: Ingo Molnar (cherry picked from commit f63a8daa5812afef4f06c962351687e1ff9ccb2b) Bug: 30955111 Bug: 31095224 Signed-off-by: Joao Dias Change-Id: I8dfc0aae8d1206c177454e0093dacd82b6129c55 Git-repo: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git Git-commit: f63a8daa5812afef4f06c962351687e1ff9ccb2b [rsiddoji@codeaurora.org: resloved some trival confilits] Signed-off-by: Ravi Kumar Siddojigari Signed-off-by: Pradosh Das Signed-off-by: Kishor PK --- kernel/events/core.c | 244 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 208 insertions(+), 36 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index dcaacbbf659b..250c39a5f84e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -808,6 +808,77 @@ static void put_ctx(struct perf_event_context *ctx) } } +/* + * Because of perf_event::ctx migration in sys_perf_event_open::move_group and + * perf_pmu_migrate_context() we need some magic. + * + * Those places that change perf_event::ctx will hold both + * perf_event_ctx::mutex of the 'old' and 'new' ctx value. + * + * Lock ordering is by mutex address. There is one other site where + * perf_event_context::mutex nests and that is put_event(). But remember that + * that is a parent<->child context relation, and migration does not affect + * children, therefore these two orderings should not interact. + * + * The change in perf_event::ctx does not affect children (as claimed above) + * because the sys_perf_event_open() case will install a new event and break + * the ctx parent<->child relation, and perf_pmu_migrate_context() is only + * concerned with cpuctx and that doesn't have children. + * + * The places that change perf_event::ctx will issue: + * + * perf_remove_from_context(); + * synchronize_rcu(); + * perf_install_in_context(); + * + * to affect the change. The remove_from_context() + synchronize_rcu() should + * quiesce the event, after which we can install it in the new location. This + * means that only external vectors (perf_fops, prctl) can perturb the event + * while in transit. Therefore all such accessors should also acquire + * perf_event_context::mutex to serialize against this. + * + * However; because event->ctx can change while we're waiting to acquire + * ctx->mutex we must be careful and use the below perf_event_ctx_lock() + * function. + * + * Lock order: + * task_struct::perf_event_mutex + * perf_event_context::mutex + * perf_event_context::lock + * perf_event::child_mutex; + * perf_event::mmap_mutex + * mmap_sem + */ +static struct perf_event_context *perf_event_ctx_lock(struct perf_event *event) +{ + struct perf_event_context *ctx; + +again: + rcu_read_lock(); + ctx = ACCESS_ONCE(event->ctx); + if (!atomic_inc_not_zero(&ctx->refcount)) { + rcu_read_unlock(); + goto again; + } + rcu_read_unlock(); + + mutex_lock(&ctx->mutex); + if (event->ctx != ctx) { + mutex_unlock(&ctx->mutex); + put_ctx(ctx); + goto again; + } + + return ctx; +} + +static void perf_event_ctx_unlock(struct perf_event *event, + struct perf_event_context *ctx) +{ + mutex_unlock(&ctx->mutex); + put_ctx(ctx); +} + static void unclone_ctx(struct perf_event_context *ctx) { if (ctx->parent_ctx) { @@ -1528,7 +1599,7 @@ int __perf_event_disable(void *info) * is the current context on this CPU and preemption is disabled, * hence we can't get into perf_event_task_sched_out for this context. */ -void perf_event_disable(struct perf_event *event) +static void _perf_event_disable(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; struct task_struct *task = ctx->task; @@ -1569,6 +1640,19 @@ retry: } raw_spin_unlock_irq(&ctx->lock); } + +/* + * Strictly speaking kernel users cannot create groups and therefore this + * interface does not need the perf_event_ctx_lock() magic. + */ +void perf_event_disable(struct perf_event *event) +{ + struct perf_event_context *ctx; + + ctx = perf_event_ctx_lock(event); + _perf_event_disable(event); + perf_event_ctx_unlock(event, ctx); +} EXPORT_SYMBOL_GPL(perf_event_disable); static void perf_set_shadow_time(struct perf_event *event, @@ -2018,7 +2102,7 @@ unlock: * perf_event_for_each_child or perf_event_for_each as described * for perf_event_disable. */ -void perf_event_enable(struct perf_event *event) +static void _perf_event_enable(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; struct task_struct *task = ctx->task; @@ -2074,9 +2158,21 @@ retry: out: raw_spin_unlock_irq(&ctx->lock); } + +/* + * See perf_event_disable(); + */ +void perf_event_enable(struct perf_event *event) +{ + struct perf_event_context *ctx; + + ctx = perf_event_ctx_lock(event); + _perf_event_enable(event); + perf_event_ctx_unlock(event, ctx); +} EXPORT_SYMBOL_GPL(perf_event_enable); -int perf_event_refresh(struct perf_event *event, int refresh) +static int _perf_event_refresh(struct perf_event *event, int refresh) { /* * not supported on inherited events @@ -2085,10 +2181,25 @@ int perf_event_refresh(struct perf_event *event, int refresh) return -EINVAL; atomic_add(refresh, &event->event_limit); - perf_event_enable(event); + _perf_event_enable(event); return 0; } + +/* + * See perf_event_disable() + */ +int perf_event_refresh(struct perf_event *event, int refresh) +{ + struct perf_event_context *ctx; + int ret; + + ctx = perf_event_ctx_lock(event); + ret = _perf_event_refresh(event, refresh); + perf_event_ctx_unlock(event, ctx); + + return ret; +} EXPORT_SYMBOL_GPL(perf_event_refresh); static void ctx_sched_out(struct perf_event_context *ctx, @@ -3221,7 +3332,17 @@ static void perf_remove_from_owner(struct perf_event *event) rcu_read_unlock(); if (owner) { - mutex_lock(&owner->perf_event_mutex); + /* + * If we're here through perf_event_exit_task() we're already + * holding ctx->mutex which would be an inversion wrt. the + * normal lock order. + * + * However we can safely take this lock because its the child + * ctx->mutex. + */ + mutex_lock_nested(&owner->perf_event_mutex, + SINGLE_DEPTH_NESTING); + /* * We have to re-check the event->owner field, if it is cleared * we raced with perf_event_exit_task(), acquiring the mutex @@ -3331,12 +3452,13 @@ static int perf_event_read_group(struct perf_event *event, u64 read_format, char __user *buf) { struct perf_event *leader = event->group_leader, *sub; - int n = 0, size = 0, ret = -EFAULT; struct perf_event_context *ctx = leader->ctx; - u64 values[5]; + int n = 0, size = 0, ret; u64 count, enabled, running; + u64 values[5]; + + lockdep_assert_held(&ctx->mutex); - mutex_lock(&ctx->mutex); count = perf_event_read_value(leader, &enabled, &running); values[n++] = 1 + leader->nr_siblings; @@ -3351,7 +3473,7 @@ static int perf_event_read_group(struct perf_event *event, size = n * sizeof(u64); if (copy_to_user(buf, values, size)) - goto unlock; + return -EFAULT; ret = size; @@ -3365,14 +3487,11 @@ static int perf_event_read_group(struct perf_event *event, size = n * sizeof(u64); if (copy_to_user(buf + ret, values, size)) { - ret = -EFAULT; - goto unlock; + return -EFAULT; } ret += size; } -unlock: - mutex_unlock(&ctx->mutex); return ret; } @@ -3431,8 +3550,14 @@ static ssize_t perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct perf_event *event = file->private_data; + struct perf_event_context *ctx; + int ret; - return perf_read_hw(event, buf, count); + ctx = perf_event_ctx_lock(event); + ret = perf_read_hw(event, buf, count); + perf_event_ctx_unlock(event, ctx); + + return ret; } static unsigned int perf_poll(struct file *file, poll_table *wait) @@ -3456,7 +3581,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) return events; } -static void perf_event_reset(struct perf_event *event) +static void _perf_event_reset(struct perf_event *event) { (void)perf_event_read(event); local64_set(&event->count, 0); @@ -3475,6 +3600,7 @@ static void perf_event_for_each_child(struct perf_event *event, struct perf_event *child; WARN_ON_ONCE(event->ctx->parent_ctx); + mutex_lock(&event->child_mutex); func(event); list_for_each_entry(child, &event->child_list, child_list) @@ -3488,14 +3614,13 @@ static void perf_event_for_each(struct perf_event *event, struct perf_event_context *ctx = event->ctx; struct perf_event *sibling; - WARN_ON_ONCE(ctx->parent_ctx); - mutex_lock(&ctx->mutex); + lockdep_assert_held(&ctx->mutex); + event = event->group_leader; perf_event_for_each_child(event, func); list_for_each_entry(sibling, &event->sibling_list, group_entry) perf_event_for_each_child(sibling, func); - mutex_unlock(&ctx->mutex); } static int perf_event_period(struct perf_event *event, u64 __user *arg) @@ -3551,25 +3676,25 @@ static int perf_event_set_output(struct perf_event *event, struct perf_event *output_event); static int perf_event_set_filter(struct perf_event *event, void __user *arg); -static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long _perf_ioctl(struct perf_event *event, unsigned int cmd, + unsigned long arg) { - struct perf_event *event = file->private_data; void (*func)(struct perf_event *); u32 flags = arg; switch (cmd) { case PERF_EVENT_IOC_ENABLE: - func = perf_event_enable; + func = _perf_event_enable; break; case PERF_EVENT_IOC_DISABLE: - func = perf_event_disable; + func = _perf_event_disable; break; case PERF_EVENT_IOC_RESET: - func = perf_event_reset; + func = _perf_event_reset; break; case PERF_EVENT_IOC_REFRESH: - return perf_event_refresh(event, arg); + return _perf_event_refresh(event, arg); case PERF_EVENT_IOC_PERIOD: return perf_event_period(event, (u64 __user *)arg); @@ -3607,6 +3732,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } +static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct perf_event *event = file->private_data; + struct perf_event_context *ctx; + long ret; + + ctx = perf_event_ctx_lock(event); + ret = _perf_ioctl(event, cmd, arg); + perf_event_ctx_unlock(event, ctx); + + return ret; +} + #ifdef CONFIG_COMPAT static long perf_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -3628,11 +3766,15 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd, int perf_event_task_enable(void) { + struct perf_event_context *ctx; struct perf_event *event; mutex_lock(¤t->perf_event_mutex); - list_for_each_entry(event, ¤t->perf_event_list, owner_entry) - perf_event_for_each_child(event, perf_event_enable); + list_for_each_entry(event, ¤t->perf_event_list, owner_entry) { + ctx = perf_event_ctx_lock(event); + perf_event_for_each_child(event, _perf_event_enable); + perf_event_ctx_unlock(event, ctx); + } mutex_unlock(¤t->perf_event_mutex); return 0; @@ -3640,11 +3782,15 @@ int perf_event_task_enable(void) int perf_event_task_disable(void) { + struct perf_event_context *ctx; struct perf_event *event; mutex_lock(¤t->perf_event_mutex); - list_for_each_entry(event, ¤t->perf_event_list, owner_entry) - perf_event_for_each_child(event, perf_event_disable); + list_for_each_entry(event, ¤t->perf_event_list, owner_entry) { + ctx = perf_event_ctx_lock(event); + perf_event_for_each_child(event, _perf_event_disable); + perf_event_ctx_unlock(event, ctx); + } mutex_unlock(¤t->perf_event_mutex); return 0; @@ -6790,6 +6936,15 @@ out: return ret; } +static void mutex_lock_double(struct mutex *a, struct mutex *b) +{ + if (b < a) + swap(a, b); + + mutex_lock(a); + mutex_lock_nested(b, SINGLE_DEPTH_NESTING); +} + /** * sys_perf_event_open - open a performance event, associate it to a task/cpu * @@ -6805,7 +6960,7 @@ SYSCALL_DEFINE5(perf_event_open, struct perf_event *group_leader = NULL, *output_event = NULL; struct perf_event *event, *sibling; struct perf_event_attr attr; - struct perf_event_context *ctx; + struct perf_event_context *ctx, *uninitialized_var(gctx); struct file *event_file = NULL; struct fd group = {NULL, 0}; struct task_struct *task = NULL; @@ -6994,7 +7149,13 @@ SYSCALL_DEFINE5(perf_event_open, } if (move_group) { - struct perf_event_context *gctx = group_leader->ctx; + gctx = group_leader->ctx; + + /* + * See perf_event_ctx_lock() for comments on the details + * of swizzling perf_event::ctx. + */ + mutex_lock_double(&gctx->mutex, &ctx->mutex); mutex_lock(&gctx->mutex); perf_remove_from_context(group_leader, false); @@ -7011,14 +7172,17 @@ SYSCALL_DEFINE5(perf_event_open, perf_event__state_init(sibling); put_ctx(gctx); } - mutex_unlock(&gctx->mutex); - put_ctx(gctx); + } else { + mutex_lock(&ctx->mutex); } WARN_ON_ONCE(ctx->parent_ctx); - mutex_lock(&ctx->mutex); if (move_group) { + /* + * Wait for everybody to stop referencing the events through + * the old lists, before installing it on new lists. + */ synchronize_rcu(); perf_install_in_context(ctx, group_leader, group_leader->cpu); get_ctx(ctx); @@ -7032,6 +7196,11 @@ SYSCALL_DEFINE5(perf_event_open, perf_install_in_context(ctx, event, event->cpu); ++ctx->generation; perf_unpin_context(ctx); + + if (move_group) { + mutex_unlock(&gctx->mutex); + put_ctx(gctx); + } mutex_unlock(&ctx->mutex); put_online_cpus(); @@ -7137,18 +7306,20 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx; dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx; - mutex_lock(&src_ctx->mutex); + /* + * See perf_event_ctx_lock() for comments on the details + * of swizzling perf_event::ctx. + */ + mutex_lock_double(&src_ctx->mutex, &dst_ctx->mutex); list_for_each_entry_safe(event, tmp, &src_ctx->event_list, event_entry) { perf_remove_from_context(event, false); put_ctx(src_ctx); list_add(&event->event_entry, &events); } - mutex_unlock(&src_ctx->mutex); synchronize_rcu(); - mutex_lock(&dst_ctx->mutex); list_for_each_entry_safe(event, tmp, &events, event_entry) { list_del(&event->event_entry); if (event->state >= PERF_EVENT_STATE_OFF) @@ -7157,6 +7328,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) get_ctx(dst_ctx); } mutex_unlock(&dst_ctx->mutex); + mutex_unlock(&src_ctx->mutex); } EXPORT_SYMBOL_GPL(perf_pmu_migrate_context); From ac123e9141d1aaf65e50d4e0f078ee29242a8316 Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Thu, 22 Dec 2016 16:30:36 +0530 Subject: [PATCH 011/210] Revert "trace: Add an option to show tgids in trace output" This reverts commit 0438cf86ad89 ("trace: Add an option to show tgids in trace output"). Reverting this patch because array overflow can occur to array saved_tgids[] when user sets the saved_cmdlines_size from debugfs to more than size of saved_tgids[] that is 128. Change-Id: I4ac838e19eec1870bea16dccaac648e34cb40ef1 [spathi@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Srinivasarao P --- kernel/trace/trace.c | 99 ++----------------------------------- kernel/trace/trace.h | 2 - kernel/trace/trace_output.c | 18 +------ 3 files changed, 5 insertions(+), 114 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1859cc4183db..1c7a49130f65 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -735,7 +735,6 @@ static const char *trace_options[] = { "irq-info", "markers", "function-trace", - "print-tgid", NULL }; @@ -1248,7 +1247,6 @@ void tracing_reset_all_online_cpus(void) static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; static unsigned map_cmdline_to_pid[SAVED_CMDLINES]; static char saved_cmdlines[SAVED_CMDLINES][TASK_COMM_LEN]; -static unsigned saved_tgids[SAVED_CMDLINES]; static int cmdline_idx; static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED; @@ -1450,7 +1448,6 @@ static int trace_save_cmdline(struct task_struct *tsk) } memcpy(&saved_cmdlines[idx], tsk->comm, TASK_COMM_LEN); - saved_tgids[idx] = tsk->tgid; arch_spin_unlock(&trace_cmdline_lock); @@ -1488,25 +1485,6 @@ void trace_find_cmdline(int pid, char comm[]) preempt_enable(); } -int trace_find_tgid(int pid) -{ - unsigned map; - int tgid; - - preempt_disable(); - arch_spin_lock(&trace_cmdline_lock); - map = map_pid_to_cmdline[pid]; - if (map != NO_CMDLINE_MAP) - tgid = saved_tgids[map]; - else - tgid = -1; - - arch_spin_unlock(&trace_cmdline_lock); - preempt_enable(); - - return tgid; -} - void tracing_record_cmdline(struct task_struct *tsk) { if (atomic_read(&trace_record_cmdline_disabled) || !tracing_is_on()) @@ -2463,13 +2441,6 @@ static void print_func_help_header(struct trace_buffer *buf, struct seq_file *m) seq_puts(m, "# | | | | |\n"); } -static void print_func_help_header_tgid(struct trace_buffer *buf, struct seq_file *m) -{ - print_event_info(buf, m); - seq_puts(m, "# TASK-PID TGID CPU# TIMESTAMP FUNCTION\n"); - seq_puts(m, "# | | | | | |\n"); -} - static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file *m) { print_event_info(buf, m); @@ -2482,18 +2453,6 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file seq_puts(m, "# | | | |||| | |\n"); } -static void print_func_help_header_irq_tgid(struct trace_buffer *buf, struct seq_file *m) -{ - print_event_info(buf, m); - seq_puts(m, "# _-----=> irqs-off\n"); - seq_puts(m, "# / _----=> need-resched\n"); - seq_puts(m, "# | / _---=> hardirq/softirq\n"); - seq_puts(m, "# || / _--=> preempt-depth\n"); - seq_puts(m, "# ||| / delay\n"); - seq_puts(m, "# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION\n"); - seq_puts(m, "# | | | | |||| | |\n"); -} - void print_trace_header(struct seq_file *m, struct trace_iterator *iter) { @@ -2794,15 +2753,10 @@ void trace_default_header(struct seq_file *m) } else { if (!(trace_flags & TRACE_ITER_VERBOSE)) { if (trace_flags & TRACE_ITER_IRQ_INFO) - if (trace_flags & TRACE_ITER_TGID) - print_func_help_header_irq_tgid(iter->trace_buffer, m); - else - print_func_help_header_irq(iter->trace_buffer, m); + print_func_help_header_irq(iter->trace_buffer, + m); else - if (trace_flags & TRACE_ITER_TGID) - print_func_help_header_tgid(iter->trace_buffer, m); - else - print_func_help_header(iter->trace_buffer, m); + print_func_help_header(iter->trace_buffer, m); } } } @@ -3659,50 +3613,6 @@ static const struct file_operations tracing_saved_cmdlines_fops = { .llseek = generic_file_llseek, }; -static ssize_t -tracing_saved_tgids_read(struct file *file, char __user *ubuf, - size_t cnt, loff_t *ppos) -{ - char *file_buf; - char *buf; - int len = 0; - int pid; - int i; - - file_buf = kmalloc(SAVED_CMDLINES*(16+1+16), GFP_KERNEL); - if (!file_buf) - return -ENOMEM; - - buf = file_buf; - - for (i = 0; i < SAVED_CMDLINES; i++) { - int tgid; - int r; - - pid = map_cmdline_to_pid[i]; - if (pid == -1 || pid == NO_CMDLINE_MAP) - continue; - - tgid = trace_find_tgid(pid); - r = sprintf(buf, "%d %d\n", pid, tgid); - buf += r; - len += r; - } - - len = simple_read_from_buffer(ubuf, cnt, ppos, - file_buf, len); - - kfree(file_buf); - - return len; -} - -static const struct file_operations tracing_saved_tgids_fops = { - .open = tracing_open_generic, - .read = tracing_saved_tgids_read, - .llseek = generic_file_llseek, -}; - static ssize_t tracing_set_trace_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -6257,9 +6167,6 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) trace_create_file("trace_marker", 0220, d_tracer, tr, &tracing_mark_fops); - trace_create_file("saved_tgids", 0444, d_tracer, - tr, &tracing_saved_tgids_fops); - trace_create_file("trace_clock", 0644, d_tracer, tr, &trace_clock_fops); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 79462443658d..aa0e736b72ac 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -653,7 +653,6 @@ static inline void __trace_stack(struct trace_array *tr, unsigned long flags, extern cycle_t ftrace_now(int cpu); extern void trace_find_cmdline(int pid, char comm[]); -extern int trace_find_tgid(int pid); #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; @@ -867,7 +866,6 @@ enum trace_iterator_flags { TRACE_ITER_IRQ_INFO = 0x800000, TRACE_ITER_MARKERS = 0x1000000, TRACE_ITER_FUNCTION = 0x2000000, - TRACE_ITER_TGID = 0x4000000, }; /* diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 055c4b95286e..111e6309d33b 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -702,25 +702,11 @@ int trace_print_context(struct trace_iterator *iter) unsigned long secs, usec_rem; char comm[TASK_COMM_LEN]; int ret; - int tgid; trace_find_cmdline(entry->pid, comm); - ret = trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid); - if (!ret) - return 0; - - if (trace_flags & TRACE_ITER_TGID) { - tgid = trace_find_tgid(entry->pid); - if (tgid < 0) - ret = trace_seq_puts(s, "(-----) "); - else - ret = trace_seq_printf(s, "(%5d) ", tgid); - if (!ret) - return 0; - } - - ret = trace_seq_printf(s, "[%03d] ", iter->cpu); + ret = trace_seq_printf(s, "%16s-%-5d [%03d] ", + comm, entry->pid, iter->cpu); if (!ret) return 0; From b8b468810f6e39d5c896ec6acac856bc74feb087 Mon Sep 17 00:00:00 2001 From: Krupal Divvela Date: Thu, 29 Dec 2016 18:00:04 +0530 Subject: [PATCH 012/210] ARM: dts: msm: Fix JPEG dts entries to 3.18 camera Update JPEG dt entries to 3.18 camera for JPEG to work on 3.10 kernel for 8952. CRs-Fixed: 1105801 Signed-off-by: Krupal Divvela Change-Id: I9b836c8202db0bb45ca6756b98358cbee26f53cb --- arch/arm/boot/dts/qcom/msm8952-camera.dtsi | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952-camera.dtsi b/arch/arm/boot/dts/qcom/msm8952-camera.dtsi index d53eab5c1103..e37f18f84afe 100644 --- a/arch/arm/boot/dts/qcom/msm8952-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952-camera.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-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 @@ -319,11 +319,12 @@ }; qcom,jpeg@1b1c000 { + status = "ok"; cell-index = <0>; compatible = "qcom,jpeg"; reg = <0x1b1c000 0x400>, <0x1b60000 0xc30>; - reg-names = "jpeg"; + reg-names = "jpeg_hw","jpeg_vbif"; interrupts = <0 59 0>; interrupt-names = "jpeg"; vdd-supply = <&gdsc_jpeg>; @@ -335,10 +336,15 @@ <&clock_gcc clk_gcc_camss_top_ahb_clk>, <&clock_gcc clk_gcc_camss_ahb_clk>; qcom,clock-rates = <266670000 0 0 0 0>; - qos-reg-settings = <0x28 0x0000550E>, - <0xC8 0x00005555>; - vbif-reg-settings = <0xC0 0x10101000>, + qcom,qos-reg-settings = <0x28 0x0000000E>, + <0xC8 0x00000000>; + qcom,vbif-reg-settings = <0xC0 0x10101000>, <0xB0 0x10100010>; + qcom,msm-bus,name = "msm_camera_jpeg0"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <62 512 0 0>, + <62 512 800000 800000>; }; qcom,irqrouter@1b00000 { From 7a8ee8ce09b5c0a192c6070a14d7d0c3378e14b8 Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Thu, 15 Dec 2016 08:13:20 -0700 Subject: [PATCH 013/210] net: ipc_router: Register services only on client port Allowing services to be registered on a non-client port will cause either an existing service or a control port to be over-written. This will cause undefined functional behavior. Allow the services to be registered only on client ports. CRs-Fixed: 1101792 Change-Id: If6cfc75e9314204b7b44957f1598a8a2e1a45325 Signed-off-by: Karthikeyan Ramasubramanian --- net/ipc_router/ipc_router_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 32e57c8bad8b..dcb4bab7cbce 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -2703,6 +2703,9 @@ int msm_ipc_router_register_server(struct msm_ipc_port *port_ptr, if (!port_ptr || !name) return -EINVAL; + if (port_ptr->type != CLIENT_PORT) + return -EINVAL; + if (name->addrtype != MSM_IPC_ADDR_NAME) return -EINVAL; From 50cd2bf13b6439030f521732aaf82262594b29ac Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Wed, 9 Nov 2016 16:25:24 -0800 Subject: [PATCH 014/210] msm: crypto: set CLR_CNTXT bit for crypto operations HLOS Crypto driver needs to set CLR_CNTXT bit for operations with legacy software key registers Change-Id: Iff482f726d106e99a4006f7077a171da3c7ca9c3 Signed-off-by: Zhen Kong --- drivers/crypto/msm/qce50.c | 43 +++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 686b62b8d583..bbdde2206c7f 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -1279,7 +1279,8 @@ go_proc: CRYPTO_CONFIG_REG)); /* issue go to crypto */ if (use_hw_key == false) { - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); } else { QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), @@ -1461,7 +1462,8 @@ static int _ce_setup_aead_direct(struct qce_device *pce_dev, CRYPTO_CONFIG_REG)); /* issue go to crypto */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -1781,7 +1783,8 @@ static int _ce_setup_cipher_direct(struct qce_device *pce_dev, CRYPTO_CONFIG_REG)); /* issue go to crypto */ if (use_hw_key == false) { - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); } else { QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), @@ -1869,7 +1872,8 @@ static int _ce_f9_setup_direct(struct qce_device *pce_dev, QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + CRYPTO_CONFIG_REG)); /* write go */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -1946,7 +1950,8 @@ static int _ce_f8_setup_direct(struct qce_device *pce_dev, QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + CRYPTO_CONFIG_REG)); /* write go */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -3024,8 +3029,8 @@ static int _setup_cipher_aes_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3137,8 +3142,8 @@ static int _setup_cipher_des_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3315,8 +3320,8 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3530,8 +3535,8 @@ static int _setup_aead_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3662,8 +3667,8 @@ static int _setup_aead_ccm_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3747,8 +3752,8 @@ static int _setup_f8_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3828,8 +3833,8 @@ static int _setup_f9_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; From 6c3d41026eb175d00dc0f2a09494b5c0d34dd04b Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Fri, 2 Sep 2016 22:09:23 -0700 Subject: [PATCH 015/210] qseecom: whitelist support for kernel client and listener Add whitelist support for listener to send modified resp to TZ; also add whitelist support for kernel client; and change the method to check whitelist feature. Change-Id: I0030b0008d6224cda3fdc1f80308a7e9bcfe4405 Signed-off-by: Zhen Kong Signed-off-by: Mallikarjuna Reddy Amireddy --- drivers/misc/qseecom.c | 325 +++++++++++++++++++++--------------- include/soc/qcom/qseecomi.h | 19 +++ 2 files changed, 209 insertions(+), 135 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 196e5c361116..dce142db95f2 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -119,6 +119,35 @@ static DEFINE_MUTEX(qsee_bw_mutex); static DEFINE_MUTEX(app_access_lock); static DEFINE_MUTEX(clk_access_lock); +struct sglist_info { + uint32_t indexAndFlags; + uint32_t sizeOrCount; +}; + +/* + * The 31th bit indicates only one or multiple physical address inside + * the request buffer. If it is set, the index locates a single physical addr + * inside the request buffer, and `sizeOrCount` is the size of the memory being + * shared at that physical address. + * Otherwise, the index locates an array of {start, len} pairs (a + * "scatter/gather list"), and `sizeOrCount` gives the number of entries in + * that array. + * + * The 30th bit indicates 64 or 32bit address; when it is set, physical addr + * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. + * + * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. + */ +#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ + ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) + +#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) + +#define FEATURE_ID_WHITELIST 15 /*whitelist feature id*/ + +#define MAKE_WHITELIST_VERSION(major, minor, patch) \ + (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF)) + struct qseecom_registered_listener_list { struct list_head list; struct qseecom_register_listener_req svc; @@ -133,6 +162,8 @@ struct qseecom_registered_listener_list { bool listener_in_use; /* wq for thread blocked on this listener*/ wait_queue_head_t listener_block_app_wq; + struct sglist_info sglistinfo_ptr[MAX_ION_FD]; + uint32_t sglist_cnt; }; struct qseecom_registered_app_list { @@ -246,30 +277,6 @@ struct qseecom_listener_handle { static struct qseecom_control qseecom; -struct sglist_info { - uint32_t indexAndFlags; - uint32_t sizeOrCount; -}; - -/* - * The 31th bit indicates only one or multiple physical address inside - * the request buffer. If it is set, the index locates a single physical addr - * inside the request buffer, and `sizeOrCount` is the size of the memory being - * shared at that physical address. - * Otherwise, the index locates an array of {start, len} pairs (a - * "scatter/gather list"), and `sizeOrCount` gives the number of entries in - * that array. - * - * The 30th bit indicates 64 or 32bit address; when it is set, physical addr - * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. - * - * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. - */ -#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ - ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) - -#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) - struct qseecom_dev_handle { enum qseecom_client_handle_type type; union { @@ -283,8 +290,9 @@ struct qseecom_dev_handle { bool perf_enabled; bool fast_load_enabled; enum qseecom_bandwidth_request_mode mode; - struct sglist_info *sglistinfo_ptr; + struct sglist_info sglistinfo_ptr[MAX_ION_FD]; uint32_t sglist_cnt; + bool use_legacy_cmd; }; struct qseecom_key_id_usage_desc { @@ -542,6 +550,34 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, ret = scm_call2(smc_id, &desc); break; } + case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: { + struct qseecom_client_listener_data_irsp *req; + struct qseecom_client_listener_data_64bit_irsp *req_64; + + smc_id = + TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID; + desc.arginfo = + TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID; + if (qseecom.qsee_version < QSEE_VERSION_40) { + req = + (struct qseecom_client_listener_data_irsp *) + req_buf; + desc.args[0] = req->listener_id; + desc.args[1] = req->status; + desc.args[2] = req->sglistinfo_ptr; + desc.args[3] = req->sglistinfo_len; + } else { + req_64 = + (struct qseecom_client_listener_data_64bit_irsp *) + req_buf; + desc.args[0] = req_64->listener_id; + desc.args[1] = req_64->status; + desc.args[2] = req_64->sglistinfo_ptr; + desc.args[3] = req_64->sglistinfo_len; + } + ret = scm_call2(smc_id, &desc); + break; + } case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: { struct qseecom_load_app_ireq *req; struct qseecom_load_app_64bit_ireq *req_64bit; @@ -1052,7 +1088,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, return -EBUSY; } - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); if (!new_entry) { pr_err("kmalloc failed\n"); return -ENOMEM; @@ -1508,6 +1544,16 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data, return ret; } +static void __qseecom_clean_listener_sglistinfo( + struct qseecom_registered_listener_list *ptr_svc) +{ + if (ptr_svc->sglist_cnt) { + memset(ptr_svc->sglistinfo_ptr, 0, + SGLISTINFO_TABLE_SIZE); + ptr_svc->sglist_cnt = 0; + } +} + static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) { @@ -1516,9 +1562,14 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, uint32_t lstnr; unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; + struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; struct qseecom_registered_listener_list *ptr_svc = NULL; sigset_t new_sigset; sigset_t old_sigset; + uint32_t status; + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = NULL; while (resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1530,6 +1581,7 @@ 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) { + ptr_svc->listener_in_use = true; ptr_svc->rcv_req_flag = 1; wake_up_interruptible(&ptr_svc->rcv_req_wq); break; @@ -1577,14 +1629,42 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", data->client.app_id, lstnr, ret); rc = -ENODEV; - send_data_rsp.status = QSEOS_RESULT_FAILURE; + status = QSEOS_RESULT_FAILURE; } else { - send_data_rsp.status = QSEOS_RESULT_SUCCESS; + status = QSEOS_RESULT_SUCCESS; } qseecom.send_resp_flag = 0; - send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; - send_data_rsp.listener_id = lstnr; + ptr_svc->send_resp_flag = 0; + table = ptr_svc->sglistinfo_ptr; + if (qseecom.qsee_version < QSEE_VERSION_40) { + send_data_rsp.listener_id = lstnr; + send_data_rsp.status = status; + send_data_rsp.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_rsp.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp; + cmd_len = sizeof(send_data_rsp); + } else { + send_data_rsp_64bit.listener_id = lstnr; + send_data_rsp_64bit.status = status; + send_data_rsp_64bit.sglistinfo_ptr = + virt_to_phys(table); + send_data_rsp_64bit.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp_64bit; + cmd_len = sizeof(send_data_rsp_64bit); + } + if (qseecom.whitelist_support == false) + *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; + else + *(uint32_t *)cmd_buf = + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; if (ptr_svc) msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, @@ -1594,9 +1674,9 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, __qseecom_enable_clk(CLK_QSEE); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - (const void *)&send_data_rsp, - sizeof(send_data_rsp), resp, - sizeof(*resp)); + cmd_buf, cmd_len, resp, sizeof(*resp)); + ptr_svc->listener_in_use = false; + __qseecom_clean_listener_sglistinfo(ptr_svc); if (ret) { pr_err("scm_call() failed with err: %d (app_id = %d)\n", ret, data->client.app_id); @@ -1629,9 +1709,14 @@ static int __qseecom_reentrancy_process_incomplete_cmd( uint32_t lstnr; unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; + struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; struct qseecom_registered_listener_list *ptr_svc = NULL; sigset_t new_sigset; sigset_t old_sigset; + uint32_t status; + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = NULL; while (resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1694,13 +1779,38 @@ static int __qseecom_reentrancy_process_incomplete_cmd( pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", data->client.app_id, lstnr, ret); rc = -ENODEV; - send_data_rsp.status = QSEOS_RESULT_FAILURE; + status = QSEOS_RESULT_FAILURE; } else { - send_data_rsp.status = QSEOS_RESULT_SUCCESS; + status = QSEOS_RESULT_SUCCESS; } - - send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; - send_data_rsp.listener_id = lstnr; + table = ptr_svc->sglistinfo_ptr; + if (qseecom.qsee_version < QSEE_VERSION_40) { + send_data_rsp.listener_id = lstnr; + send_data_rsp.status = status; + send_data_rsp.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp; + cmd_len = sizeof(send_data_rsp); + } else { + send_data_rsp_64bit.listener_id = lstnr; + send_data_rsp_64bit.status = status; + send_data_rsp_64bit.sglistinfo_ptr = + virt_to_phys(table); + send_data_rsp_64bit.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp_64bit; + cmd_len = sizeof(send_data_rsp_64bit); + } + if (qseecom.whitelist_support == false) + *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; + else + *(uint32_t *)cmd_buf = + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; if (ptr_svc) msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, @@ -1710,11 +1820,9 @@ static int __qseecom_reentrancy_process_incomplete_cmd( __qseecom_enable_clk(CLK_QSEE); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - (const void *)&send_data_rsp, - sizeof(send_data_rsp), resp, - sizeof(*resp)); - + cmd_buf, cmd_len, resp, sizeof(*resp)); ptr_svc->listener_in_use = false; + __qseecom_clean_listener_sglistinfo(ptr_svc); wake_up_interruptible(&ptr_svc->listener_block_app_wq); if (ret) { @@ -2708,7 +2816,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); } - if (qseecom.whitelist_support == false) + if (qseecom.whitelist_support == false || data->use_legacy_cmd == true) *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND; else *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; @@ -2813,6 +2921,8 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_send_modfd_cmd_req *req = NULL; struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; struct qseecom_registered_listener_list *this_lstnr = NULL; + uint32_t offset; + struct sg_table *sg_ptr; if ((data->type != QSEECOM_LISTENER_SERVICE) && (data->type != QSEECOM_CLIENT_APP)) @@ -2834,7 +2944,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, } for (i = 0; i < MAX_ION_FD; i++) { - struct sg_table *sg_ptr = NULL; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { ihandle = ion_import_dma_buf(qseecom.ion_clnt, @@ -2976,14 +3085,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); if (data->type == QSEECOM_CLIENT_APP) { + offset = req->ifd_data[i].cmd_buf_offset; data->sglistinfo_ptr[i].indexAndFlags = SGLISTINFO_SET_INDEX_FLAG( - (sg_ptr->nents == 1), 0, - req->ifd_data[i].cmd_buf_offset); + (sg_ptr->nents == 1), 0, offset); data->sglistinfo_ptr[i].sizeOrCount = (sg_ptr->nents == 1) ? sg->length : sg_ptr->nents; data->sglist_cnt = i + 1; + } else { + offset = (lstnr_resp->ifd_data[i].cmd_buf_offset + + (uintptr_t)lstnr_resp->resp_buf_ptr - + (uintptr_t)this_lstnr->sb_virt); + this_lstnr->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 0, offset); + this_lstnr->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + this_lstnr->sglist_cnt = i + 1; } } /* Deallocate the handle */ @@ -3056,6 +3176,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, struct qseecom_send_modfd_cmd_req *req = NULL; struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; struct qseecom_registered_listener_list *this_lstnr = NULL; + uint32_t offset; + struct sg_table *sg_ptr; if ((data->type != QSEECOM_LISTENER_SERVICE) && (data->type != QSEECOM_CLIENT_APP)) @@ -3077,7 +3199,6 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, } for (i = 0; i < MAX_ION_FD; i++) { - struct sg_table *sg_ptr = NULL; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { ihandle = ion_import_dma_buf(qseecom.ion_clnt, @@ -3194,14 +3315,25 @@ cleanup: ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); if (data->type == QSEECOM_CLIENT_APP) { + offset = req->ifd_data[i].cmd_buf_offset; data->sglistinfo_ptr[i].indexAndFlags = SGLISTINFO_SET_INDEX_FLAG( - (sg_ptr->nents == 1), 1, - req->ifd_data[i].cmd_buf_offset); + (sg_ptr->nents == 1), 1, offset); data->sglistinfo_ptr[i].sizeOrCount = (sg_ptr->nents == 1) ? sg->length : sg_ptr->nents; data->sglist_cnt = i + 1; + } else { + offset = (lstnr_resp->ifd_data[i].cmd_buf_offset + + (uintptr_t)lstnr_resp->resp_buf_ptr - + (uintptr_t)this_lstnr->sb_virt); + this_lstnr->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 1, offset); + this_lstnr->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + this_lstnr->sglist_cnt = i + 1; } } /* Deallocate the handle */ @@ -3916,21 +4048,12 @@ int qseecom_start_app(struct qseecom_handle **handle, data->client.user_virt_sb_base = 0; data->client.ihandle = NULL; - /* Allocate sglistinfo buffer for kernel client */ - data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); - if (!(data->sglistinfo_ptr)) { - kfree(data); - kfree(*handle); - *handle = NULL; - return -ENOMEM; - } init_waitqueue_head(&data->abort_wq); data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096, ION_HEAP(ION_QSECOM_HEAP_ID), 0); if (IS_ERR_OR_NULL(data->client.ihandle)) { pr_err("Ion client could not retrieve the handle\n"); - kfree(data->sglistinfo_ptr); kfree(data); kfree(*handle); *handle = NULL; @@ -4033,7 +4156,6 @@ int qseecom_start_app(struct qseecom_handle **handle, return 0; err: - kfree(data->sglistinfo_ptr); kfree(data); kfree(*handle); *handle = NULL; @@ -4075,7 +4197,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) mutex_unlock(&app_access_lock); if (ret == 0) { - kzfree(data->sglistinfo_ptr); kzfree(data); kzfree(*handle); kzfree(kclient); @@ -4135,8 +4256,11 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, } perf_enabled = true; } + if (!strcmp(data->client.app_name, "securemm")) + data->use_legacy_cmd = true; ret = __qseecom_send_cmd(data, &req); + data->use_legacy_cmd = false; if (qseecom.support_bus_scaling) __qseecom_add_bw_scale_down_timer( QSEECOM_SEND_CMD_CRYPTO_TIMEOUT); @@ -6776,6 +6900,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) wake_up_all(&data->abort_wq); if (ret) pr_err("failed qseecom_send_mod_resp: %d\n", ret); + __qseecom_clean_data_sglistinfo(data); break; } case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: { @@ -6901,12 +7026,6 @@ static int qseecom_open(struct inode *inode, struct file *file) data->mode = INACTIVE; init_waitqueue_head(&data->abort_wq); atomic_set(&data->ioctl_count, 0); - - data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); - if (!(data->sglistinfo_ptr)) { - kzfree(data); - return -ENOMEM; - } return ret; } @@ -6961,7 +7080,6 @@ static int qseecom_release(struct inode *inode, struct file *file) if (data->perf_enabled == true) qsee_disable_clock_vote(data, CLK_DFAB); } - kfree(data->sglistinfo_ptr); kfree(data); return ret; @@ -7103,73 +7221,14 @@ static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce) } /* - * Check if whitelist feature is supported by making a test scm_call - * to send a whitelist command to an invalid app ID 0 + * Check whitelist feature, and if TZ feature version is < 1.0.0, + * then whitelist feature is not supported. */ static int qseecom_check_whitelist_feature(void) { - struct qseecom_client_send_data_ireq send_data_req = {0}; - struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0}; - struct qseecom_command_scm_resp resp; - uint32_t buf_size = 128; - void *buf = NULL; - void *cmd_buf = NULL; - size_t cmd_len; - int ret = 0; - phys_addr_t pa; + int version = scm_get_feat_version(FEATURE_ID_WHITELIST); - buf = kzalloc(buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - pa = virt_to_phys(buf); - if (qseecom.qsee_version < QSEE_VERSION_40) { - send_data_req.qsee_cmd_id = - QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; - send_data_req.app_id = 0; - send_data_req.req_ptr = (uint32_t)pa; - send_data_req.req_len = buf_size; - send_data_req.rsp_ptr = (uint32_t)pa; - send_data_req.rsp_len = buf_size; - send_data_req.sglistinfo_ptr = (uint32_t)pa; - send_data_req.sglistinfo_len = buf_size; - cmd_buf = (void *)&send_data_req; - cmd_len = sizeof(struct qseecom_client_send_data_ireq); - } else { - send_data_req_64bit.qsee_cmd_id = - QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; - send_data_req_64bit.app_id = 0; - send_data_req_64bit.req_ptr = (uint64_t)pa; - send_data_req_64bit.req_len = buf_size; - send_data_req_64bit.rsp_ptr = (uint64_t)pa; - send_data_req_64bit.rsp_len = buf_size; - send_data_req_64bit.sglistinfo_ptr = (uint64_t)pa; - send_data_req_64bit.sglistinfo_len = buf_size; - cmd_buf = (void *)&send_data_req_64bit; - cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); - } - ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - cmd_buf, cmd_len, - &resp, sizeof(resp)); -/* - * If this cmd exists and whitelist is supported, scm_call return -2 (scm - * driver remap it to -EINVAL) and resp.result 0xFFFFFFED(-19); Otherwise, - * scm_call return -1 (remap to -EIO). - */ - if (ret == -EIO) { - qseecom.whitelist_support = false; - ret = 0; - } else if (ret == -EINVAL && - resp.result == QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD) { - qseecom.whitelist_support = true; - ret = 0; - } else { - pr_info("Check whitelist with ret = %d, result = 0x%x\n", - ret, resp.result); - qseecom.whitelist_support = false; - ret = 0; - } - kfree(buf); - return ret; + return version >= MAKE_WHITELIST_VERSION(1, 0, 0); } static int qseecom_probe(struct platform_device *pdev) @@ -7498,11 +7557,7 @@ static int qseecom_probe(struct platform_device *pdev) qseecom.qsee_perf_client = msm_bus_scale_register_client( qseecom_platform_support); - rc = qseecom_check_whitelist_feature(); - if (rc) { - rc = -EINVAL; - goto exit_destroy_ion_client; - } + qseecom.whitelist_support = qseecom_check_whitelist_feature(); pr_warn("qseecom.whitelist_support = %d\n", qseecom.whitelist_support); diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h index 50b10f91949f..03e0b461b68c 100644 --- a/include/soc/qcom/qseecomi.h +++ b/include/soc/qcom/qseecomi.h @@ -78,6 +78,7 @@ enum qseecom_qceos_cmd_id { QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C, QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D, QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E, + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST = 0x1F, QSEOS_FSM_OEM_FUSE_WRITE_ROW = 0x301, QSEOS_FSM_OEM_FUSE_READ_ROW = 0x302, QSEOS_CMD_MAX = 0xEFFFFFFF @@ -211,6 +212,16 @@ __packed struct qseecom_client_listener_data_irsp { uint32_t qsee_cmd_id; uint32_t listener_id; uint32_t status; + uint32_t sglistinfo_ptr; + uint32_t sglistinfo_len; +}; + +__packed struct qseecom_client_listener_data_64bit_irsp { + uint32_t qsee_cmd_id; + uint32_t listener_id; + uint32_t status; + uint64_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; /* @@ -679,4 +690,12 @@ __packed struct qseecom_client_send_fsm_key_req { TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ TZ_SYSCALL_PARAM_TYPE_VAL) +#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x05) + +#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_4( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \ + TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL) + #endif /* __QSEECOMI_H_ */ From d6b66bb3da125b654f88e549787e48effb6ffc81 Mon Sep 17 00:00:00 2001 From: John Dias Date: Mon, 10 Oct 2016 14:44:30 -0700 Subject: [PATCH 016/210] perf: protect group_leader from races that cause ctx double-free When moving a group_leader perf event from a software-context to a hardware-context, there's a race in checking and updating that context. The existing locking solution doesn't work; note that it tries to grab a lock inside the group_leader's context object, which you can only get at by going through a pointer that should be protected from these races. To avoid that problem, and to produce a simple solution, we can just use a lock per group_leader to protect all checks on the group_leader's context. The new lock is grabbed and released when no context locks are held. Bug: 30955111 Bug: 31095224 Change-Id: If37124c100ca6f4aa962559fba3bd5dbbec8e052 Git-repo: https://android.googlesource.com/kernel/msm.git Git-commit: 5b87e00be9ca28ea32cab49b92c0386e4a91f730 Signed-off-by: Dennis Cagle --- include/linux/perf_event.h | 6 ++++++ kernel/events/core.c | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 619d3240d25a..b10868f51332 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -317,6 +317,12 @@ struct perf_event { int nr_siblings; int group_flags; struct perf_event *group_leader; + + /* + * Protect the pmu, attributes and context of a group leader. + * Note: does not protect the pointer to the group_leader. + */ + struct mutex group_leader_mutex; struct pmu *pmu; enum perf_event_active_state state; diff --git a/kernel/events/core.c b/kernel/events/core.c index 250c39a5f84e..5c4b7f7ae69b 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6631,6 +6631,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, if (!group_leader) group_leader = event; + mutex_init(&event->group_leader_mutex); mutex_init(&event->child_mutex); INIT_LIST_HEAD(&event->child_list); @@ -7020,6 +7021,16 @@ SYSCALL_DEFINE5(perf_event_open, group_leader = NULL; } + /* + * Take the group_leader's group_leader_mutex before observing + * anything in the group leader that leads to changes in ctx, + * many of which may be changing on another thread. + * In particular, we want to take this lock before deciding + * whether we need to move_group. + */ + if (group_leader) + mutex_lock(&group_leader->group_leader_mutex); + if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) { task = find_lively_task_by_vpid(pid); if (IS_ERR(task)) { @@ -7202,6 +7213,8 @@ SYSCALL_DEFINE5(perf_event_open, put_ctx(gctx); } mutex_unlock(&ctx->mutex); + if (group_leader) + mutex_unlock(&group_leader->group_leader_mutex); put_online_cpus(); @@ -7237,6 +7250,8 @@ err_task: if (task) put_task_struct(task); err_group_fd: + if (group_leader) + mutex_unlock(&group_leader->group_leader_mutex); fdput(group); err_fd: put_unused_fd(event_fd); From d2aa222f6e84013c3e8169a7e94dc29339ad796e Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Thu, 14 May 2015 12:58:08 +0530 Subject: [PATCH 017/210] BACKPORT: Bluetooth: Fix potential NULL dereference in RFCOMM bind callback (cherry picked from 951b6a0717db97ce420547222647bcc40bf1eacd) addr can be NULL and it should not be dereferenced before NULL checking. Signed-off-by: Jaganath Kanakkassery Signed-off-by: Marcel Holtmann Change-Id: I18bda54bb1427d9443a39a04a5c551720118dc26 Bug: 30149612 Git-repo: https://android.googlesource.com/kernel/common.git Git-commit: dfc1f470349cd079624d46880c3654709df9005b Signed-off-by: Ravi Kumar Siddojigari --- net/bluetooth/rfcomm/sock.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 1e1e44be2c1e..08964520e333 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -329,15 +329,19 @@ static int rfcomm_sock_create(struct net *net, struct socket *sock, static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) { - struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; + struct sockaddr_rc sa; struct sock *sk = sock->sk; - int err = 0; - - BT_DBG("sk %pK %pMR", sk, &sa->rc_bdaddr); + int len, err = 0; if (!addr || addr->sa_family != AF_BLUETOOTH) return -EINVAL; + memset(&sa, 0, sizeof(sa)); + len = min_t(unsigned int, sizeof(sa), addr_len); + memcpy(&sa, addr, len); + + BT_DBG("sk %pK %pMR", sk, &sa.rc_bdaddr); + lock_sock(sk); if (sk->sk_state != BT_OPEN) { @@ -352,12 +356,12 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr write_lock(&rfcomm_sk_list.lock); - if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { + if (sa.rc_channel && __rfcomm_get_sock_by_addr(sa.rc_channel, &sa.rc_bdaddr)) { err = -EADDRINUSE; } else { /* Save source address */ - bacpy(&bt_sk(sk)->src, &sa->rc_bdaddr); - rfcomm_pi(sk)->channel = sa->rc_channel; + bacpy(&bt_sk(sk)->src, &sa.rc_bdaddr); + rfcomm_pi(sk)->channel = sa.rc_channel; sk->sk_state = BT_BOUND; } From 12e2488f451472236142f185ce46053ab29f71ac Mon Sep 17 00:00:00 2001 From: Brahmaji K Date: Tue, 13 Dec 2016 20:32:24 +0530 Subject: [PATCH 018/210] msm-3.18: drivers : added validation of input/output buffer sizes This change fixes issues reagrding the ioctl QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ uncovered by fuzzy tests. Modified handler of above ioctl, not to allow input/output buffer sizes greater than a fixed defined size. Change-Id: I69f94a29d939341564f6f3ebfda48fceaa934542 Signed-off-by: Brahmaji K --- drivers/misc/qseecom.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index dce142db95f2..64b496639a23 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -81,6 +81,9 @@ /* Encrypt/Decrypt Data Integrity Partition (DIP) for MDTP */ #define SCM_MDTP_CIPHER_DIP 0x01 +/* Maximum Allowed Size (128K) of Data Integrity Partition (DIP) for MDTP */ +#define MAX_DIP 0x20000 + #define RPMB_SERVICE 0x2000 #define SSD_SERVICE 0x3000 @@ -5678,7 +5681,8 @@ static int qseecom_mdtp_cipher_dip(void __user *argp) } if (req.in_buf == NULL || req.out_buf == NULL || - req.in_buf_size == 0 || req.out_buf_size == 0 || + req.in_buf_size == 0 || req.in_buf_size > MAX_DIP || + req.out_buf_size == 0 || req.out_buf_size > MAX_DIP || req.direction > 1) { pr_err("invalid parameters\n"); ret = -EINVAL; From 6b7ecac7774cd5f0169d72e2b7e6db0a63155589 Mon Sep 17 00:00:00 2001 From: Sharad Sangle Date: Tue, 13 Dec 2016 14:35:39 +0530 Subject: [PATCH 019/210] ASoC: msm: qdsp6v2: DAP: Add check to validate param length To avoid buffer overflow, validate input length used to fetch visualizer data. CRs-fixed: 1096672 Change-Id: I224bc2f20d94182713c565972fb0bd52cad6f3fd Signed-off-by: Sharad Sangle --- sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c index bb0f890d300f..5866e46cc6a2 100644 --- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 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. @@ -18,6 +18,10 @@ #include "msm-dolby-dap-config.h" +#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH +#define DOLBY_PARAM_VCNB_MAX_LENGTH 40 +#endif + /* dolby endp based parameters */ struct dolby_dap_endp_params_s { int device; @@ -896,6 +900,11 @@ int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol, uint32_t param_payload_len = DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t); int port_id, copp_idx, idx; + if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) { + pr_err("%s Incorrect VCNB length", __func__); + ucontrol->value.integer.value[0] = 0; + return -EINVAL; + } for (idx = 0; idx < AFE_MAX_PORTS; idx++) { port_id = dolby_dap_params_states.port_id[idx]; copp_idx = dolby_dap_params_states.copp_idx[idx]; From b7816672a14b69a33def3b82f8b9fac137cbab1b Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Wed, 7 Dec 2016 16:35:07 -0800 Subject: [PATCH 020/210] drivers: soc: qcom: Add error handling in function avtimer_ioctl Error handling is added to prevent garbage value being passed to user space by the uninitialized local variable avtimer_tick. CRs-Fixed: 1097878 Change-Id: I3f895deaae3acf329088cf8135859cc41e781763 Signed-off-by: Xiaoyu Ye --- drivers/platform/msm/avtimer.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/avtimer.c b/drivers/platform/msm/avtimer.c index b685c450e410..3aa4b3a1b709 100644 --- a/drivers/platform/msm/avtimer.c +++ b/drivers/platform/msm/avtimer.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -331,9 +331,17 @@ static long avtimer_ioctl(struct file *file, unsigned int ioctl_num, switch (ioctl_num) { case IOCTL_GET_AVTIMER_TICK: { - uint64_t avtimer_tick; + uint64_t avtimer_tick = 0; + int rc; + + rc = avcs_core_query_timer(&avtimer_tick); + + if (rc) { + pr_err("%s: Error: Invalid AV Timer tick, rc = %d\n", + __func__, rc); + return rc; + } - avcs_core_query_timer(&avtimer_tick); pr_debug_ratelimited("%s: AV Timer tick: time %llx\n", __func__, avtimer_tick); if (copy_to_user((void *) ioctl_param, &avtimer_tick, From b4e374926ddc325840cda704aea1eb0c49d7f0e3 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 30 Nov 2016 14:41:24 -0800 Subject: [PATCH 021/210] msm: ipa: fix the potential heap overflow on wan-driver Add the check on rmnet_ipa3_set_tether_client_pipe API to make sure not accessing move than QMI_IPA_MAX_PIPES_V01 entries when user-space module compromised. Change-Id: I59d39c7e5743dfea17853b6c4709605d4ebae962 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/rmnet_ipa.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c index ddae8c5bf85d..c274ee1adacb 100644 --- a/drivers/platform/msm/ipa/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/rmnet_ipa.c @@ -2426,7 +2426,7 @@ int rmnet_ipa_set_data_quota(struct wan_ioctl_set_data_quota *data) * * Return codes: * 0: Success - * -EFAULT: Invalid interface name provided + * -EFAULT: Invalid src/dst pipes provided * other: See ipa_qmi_set_data_quota */ int rmnet_ipa_set_tether_client_pipe( @@ -2434,6 +2434,23 @@ int rmnet_ipa_set_tether_client_pipe( { int number, i; + /* error checking if ul_src_pipe_len valid or not*/ + if (data->ul_src_pipe_len > QMI_IPA_MAX_PIPES_V01 || + data->ul_src_pipe_len < 0) { + IPAWANERR("UL src pipes %d exceeding max %d\n", + data->ul_src_pipe_len, + QMI_IPA_MAX_PIPES_V01); + return -EFAULT; + } + /* error checking if dl_dst_pipe_len valid or not*/ + if (data->dl_dst_pipe_len > QMI_IPA_MAX_PIPES_V01 || + data->dl_dst_pipe_len < 0) { + IPAWANERR("DL dst pipes %d exceeding max %d\n", + data->dl_dst_pipe_len, + QMI_IPA_MAX_PIPES_V01); + return -EFAULT; + } + IPAWANDBG("client %d, UL %d, DL %d, reset %d\n", data->ipa_client, data->ul_src_pipe_len, From c9198deaef8e0dbefce0573670d722f78befd47e Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Wed, 7 Dec 2016 18:19:31 -0800 Subject: [PATCH 022/210] ASoC: wcd9320: Fix out of bounds for mad input value Add check in taiko_mad_input_put function to return error on out of bounds access using mad input value CRs-fixed: 1096799 Change-Id: I75ce9e881cf05a50e874a555b2f8bd3286cdaed4 Signed-off-by: Karthikeyan Mani --- sound/soc/codecs/wcd9320.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c index 3fbd94769e15..9b9c63700a68 100644 --- a/sound/soc/codecs/wcd9320.c +++ b/sound/soc/codecs/wcd9320.c @@ -1204,6 +1204,14 @@ static int taiko_mad_input_put(struct snd_kcontrol *kcontrol, taiko_mad_input = ucontrol->value.integer.value[0]; + if (taiko_mad_input >= ARRAY_SIZE(taiko_conn_mad_text)) { + dev_err(codec->dev, + "%s: taiko_mad_input = %d out of bounds\n", + __func__, taiko_mad_input); + return -EINVAL; + } + + micb_4_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias; pr_debug("%s: taiko_mad_input = %s\n", __func__, taiko_conn_mad_text[taiko_mad_input]); From 424c78e96d6f6f6b28dd2d05e79b631ad6642ebe Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Wed, 7 Dec 2016 17:39:55 -0800 Subject: [PATCH 023/210] ASoC: wcd9330: Fix out of bounds for mad input value Add check in tomtom_mad_input_put function to return error on out of bounds access using mad input value. CRs-fixed: 1096799 Change-Id: Ied86bf88301e555b25eaa190d2d786cdad691ccd Signed-off-by: Karthikeyan Mani --- sound/soc/codecs/wcd9330.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c index 14e28045703b..8f4de8137671 100644 --- a/sound/soc/codecs/wcd9330.c +++ b/sound/soc/codecs/wcd9330.c @@ -1392,6 +1392,13 @@ static int tomtom_mad_input_put(struct snd_kcontrol *kcontrol, tomtom_mad_input = ucontrol->value.integer.value[0]; micb_4_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias; + if (tomtom_mad_input >= ARRAY_SIZE(tomtom_conn_mad_text)) { + dev_err(codec->dev, + "%s: tomtom_mad_input = %d out of bounds\n", + __func__, tomtom_mad_input); + return -EINVAL; + } + pr_debug("%s: tomtom_mad_input = %s\n", __func__, tomtom_conn_mad_text[tomtom_mad_input]); From 1e895f47043b57e1f44a1460f2ebfe1733b70245 Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Wed, 14 Dec 2016 11:46:35 -0800 Subject: [PATCH 024/210] ASoC: wcd9335: Fix out of bounds for mad input value Add check in tasha_mad_input_put function to return error on out of bounds access using mad input value. CRs-fixed: 1096799 Change-Id: Iddaa3fef362f7cb1919aa3bd8dd4b83133fe7c97 Signed-off-by: Karthikeyan Mani --- sound/soc/codecs/wcd9335.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index e4cdd4da5e8d..1d282146a104 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -7160,6 +7160,13 @@ static int tasha_mad_input_put(struct snd_kcontrol *kcontrol, tasha_mad_input = ucontrol->value.integer.value[0]; + if (tasha_mad_input >= ARRAY_SIZE(tasha_conn_mad_text)) { + dev_err(codec->dev, + "%s: tasha_mad_input = %d out of bounds\n", + __func__, tasha_mad_input); + return -EINVAL; + } + if (!strcmp(tasha_conn_mad_text[tasha_mad_input], "NOTUSED1") || !strcmp(tasha_conn_mad_text[tasha_mad_input], "NOTUSED2") || !strcmp(tasha_conn_mad_text[tasha_mad_input], "NOTUSED3") || From ae6485b9656470e9a64d5320cb8efd5820ddec8d Mon Sep 17 00:00:00 2001 From: Xiaojun Sang Date: Fri, 16 Dec 2016 16:25:27 +0800 Subject: [PATCH 025/210] ASoC: soc: msm: initialize buffer to prevent kernel data leakage To prevent potential kernel stack data leakage, initialize channel_map[]. CRs-Fixed: 1100878 Change-Id: I7b81cea20485bc7514551672bb54c7fd455049e3 Signed-off-by: Xiaojun Sang --- sound/soc/msm/qdsp6v2/msm-qti-pp-config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c index 1eeb577b0ed4..94d6cf7a7c7f 100644 --- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c @@ -484,7 +484,7 @@ static int msm_qti_pp_set_auxpcm_lb_vol_mixer(struct snd_kcontrol *kcontrol, static int msm_qti_pp_get_channel_map_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL]; + char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL] = {0}; int i; adm_get_multi_ch_map(channel_map, ADM_PATH_PLAYBACK); From 4052deb6db67ee758dae31b4419e65d8547049db Mon Sep 17 00:00:00 2001 From: Yan He Date: Wed, 2 Nov 2016 11:51:10 -0700 Subject: [PATCH 026/210] msm: sps: add the checking of userspace input length Add the checking of the input length from userspace so kernel space will not copy any content outside the input buffer. Change-Id: I3cef834ed1df836356ba40e6e950a534ec49819d Signed-off-by: Yan He --- drivers/platform/msm/sps/sps.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c index 8e13a51674ac..b2ab92bacce3 100644 --- a/drivers/platform/msm/sps/sps.c +++ b/drivers/platform/msm/sps/sps.c @@ -125,9 +125,10 @@ static ssize_t sps_set_info(struct file *file, const char __user *buf, int i; u32 buf_size_kb = 0; u32 new_buf_size; + u32 size = sizeof(str) < count ? sizeof(str) : count; memset(str, 0, sizeof(str)); - missing = copy_from_user(str, buf, sizeof(str)); + missing = copy_from_user(str, buf, size); if (missing) return -EFAULT; @@ -215,9 +216,10 @@ static ssize_t sps_set_logging_option(struct file *file, const char __user *buf, char str[MAX_MSG_LEN]; int i; u8 option = 0; + u32 size = sizeof(str) < count ? sizeof(str) : count; memset(str, 0, sizeof(str)); - missing = copy_from_user(str, buf, sizeof(str)); + missing = copy_from_user(str, buf, size); if (missing) return -EFAULT; @@ -264,9 +266,10 @@ static ssize_t sps_set_bam_addr(struct file *file, const char __user *buf, struct sps_bam *bam; u32 num_pipes = 0; void *vir_addr; + u32 size = sizeof(str) < count ? sizeof(str) : count; memset(str, 0, sizeof(str)); - missing = copy_from_user(str, buf, sizeof(str)); + missing = copy_from_user(str, buf, size); if (missing) return -EFAULT; From 530f3a0fd837ed105eddaf99810bc13d97dc4302 Mon Sep 17 00:00:00 2001 From: Bhalchandra Gajare Date: Thu, 15 Dec 2016 16:43:45 -0800 Subject: [PATCH 027/210] ASoC: msm-lsm-client: cleanup ioctl functions Some of the ioctl command handling is not properly using the copy_from_user interface. Fix these issues and cleanup the ioctl functions to make sure there is no illegal memory access. CRs-Fixed: 1087469 Change-Id: Ieb1beb92e7854a05b8045de0ce179d12c9a6da74 Signed-off-by: Bhalchandra Gajare --- sound/soc/msm/qdsp6v2/msm-lsm-client.c | 131 ++++++++----------------- 1 file changed, 40 insertions(+), 91 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c index 32a16bf30dc3..c365220b33c0 100644 --- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c +++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c @@ -727,8 +727,13 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_LSM_SET_SESSION_DATA: dev_dbg(rtd->dev, "%s: set session data\n", __func__); - memcpy(&session_data, arg, - sizeof(struct snd_lsm_session_data)); + if (copy_from_user(&session_data, arg, + sizeof(session_data))) { + dev_err(rtd->dev, "%s: %s: copy_from_user failed\n", + __func__, "LSM_SET_SESSION_DATA"); + return -EFAULT; + } + if (session_data.app_id != LSM_VOICE_WAKEUP_APP_ID_V2) { dev_err(rtd->dev, "%s:Invalid App id %d for Listen client\n", @@ -817,13 +822,6 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_SET_PARAMS: - if (!arg) { - dev_err(rtd->dev, - "%s: %s Invalid argument\n", - __func__, "SNDRV_LSM_SET_PARAMS"); - return -EINVAL; - } - dev_dbg(rtd->dev, "%s: set_params\n", __func__); memcpy(&det_params, arg, sizeof(det_params)); @@ -975,45 +973,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; } case SNDRV_LSM_LAB_CONTROL: { - u32 *enable = NULL; - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid param arg for ioctl %s session %d\n", - __func__, "SNDRV_LSM_LAB_CONTROL", - prtd->lsm_client->session); - rc = -EINVAL; - break; + u32 enable; + + if (copy_from_user(&enable, arg, sizeof(enable))) { + dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n", + __func__, "LSM_LAB_CONTROL"); + return -EFAULT; } - enable = (int *)arg; + dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n", - __func__, "SNDRV_LSM_LAB_CONTROL", *enable); + __func__, "SNDRV_LSM_LAB_CONTROL", enable); if (!prtd->lsm_client->started) { - if (prtd->lsm_client->lab_enable == *enable) { + if (prtd->lsm_client->lab_enable == enable) { dev_dbg(rtd->dev, "%s: Lab for session %d already %s\n", __func__, prtd->lsm_client->session, - ((*enable) ? "enabled" : "disabled")); + enable ? "enabled" : "disabled"); rc = 0; break; } - rc = q6lsm_lab_control(prtd->lsm_client, *enable); + rc = q6lsm_lab_control(prtd->lsm_client, enable); if (rc) { dev_err(rtd->dev, "%s: ioctl %s failed rc %d to %s lab for session %d\n", __func__, "SNDRV_LAB_CONTROL", rc, - ((*enable) ? "enable" : "disable"), + enable ? "enable" : "disable", prtd->lsm_client->session); } else { rc = msm_lsm_lab_buffer_alloc(prtd, - ((*enable) ? LAB_BUFFER_ALLOC - : LAB_BUFFER_DEALLOC)); + enable ? LAB_BUFFER_ALLOC + : LAB_BUFFER_DEALLOC); if (rc) dev_err(rtd->dev, "%s: msm_lsm_lab_buffer_alloc failed rc %d for %s", __func__, rc, - ((*enable) ? "ALLOC" : "DEALLOC")); + enable ? "ALLOC" : "DEALLOC"); if (!rc) - prtd->lsm_client->lab_enable = *enable; + prtd->lsm_client->lab_enable = enable; } } else { dev_err(rtd->dev, "%s: ioctl %s issued after start", @@ -1060,12 +1056,6 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, return rc; } #ifdef CONFIG_COMPAT -struct snd_lsm_event_status32 { - u16 status; - u16 payload_size; - u8 payload[0]; -}; - struct snd_lsm_sound_model_v2_32 { compat_uptr_t data; compat_uptr_t confidence_level; @@ -1097,8 +1087,6 @@ struct snd_lsm_module_params_32 { }; enum { - SNDRV_LSM_EVENT_STATUS32 = - _IOW('U', 0x02, struct snd_lsm_event_status32), SNDRV_LSM_REG_SND_MODEL_V2_32 = _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), SNDRV_LSM_SET_PARAMS_32 = @@ -1129,12 +1117,12 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, prtd = runtime->private_data; switch (cmd) { - case SNDRV_LSM_EVENT_STATUS32: { - struct snd_lsm_event_status32 userarg32, *user32 = NULL; - struct snd_lsm_event_status *user = NULL; + case SNDRV_LSM_EVENT_STATUS: { + struct snd_lsm_event_status *user = NULL, userarg32; + struct snd_lsm_event_status *user32 = NULL; if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", - __func__, "SNDRV_LSM_EVENT_STATUS32"); + __func__, "SNDRV_LSM_EVENT_STATUS"); return -EFAULT; } @@ -1288,13 +1276,6 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, return -EINVAL; } - if (!arg) { - dev_err(rtd->dev, - "%s: %s: No Param data to set\n", - __func__, "SET_MODULE_PARAMS_32"); - return -EINVAL; - } - if (copy_from_user(&p_data_32, arg, sizeof(p_data_32))) { dev_err(rtd->dev, @@ -1379,6 +1360,19 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, kfree(params32); break; } + case SNDRV_LSM_REG_SND_MODEL_V2: + case SNDRV_LSM_SET_PARAMS: + case SNDRV_LSM_SET_MODULE_PARAMS: + /* + * In ideal cases, the compat_ioctl should never be called + * with the above unlocked ioctl commands. Print error + * and return error if it does. + */ + dev_err(rtd->dev, + "%s: Invalid cmd for compat_ioctl\n", + __func__); + err = -EINVAL; + break; default: err = msm_lsm_ioctl_shared(substream, cmd, arg); break; @@ -1394,7 +1388,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, { int err = 0; u32 size = 0; - struct snd_lsm_session_data session_data; struct snd_pcm_runtime *runtime; struct snd_soc_pcm_runtime *rtd; struct lsm_priv *prtd; @@ -1409,26 +1402,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, rtd = substream->private_data; switch (cmd) { - case SNDRV_LSM_SET_SESSION_DATA: - dev_dbg(rtd->dev, - "%s: SNDRV_LSM_SET_SESSION_DATA\n", - __func__); - if (copy_from_user(&session_data, (void *)arg, - sizeof(struct snd_lsm_session_data))) { - err = -EFAULT; - dev_err(rtd->dev, - "%s: copy from user failed, size %zd\n", - __func__, sizeof(struct snd_lsm_session_data)); - break; - } - if (!err) - err = msm_lsm_ioctl_shared(substream, - cmd, &session_data); - if (err) - dev_err(rtd->dev, - "%s REG_SND_MODEL failed err %d\n", - __func__, err); - break; case SNDRV_LSM_REG_SND_MODEL_V2: { struct snd_lsm_sound_model_v2 snd_model_v2; @@ -1439,11 +1412,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, return -EINVAL; } - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid params snd_model\n", __func__); - return -EINVAL; - } if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) { err = -EFAULT; dev_err(rtd->dev, @@ -1472,12 +1440,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, } pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__); - if (!arg) { - dev_err(rtd->dev, - "%s: %s, Invalid params\n", - __func__, "SNDRV_LSM_SET_PARAMS"); - return -EINVAL; - } if (copy_from_user(&det_params, arg, sizeof(det_params))) { @@ -1510,13 +1472,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, return -EINVAL; } - if (!arg) { - dev_err(rtd->dev, - "%s: %s: No Param data to set\n", - __func__, "SET_MODULE_PARAMS"); - return -EINVAL; - } - if (copy_from_user(&p_data, arg, sizeof(p_data))) { dev_err(rtd->dev, @@ -1574,12 +1529,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, struct snd_lsm_event_status *user = NULL, userarg; dev_dbg(rtd->dev, "%s: SNDRV_LSM_EVENT_STATUS\n", __func__); - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid params event status\n", - __func__); - return -EINVAL; - } if (copy_from_user(&userarg, arg, sizeof(userarg))) { dev_err(rtd->dev, "%s: err copyuser event_status\n", From 5d1fe9c1fabb1245d04fdac1d6a87a84a5abab2a Mon Sep 17 00:00:00 2001 From: Hamad Kadmany Date: Sun, 18 Dec 2016 15:03:11 +0200 Subject: [PATCH 028/210] wil6210: Block write ioctl to the card by default The ability to write to the card is used for debug purposes. The ability is disabled by default to prevent misuse of this functionality. CRs-Fixed: 1096945 Change-Id: I8fc3f646a0127ec705239be6a7de858a4f805acc Signed-off-by: Hamad Kadmany --- drivers/net/wireless/ath/wil6210/Kconfig | 11 +++++++++++ drivers/net/wireless/ath/wil6210/ioctl.c | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index 481680a3aa55..eaa5a9d5e5cf 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -40,6 +40,17 @@ config WIL6210_TRACING If unsure, say Y to make it easier to debug problems. +config WIL6210_WRITE_IOCTL + bool "wil6210 write ioctl to the device" + depends on WIL6210 + default n + ---help--- + Say Y here to allow write-access from user-space to + the device memory through ioctl. This is useful for + debugging purposes only. + + If unsure, say N. + config WIL6210_PLATFORM_MSM bool "wil6210 MSM platform specific support" depends on WIL6210 diff --git a/drivers/net/wireless/ath/wil6210/ioctl.c b/drivers/net/wireless/ath/wil6210/ioctl.c index e9c0673819c6..f5ad47312450 100644 --- a/drivers/net/wireless/ath/wil6210/ioctl.c +++ b/drivers/net/wireless/ath/wil6210/ioctl.c @@ -79,10 +79,12 @@ static int wil_ioc_memio_dword(struct wil6210_priv *wil, void __user *data) io.val = ioread32(a); need_copy = true; break; +#if defined(CONFIG_WIL6210_WRITE_IOCTL) case wil_mmio_write: iowrite32(io.val, a); wmb(); /* make sure write propagated to HW */ break; +#endif default: wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op); return -EINVAL; @@ -139,6 +141,7 @@ static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data) goto out_free; } break; +#if defined(CONFIG_WIL6210_WRITE_IOCTL) case wil_mmio_write: if (copy_from_user(block, io.block, io.size)) { rc = -EFAULT; @@ -148,6 +151,7 @@ static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data) wmb(); /* make sure write propagated to HW */ wil_hex_dump_ioctl("Write ", block, io.size); break; +#endif default: wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op); rc = -EINVAL; From 0f99ef83f749679fb359ff2db3e35fb750e0adbc Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Wed, 4 Jan 2017 14:59:16 +0530 Subject: [PATCH 029/210] msm-camera: Addressing possible overflow conditions Changes to address possible integer overflow and incorrect array indexing conditions. -Fix checkpatch.pl warnings. CRs-Fixed: 897259 Change-Id: Ib134320cd6f7b34d7a10572ec347ec12127049a9 Signed-off-by: Trilokesh Rangam Signed-off-by: Yang Guang Signed-off-by: VijayaKumar T M --- .../msm/camera_v2/sensor/io/msm_camera_io_util.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c index 29ed44ab3db8..b61307099577 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c @@ -42,6 +42,7 @@ void msm_camera_io_w_mb(u32 data, void __iomem *addr) u32 msm_camera_io_r(void __iomem *addr) { uint32_t data = readl_relaxed(addr); + CDBG("%s: 0x%pK %08x\n", __func__, (addr), (data)); return data; } @@ -49,6 +50,7 @@ u32 msm_camera_io_r(void __iomem *addr) u32 msm_camera_io_r_mb(void __iomem *addr) { uint32_t data; + rmb(); data = readl_relaxed(addr); rmb(); @@ -73,6 +75,7 @@ void msm_camera_io_dump(void __iomem *addr, int size) int i; u32 *p = (u32 *) addr; u32 data; + CDBG("%s: %pK %d\n", __func__, addr, size); line_str[0] = '\0'; p_str = line_str; @@ -152,6 +155,7 @@ int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, int i; int rc = 0; long clk_rate; + if (enable) { for (i = 0; i < num_clk; i++) { CDBG("%s enable %s\n", __func__, clk_info[i].clk_name); @@ -258,6 +262,12 @@ int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg, pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__); return -EINVAL; } + + if (cam_vreg == NULL) { + pr_err("%s:%d cam_vreg sequence invalid\n", __func__, __LINE__); + return -EINVAL; + } + if (!num_vreg_seq) num_vreg_seq = num_vreg; @@ -434,6 +444,7 @@ void msm_camera_bus_scale_cfg(uint32_t bus_perf_client, enum msm_bus_perf_setting perf_setting) { int rc = 0; + if (!bus_perf_client) { pr_err("%s: Bus Client NOT Registered!!!\n", __func__); return; From a9e79718d18fa35205716a462fd64502c5b56d92 Mon Sep 17 00:00:00 2001 From: Xiaojun Sang Date: Mon, 10 Oct 2016 15:44:23 +0800 Subject: [PATCH 030/210] ASoC: qdsp6v2: fix potential bug of infinite loop When variable bufsz equals to 0, there would be infinite loop at q6asm_audio_client_buf_alloc. Fix the potential bug by checking bufsz beforehand. CRs-Fixed: 1072280 Change-Id: I9640112b8945dc603e3af55fc1096bea9f7e6634 Signed-off-by: Xiaojun Sang --- sound/soc/msm/qdsp6v2/q6asm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 071ea9407be7..22af1c3ac648 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1093,8 +1093,9 @@ int q6asm_audio_client_buf_alloc(unsigned int dir, struct audio_buffer *buf; size_t len; - if (!(ac) || ((dir != IN) && (dir != OUT))) { - pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + if (!(ac) || !(bufsz) || ((dir != IN) && (dir != OUT))) { + pr_err("%s: ac %pK bufsz %d dir %d\n", __func__, ac, bufsz, + dir); return -EINVAL; } From 1a0bf95d9ac110324a3e3e4faea332c4441246ee Mon Sep 17 00:00:00 2001 From: Xiaojun Sang Date: Fri, 4 Nov 2016 14:35:58 +0800 Subject: [PATCH 031/210] ASoC: soc: prevent risk of buffer overflow In case of large value for bufcnt_t or bufcnt, cmd_size may overflow. Buffer size allocated by cmd_size might be not as expected. Possible buffer overflow could happen. CRs-Fixed: 1084210 Change-Id: I9556f18dd6a9fdf3f76c133ae75c04ecce171f08 Signed-off-by: Xiaojun Sang --- sound/soc/msm/qdsp6v2/q6asm.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 071ea9407be7..d5b6187ed96d 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -5056,7 +5056,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, struct asm_buffer_node *buffer_node = NULL; int rc = 0; int i = 0; - int cmd_size = 0; + uint32_t cmd_size = 0; uint32_t bufcnt_t; uint32_t bufsz_t; @@ -5078,10 +5078,25 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, bufsz_t = PAGE_ALIGN(bufsz_t); } + if (bufcnt_t > (UINT_MAX + - sizeof(struct avs_cmd_shared_mem_map_regions)) + / sizeof(struct avs_shared_map_region_payload)) { + pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n", + __func__, bufcnt_t); + return -EINVAL; + } + cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) + (sizeof(struct avs_shared_map_region_payload) * bufcnt_t); + + if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) { + pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n", + __func__, bufcnt); + return -EINVAL; + } + buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, GFP_KERNEL); if (!buffer_node) { From be8fe7f973b934da1c4ab3969720ed14f78b97b4 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Tue, 3 Jan 2017 12:11:18 +0200 Subject: [PATCH 032/210] msm: rndis_ipa: Remove rndis_ipa loopback functionality Rndis_ipa loopback functionality at rndis_ipa driver is a debug functionality that is not used. Change-Id: Ibbcb26d3871cffeb46b028efcf4d428e88eb9e10 CRs-fixed: 1104431 Signed-off-by: Ghanim Fodi --- drivers/net/ethernet/msm/rndis_ipa.c | 432 +-------------------------- 1 file changed, 1 insertion(+), 431 deletions(-) diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c index 09b85fb32d4f..c61e2a72040f 100644 --- a/drivers/net/ethernet/msm/rndis_ipa.c +++ b/drivers/net/ethernet/msm/rndis_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2017 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 @@ -132,29 +132,6 @@ enum rndis_ipa_operation { RNDIS_IPA_DEBUG("Driver state: %s\n",\ rndis_ipa_state_string(ctx->state)); -/** - * struct rndis_loopback_pipe - hold all information needed for - * pipe loopback logic - */ -struct rndis_loopback_pipe { - struct sps_pipe *ipa_sps; - struct ipa_sps_params ipa_sps_connect; - struct ipa_connect_params ipa_connect_params; - - struct sps_pipe *dma_sps; - struct sps_connect dma_connect; - - struct sps_alloc_dma_chan dst_alloc; - struct sps_dma_chan ipa_sps_channel; - enum sps_mode mode; - u32 ipa_peer_bam_hdl; - u32 peer_pipe_index; - u32 ipa_drv_ep_hdl; - u32 ipa_pipe_index; - enum ipa_client_type ipa_client; - ipa_notify_cb ipa_callback; - struct ipa_ep_cfg *ipa_ep_cfg; -}; /** * struct rndis_ipa_dev - main driver context parameters @@ -169,13 +146,9 @@ struct rndis_loopback_pipe { * @rx_dump_enable: dump all Rx packets * @icmp_filter: allow all ICMP packet to pass through the filters * @rm_enable: flag that enable/disable Resource manager request prior to Tx - * @loopback_enable: flag that enable/disable USB stub loopback * @deaggregation_enable: enable/disable IPA HW deaggregation logic * @during_xmit_error: flags that indicate that the driver is in a middle * of error handling in Tx path - * @usb_to_ipa_loopback_pipe: usb to ipa (Rx) pipe representation for loopback - * @ipa_to_usb_loopback_pipe: ipa to usb (Tx) pipe representation for loopback - * @bam_dma_hdl: handle representing bam-dma, used for loopback logic * @directory: holds all debug flags used by the driver to allow cleanup * for driver unload * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table @@ -205,12 +178,8 @@ struct rndis_ipa_dev { u32 rx_dump_enable; u32 icmp_filter; u32 rm_enable; - bool loopback_enable; u32 deaggregation_enable; u32 during_xmit_error; - struct rndis_loopback_pipe usb_to_ipa_loopback_pipe; - struct rndis_loopback_pipe ipa_to_usb_loopback_pipe; - u32 bam_dma_hdl; struct dentry *directory; uint32_t eth_ipv4_hdr_hdl; uint32_t eth_ipv6_hdr_hdl; @@ -274,31 +243,12 @@ static int resource_request(struct rndis_ipa_dev *rndis_ipa_ctx); static void resource_release(struct rndis_ipa_dev *rndis_ipa_ctx); static netdev_tx_t rndis_ipa_start_xmit(struct sk_buff *skb, struct net_device *net); -static int rndis_ipa_loopback_pipe_create( - struct rndis_ipa_dev *rndis_ipa_ctx, - struct rndis_loopback_pipe *loopback_pipe); -static void rndis_ipa_destroy_loopback_pipe( - struct rndis_loopback_pipe *loopback_pipe); -static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); -static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); -static int rndis_ipa_setup_loopback(bool enable, - struct rndis_ipa_dev *rndis_ipa_ctx); -static int rndis_ipa_debugfs_loopback_open(struct inode *inode, - struct file *file); static int rndis_ipa_debugfs_atomic_open(struct inode *inode, struct file *file); static int rndis_ipa_debugfs_aggr_open(struct inode *inode, struct file *file); static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); -static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos); static void rndis_ipa_dump_skb(struct sk_buff *skb); @@ -333,12 +283,6 @@ const struct file_operations rndis_ipa_debugfs_atomic_ops = { .read = rndis_ipa_debugfs_atomic_read, }; -const struct file_operations rndis_ipa_loopback_ops = { - .open = rndis_ipa_debugfs_loopback_open, - .read = rndis_ipa_debugfs_loopback_read, - .write = rndis_ipa_debugfs_loopback_write, -}; - const struct file_operations rndis_ipa_aggr_ops = { .open = rndis_ipa_debugfs_aggr_open, .write = rndis_ipa_debugfs_aggr_write, @@ -2188,14 +2132,6 @@ static int rndis_ipa_debugfs_init(struct rndis_ipa_dev *rndis_ipa_ctx) goto fail_file; } - file = debugfs_create_file("loopback_enable", flags_read_write, - rndis_ipa_ctx->directory, - rndis_ipa_ctx, &rndis_ipa_loopback_ops); - if (!file) { - RNDIS_IPA_ERROR("could not create outstanding file\n"); - goto fail_file; - } - file = debugfs_create_u8("state", flags_read_only, rndis_ipa_ctx->directory, (u8 *)&rndis_ipa_ctx->state); if (!file) { @@ -2351,59 +2287,6 @@ static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, return count; } -static int rndis_ipa_debugfs_loopback_open(struct inode *inode, - struct file *file) -{ - struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; - file->private_data = rndis_ipa_ctx; - - return 0; -} - -static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int cnt; - struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; - - file->private_data = &rndis_ipa_ctx->loopback_enable; - - cnt = rndis_ipa_debugfs_enable_read(file, - ubuf, count, ppos); - - return cnt; -} - -static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - int retval; - int cnt; - struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; - bool old_state = rndis_ipa_ctx->loopback_enable; - - file->private_data = &rndis_ipa_ctx->loopback_enable; - - cnt = rndis_ipa_debugfs_enable_write(file, - buf, count, ppos); - - RNDIS_IPA_DEBUG("loopback_enable was set to:%d->%d\n", - old_state, rndis_ipa_ctx->loopback_enable); - - if (old_state == rndis_ipa_ctx->loopback_enable) { - RNDIS_IPA_ERROR("NOP - same state\n"); - return cnt; - } - - retval = rndis_ipa_setup_loopback( - rndis_ipa_ctx->loopback_enable, - rndis_ipa_ctx); - if (retval) - rndis_ipa_ctx->loopback_enable = old_state; - - return cnt; -} - static int rndis_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) { struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; @@ -2434,319 +2317,6 @@ static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, return simple_read_from_buffer(ubuf, count, ppos, atomic_str, nbytes); } -static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int nbytes; - int size = 0; - int ret; - loff_t pos; - u8 enable_str[sizeof(char)*3] = {0}; - bool *enable = file->private_data; - pos = *ppos; - nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); - ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); - if (ret < 0) { - RNDIS_IPA_ERROR("simple_read_from_buffer problem\n"); - return ret; - } - size += ret; - count -= nbytes; - *ppos = pos + size; - return size; -} - -static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long missing; - char input; - bool *enable = file->private_data; - if (count != sizeof(input) + 1) { - RNDIS_IPA_ERROR("wrong input length(%zd)\n", count); - return -EINVAL; - } - if (!buf) { - RNDIS_IPA_ERROR("Bad argument\n"); - return -EINVAL; - } - missing = copy_from_user(&input, buf, 1); - if (missing) - return -EFAULT; - RNDIS_IPA_DEBUG("input received %c\n", input); - *enable = input - '0'; - RNDIS_IPA_DEBUG("value was set to %d\n", *enable); - return count; -} - -/** - * Connects IPA->BAMDMA - * This shall simulate the path from IPA to USB - * Allowing the driver TX path - */ -static int rndis_ipa_loopback_pipe_create( - struct rndis_ipa_dev *rndis_ipa_ctx, - struct rndis_loopback_pipe *loopback_pipe) -{ - int retval; - - RNDIS_IPA_LOG_ENTRY(); - - /* SPS pipe has two side handshake - * This is the first handshake of IPA->BAMDMA, - * This is the IPA side - */ - loopback_pipe->ipa_connect_params.client = loopback_pipe->ipa_client; - loopback_pipe->ipa_connect_params.client_bam_hdl = - rndis_ipa_ctx->bam_dma_hdl; - loopback_pipe->ipa_connect_params.client_ep_idx = - loopback_pipe->peer_pipe_index; - loopback_pipe->ipa_connect_params.desc_fifo_sz = BAM_DMA_DESC_FIFO_SIZE; - loopback_pipe->ipa_connect_params.data_fifo_sz = BAM_DMA_DATA_FIFO_SIZE; - loopback_pipe->ipa_connect_params.notify = loopback_pipe->ipa_callback; - loopback_pipe->ipa_connect_params.priv = rndis_ipa_ctx; - loopback_pipe->ipa_connect_params.ipa_ep_cfg = - *(loopback_pipe->ipa_ep_cfg); - - /* loopback_pipe->ipa_sps_connect is out param */ - retval = ipa_connect(&loopback_pipe->ipa_connect_params, - &loopback_pipe->ipa_sps_connect, - &loopback_pipe->ipa_drv_ep_hdl); - if (retval) { - RNDIS_IPA_ERROR("ipa_connect() fail (%d)", retval); - return retval; - } - RNDIS_IPA_DEBUG("ipa_connect() succeeded, ipa_drv_ep_hdl=%d", - loopback_pipe->ipa_drv_ep_hdl); - - /* SPS pipe has two side handshake - * This is the second handshake of IPA->BAMDMA, - * This is the BAMDMA side - */ - loopback_pipe->dma_sps = sps_alloc_endpoint(); - if (!loopback_pipe->dma_sps) { - RNDIS_IPA_ERROR("sps_alloc_endpoint() failed "); - retval = -ENOMEM; - goto fail_sps_alloc; - } - - retval = sps_get_config(loopback_pipe->dma_sps, - &loopback_pipe->dma_connect); - if (retval) { - RNDIS_IPA_ERROR("sps_get_config() failed (%d)", retval); - goto fail_get_cfg; - } - - /* Start setting the non IPA ep for SPS driver*/ - loopback_pipe->dma_connect.mode = loopback_pipe->mode; - - /* SPS_MODE_DEST: DMA end point is the dest (consumer) IPA->DMA */ - if (loopback_pipe->mode == SPS_MODE_DEST) { - - loopback_pipe->dma_connect.source = - loopback_pipe->ipa_sps_connect.ipa_bam_hdl; - loopback_pipe->dma_connect.src_pipe_index = - loopback_pipe->ipa_sps_connect.ipa_ep_idx; - loopback_pipe->dma_connect.destination = - rndis_ipa_ctx->bam_dma_hdl; - loopback_pipe->dma_connect.dest_pipe_index = - loopback_pipe->peer_pipe_index; - - /* SPS_MODE_SRC: DMA end point is the source (producer) DMA->IPA */ - } else { - - loopback_pipe->dma_connect.source = - rndis_ipa_ctx->bam_dma_hdl; - loopback_pipe->dma_connect.src_pipe_index = - loopback_pipe->peer_pipe_index; - loopback_pipe->dma_connect.destination = - loopback_pipe->ipa_sps_connect.ipa_bam_hdl; - loopback_pipe->dma_connect.dest_pipe_index = - loopback_pipe->ipa_sps_connect.ipa_ep_idx; - - } - - loopback_pipe->dma_connect.desc = loopback_pipe->ipa_sps_connect.desc; - loopback_pipe->dma_connect.data = loopback_pipe->ipa_sps_connect.data; - loopback_pipe->dma_connect.event_thresh = 0x10; - /* BAM-to-BAM */ - loopback_pipe->dma_connect.options = SPS_O_AUTO_ENABLE; - - RNDIS_IPA_DEBUG("doing sps_connect() with - "); - RNDIS_IPA_DEBUG("src bam_hdl:0x%lx, src_pipe#:%d", - loopback_pipe->dma_connect.source, - loopback_pipe->dma_connect.src_pipe_index); - RNDIS_IPA_DEBUG("dst bam_hdl:0x%lx, dst_pipe#:%d", - loopback_pipe->dma_connect.destination, - loopback_pipe->dma_connect.dest_pipe_index); - - retval = sps_connect(loopback_pipe->dma_sps, - &loopback_pipe->dma_connect); - if (retval) { - RNDIS_IPA_ERROR("sps_connect() fail for BAMDMA side (%d)", - retval); - goto fail_sps_connect; - } - - RNDIS_IPA_LOG_EXIT(); - - return 0; - -fail_sps_connect: -fail_get_cfg: - sps_free_endpoint(loopback_pipe->dma_sps); -fail_sps_alloc: - ipa_disconnect(loopback_pipe->ipa_drv_ep_hdl); - return retval; -} - -static void rndis_ipa_destroy_loopback_pipe( - struct rndis_loopback_pipe *loopback_pipe) -{ - sps_disconnect(loopback_pipe->dma_sps); - sps_free_endpoint(loopback_pipe->dma_sps); -} - -/** - * rndis_ipa_create_loopback() - create a BAM-DMA loopback - * in order to replace the USB core - */ -static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) -{ - /* The BAM handle should be use as - * source/destination in the sps_connect() - */ - int retval; - - RNDIS_IPA_LOG_ENTRY(); - - - retval = sps_ctrl_bam_dma_clk(true); - if (retval) { - RNDIS_IPA_ERROR("fail on enabling BAM-DMA clocks"); - return -ENODEV; - } - - /* Get BAM handle instead of USB handle */ - rndis_ipa_ctx->bam_dma_hdl = sps_dma_get_bam_handle(); - if (!rndis_ipa_ctx->bam_dma_hdl) { - RNDIS_IPA_ERROR("sps_dma_get_bam_handle() failed"); - return -ENODEV; - } - RNDIS_IPA_DEBUG("sps_dma_get_bam_handle() succeeded (0x%x)", - rndis_ipa_ctx->bam_dma_hdl); - - /* IPA<-BAMDMA, NetDev Rx path (BAMDMA is the USB stub) */ - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_client = - IPA_CLIENT_USB_PROD; - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.peer_pipe_index = - FROM_USB_TO_IPA_BAMDMA; - /*DMA EP mode*/ - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.mode = SPS_MODE_SRC; - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_ep_cfg = - &usb_to_ipa_ep_cfg_deaggr_en; - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_callback = - rndis_ipa_packet_receive_notify; - RNDIS_IPA_DEBUG("setting up IPA<-BAMDAM pipe (RNDIS_IPA RX path)"); - retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, - &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); - if (retval) { - RNDIS_IPA_ERROR("fail to close IPA->BAMDAM pipe"); - goto fail_to_usb; - } - RNDIS_IPA_DEBUG("IPA->BAMDAM pipe successfully connected (TX path)"); - - /* IPA->BAMDMA, NetDev Tx path (BAMDMA is the USB stub)*/ - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_client = - IPA_CLIENT_USB_CONS; - /*DMA EP mode*/ - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.mode = SPS_MODE_DEST; - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_ep_cfg = &ipa_to_usb_ep_cfg; - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.peer_pipe_index = - FROM_IPA_TO_USB_BAMDMA; - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_callback = - rndis_ipa_tx_complete_notify; - RNDIS_IPA_DEBUG("setting up IPA->BAMDAM pipe (RNDIS_IPA TX path)"); - retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, - &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); - if (retval) { - RNDIS_IPA_ERROR("fail to close IPA<-BAMDAM pipe"); - goto fail_from_usb; - } - RNDIS_IPA_DEBUG("IPA<-BAMDAM pipe successfully connected(RX path)"); - - RNDIS_IPA_LOG_EXIT(); - - return 0; - -fail_from_usb: - rndis_ipa_destroy_loopback_pipe( - &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); -fail_to_usb: - - return retval; -} - -static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) -{ - rndis_ipa_destroy_loopback_pipe( - &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); - rndis_ipa_destroy_loopback_pipe( - &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); - sps_dma_free_bam_handle(rndis_ipa_ctx->bam_dma_hdl); - if (sps_ctrl_bam_dma_clk(false)) - RNDIS_IPA_ERROR("fail to disable BAM-DMA clocks"); -} - -/** - * rndis_ipa_setup_loopback() - create/destroy a loopback on IPA HW - * (as USB pipes loopback) and notify RNDIS_IPA netdev for pipe connected - * @enable: flag that determines if the loopback should be created or destroyed - * @rndis_ipa_ctx: driver main context - * - * This function is the main loopback logic. - * It shall create/destory the loopback by using BAM-DMA and notify - * the netdev accordingly. - */ -static int rndis_ipa_setup_loopback(bool enable, - struct rndis_ipa_dev *rndis_ipa_ctx) -{ - int retval; - - if (!enable) { - rndis_ipa_destroy_loopback(rndis_ipa_ctx); - RNDIS_IPA_DEBUG("loopback destroy done"); - retval = rndis_ipa_pipe_disconnect_notify(rndis_ipa_ctx); - if (retval) { - RNDIS_IPA_ERROR("connect notify fail"); - return -ENODEV; - } - return 0; - } - - RNDIS_IPA_DEBUG("creating loopback (instead of USB core)"); - retval = rndis_ipa_create_loopback(rndis_ipa_ctx); - RNDIS_IPA_DEBUG("creating loopback- %s", (retval ? "FAIL" : "OK")); - if (retval) { - RNDIS_IPA_ERROR("Fail to connect loopback"); - return -ENODEV; - } - retval = rndis_ipa_pipe_connect_notify( - rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_drv_ep_hdl, - rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_drv_ep_hdl, - BAM_DMA_DATA_FIFO_SIZE, - 15, - BAM_DMA_DATA_FIFO_SIZE - rndis_ipa_ctx->net->mtu, - rndis_ipa_ctx); - if (retval) { - RNDIS_IPA_ERROR("connect notify fail"); - return -ENODEV; - } - - return 0; - -} - static int rndis_ipa_init_module(void) { pr_info("RNDIS_IPA module is loaded."); From 8e821953c0dd7f5e0c49ed0978ae818562abb927 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 25 Sep 2015 16:30:08 +0100 Subject: [PATCH 033/210] KEYS: Fix race between key destruction and finding a keyring by name (cherry picked from commit 94c4554ba07adbdde396748ee7ae01e86cf2d8d7) There appears to be a race between: (1) key_gc_unused_keys() which frees key->security and then calls keyring_destroy() to unlink the name from the name list (2) find_keyring_by_name() which calls key_permission(), thus accessing key->security, on a key before checking to see whether the key usage is 0 (ie. the key is dead and might be cleaned up). Fix this by calling ->destroy() before cleaning up the core key data - including key->security. Reported-by: Petr Matousek Signed-off-by: David Howells Bug: 31253168 Git-repo: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git Git-commit : 94c4554ba07adbdde396748ee7ae01e86cf2d8d7 Signed-off-by: Srinivasa Rao Kuppala Change-Id: I2bb1e7b7240dc81a172483ce35f569d357579b96 --- security/keys/gc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/keys/gc.c b/security/keys/gc.c index 797818695c87..483ebdf9c383 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -187,6 +187,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kdebug("- %u", key->serial); key_check(key); + /* Throw away the key data */ + if (key->type->destroy) + key->type->destroy(key); + security_key_free(key); /* deal with the user's key tracking and quota */ @@ -201,10 +205,6 @@ static noinline void key_gc_unused_keys(struct list_head *keys) if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) atomic_dec(&key->user->nikeys); - /* now throw away the key memory */ - if (key->type->destroy) - key->type->destroy(key); - key_user_put(key->user); kfree(key->description); From 34f08de5610fb2567b238f92247fb319dec6359c Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 15 Oct 2015 17:21:37 +0100 Subject: [PATCH 034/210] UPSTREAM: KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring (cherry picked from commit f05819df10d7b09f6d1eb6f8534a8f68e5a4fe61) The following sequence of commands: i=`keyctl add user a a @s` keyctl request2 keyring foo bar @t keyctl unlink $i @s tries to invoke an upcall to instantiate a keyring if one doesn't already exist by that name within the user's keyring set. However, if the upcall fails, the code sets keyring->type_data.reject_error to -ENOKEY or some other error code. When the key is garbage collected, the key destroy function is called unconditionally and keyring_destroy() uses list_empty() on keyring->type_data.link - which is in a union with reject_error. Subsequently, the kernel tries to unlink the keyring from the keyring names list - which oopses like this: BUG: unable to handle kernel paging request at 00000000ffffff8a IP: [] keyring_destroy+0x3d/0x88 ... Workqueue: events key_garbage_collector ... RIP: 0010:[] keyring_destroy+0x3d/0x88 RSP: 0018:ffff88003e2f3d30 EFLAGS: 00010203 RAX: 00000000ffffff82 RBX: ffff88003bf1a900 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 000000003bfc6901 RDI: ffffffff81a73a40 RBP: ffff88003e2f3d38 R08: 0000000000000152 R09: 0000000000000000 R10: ffff88003e2f3c18 R11: 000000000000865b R12: ffff88003bf1a900 R13: 0000000000000000 R14: ffff88003bf1a908 R15: ffff88003e2f4000 ... CR2: 00000000ffffff8a CR3: 000000003e3ec000 CR4: 00000000000006f0 ... Call Trace: [] key_gc_unused_keys.constprop.1+0x5d/0x10f [] key_garbage_collector+0x1fa/0x351 [] process_one_work+0x28e/0x547 [] worker_thread+0x26e/0x361 [] ? rescuer_thread+0x2a8/0x2a8 [] kthread+0xf3/0xfb [] ? kthread_create_on_node+0x1c2/0x1c2 [] ret_from_fork+0x3f/0x70 [] ? kthread_create_on_node+0x1c2/0x1c2 Note the value in RAX. This is a 32-bit representation of -ENOKEY. The solution is to only call ->destroy() if the key was successfully instantiated. Reported-by: Dmitry Vyukov Signed-off-by: David Howells Tested-by: Dmitry Vyukov Change-Id: I29a78e84be219d2f760ef845c7d8481ef4d5517a Bug: 31253168 Git-repo: https://android.googlesource.com/kernel/common.git Git-commit: cb51f03e75ce5c3348c7c11b4f66e0101d4b555a Signed-off-by: Ravi Kumar Siddojigari --- security/keys/gc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/security/keys/gc.c b/security/keys/gc.c index 483ebdf9c383..de34c290bd6f 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -187,8 +187,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kdebug("- %u", key->serial); key_check(key); - /* Throw away the key data */ - if (key->type->destroy) + /* Throw away the key data if the key is instantiated */ + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && + !test_bit(KEY_FLAG_NEGATIVE, &key->flags) && + key->type->destroy) key->type->destroy(key); security_key_free(key); From 3aec17530eae09fda19c0be57244b71f00d06052 Mon Sep 17 00:00:00 2001 From: Andrey Markovytch Date: Mon, 26 Dec 2016 08:58:18 +0200 Subject: [PATCH 035/210] ice: fix security issue with validating error in pointer get_ice_device_from_storage_type can return error pointer which is not NULL in case of error, this was not checked, changes fixes this. Change-Id: I7dd8a068454a7bd250189ff9467c685af449f81b Signed-off-by: Andrey Markovytch --- drivers/crypto/msm/ice.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index 6063a5551d26..7255973d493d 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -1645,6 +1645,9 @@ int qcom_ice_setup_ice_hw(const char *storage_type, int enable) struct ice_device *ice_dev = NULL; ice_dev = get_ice_device_from_storage_type(storage_type); + if (ice_dev == ERR_PTR(-EPROBE_DEFER)) + return -EPROBE_DEFER; + if (!ice_dev) return ret; From 002a8109ebc6fc28cebacb01c8727f0874d838e5 Mon Sep 17 00:00:00 2001 From: EunTaik Lee Date: Wed, 24 Feb 2016 04:38:06 +0000 Subject: [PATCH 036/210] staging/android/ion : fix a race condition in the ion driver There is a use-after-free problem in the ion driver. This is caused by a race condition in the ion_ioctl() function. A handle has ref count of 1 and two tasks on different cpus calls ION_IOC_FREE simultaneously. cpu 0 cpu 1 ------------------------------------------------------- ion_handle_get_by_id() (ref == 2) ion_handle_get_by_id() (ref == 3) ion_free() (ref == 2) ion_handle_put() (ref == 1) ion_free() (ref == 0 so ion_handle_destroy() is called and the handle is freed.) ion_handle_put() is called and it decreases the slub's next free pointer The problem is detected as an unaligned access in the spin lock functions since it uses load exclusive instruction. In some cases it corrupts the slub's free pointer which causes a mis-aligned access to the next free pointer.(kmalloc returns a pointer like ffffc0745b4580aa). And it causes lots of other hard-to-debug problems. This symptom is caused since the first member in the ion_handle structure is the reference count and the ion driver decrements the reference after it has been freed. To fix this problem client->lock mutex is extended to protect all the codes that uses the handle. Change-Id: Ia1a36ad6336305fe8383863cfab066a56525fd9f Signed-off-by: Eun Taik Lee Reviewed-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman Git-commit: 9590232bb4f4cc824f3425a6e1349afbe6d6d2b7 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [shashim@codeaurora.org: Resolved minor merge conflicts] Signed-off-by: Shiraz Hashim --- drivers/staging/android/ion/ion.c | 55 +++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 13 deletions(-) mode change 100644 => 100755 drivers/staging/android/ion/ion.c diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c old mode 100644 new mode 100755 index bf93c7770a58..b2c2444d2745 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -402,13 +402,22 @@ static void ion_handle_get(struct ion_handle *handle) kref_get(&handle->ref); } +static int ion_handle_put_nolock(struct ion_handle *handle) +{ + int ret; + + ret = kref_put(&handle->ref, ion_handle_destroy); + + return ret; +} + int ion_handle_put(struct ion_handle *handle) { struct ion_client *client = handle->client; int ret; mutex_lock(&client->lock); - ret = kref_put(&handle->ref, ion_handle_destroy); + ret = ion_handle_put_nolock(handle); mutex_unlock(&client->lock); return ret; @@ -432,18 +441,28 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, return ERR_PTR(-EINVAL); } +static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id) +{ + struct ion_handle *handle; + + handle = idr_find(&client->idr, id); + if (handle) + ion_handle_get(handle); + + return handle ? handle : ERR_PTR(-EINVAL); +} + struct ion_handle *ion_handle_get_by_id(struct ion_client *client, int id) { struct ion_handle *handle; mutex_lock(&client->lock); - handle = idr_find(&client->idr, id); - if (handle) - ion_handle_get(handle); + handle = ion_handle_get_by_id_nolock(client, id); mutex_unlock(&client->lock); - return handle ? handle : ERR_PTR(-EINVAL); + return handle; } static bool ion_handle_validate(struct ion_client *client, @@ -592,21 +611,27 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } EXPORT_SYMBOL(ion_alloc); -void ion_free(struct ion_client *client, struct ion_handle *handle) +static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) { bool valid_handle; BUG_ON(client != handle->client); - mutex_lock(&client->lock); valid_handle = ion_handle_validate(client, handle); if (!valid_handle) { WARN(1, "%s: invalid handle passed to free.\n", __func__); - mutex_unlock(&client->lock); return; } + ion_handle_put_nolock(handle); +} + +void ion_free(struct ion_client *client, struct ion_handle *handle) +{ + BUG_ON(client != handle->client); + + mutex_lock(&client->lock); + ion_free_nolock(client, handle); mutex_unlock(&client->lock); - ion_handle_put(handle); } EXPORT_SYMBOL(ion_free); @@ -1476,11 +1501,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_handle *handle; - handle = ion_handle_get_by_id(client, data.handle.handle); - if (IS_ERR(handle)) + mutex_lock(&client->lock); + handle = ion_handle_get_by_id_nolock(client, data.handle.handle); + if (IS_ERR(handle)) { + mutex_unlock(&client->lock); return PTR_ERR(handle); - ion_free(client, handle); - ion_handle_put(handle); + } + ion_free_nolock(client, handle); + ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); break; } case ION_IOC_SHARE: From 9cafbf71dc6be22ee85a7095965da3e1b9f1d125 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Wed, 21 Dec 2016 16:30:45 +0530 Subject: [PATCH 037/210] msm: kgsl: Do VBIF reset before GPU power collapse For A510 GPU reset VBIF core before it power collapse to avoid popping bogus FIFO entries. CRs-Fixed: 1063523 Change-Id: Ie7aa76714bbca7d25e482db9a74b1d5cf37f66b6 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno_a5xx.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 50e44ad32ebf..fe27e94bef93 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -469,12 +469,10 @@ static void a5xx_regulator_disable(struct adreno_device *adreno_dev) unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; - if (adreno_is_a510(adreno_dev)) - return; - /* If feature is not supported or not enabled */ - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) { + if (!adreno_is_a510(adreno_dev) && + (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || + !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag))) { /* Set the default register values; set SW_COLLAPSE to 1 */ kgsl_regwrite(device, A5XX_GPMU_SP_POWER_CNTL, 0x778001); /* @@ -508,7 +506,7 @@ static void a5xx_regulator_disable(struct adreno_device *adreno_dev) KGSL_PWR_WARN(device, "GMEM is forced on\n"); } - if (adreno_is_a530(adreno_dev)) { + if (adreno_is_a530(adreno_dev) || adreno_is_a510(adreno_dev)) { /* Reset VBIF before PC to avoid popping bogus FIFO entries */ kgsl_regwrite(device, A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000); From e4ae29c119e75a85ce626a69d21ab1cabe444fef Mon Sep 17 00:00:00 2001 From: Kumar Behera Date: Fri, 9 Dec 2016 09:55:00 -0800 Subject: [PATCH 038/210] msm: cpp: Fix for integer overflow in cpp Due to integer overflow ,the bound check in config frame function may pass and this may allow user to access invalid buffer. This fix takes care of proper bound and don't allow integer overflow. CRs-Fxied: 1097709 Change-Id: I504ad591633afaba82268b5ee27a321691d75c80 Signed-off-by: Kumar Behera --- drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 921ed4a40b81..63751c45d204 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -2163,7 +2163,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info; int32_t in_fd; int32_t num_output_bufs = 1; - int32_t stripe_base = 0; + uint32_t stripe_base = 0; uint32_t stripe_size; uint8_t tnr_enabled; enum msm_camera_buf_mngr_buf_type buf_type = @@ -2190,6 +2190,13 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, return -EINVAL; } + if (stripe_base == UINT_MAX || new_frame->num_strips > + (UINT_MAX - 1 - stripe_base) / stripe_size) { + pr_err("Invalid frame message,num_strips %d is large\n", + new_frame->num_strips); + return -EINVAL; + } + if ((stripe_base + new_frame->num_strips * stripe_size + 1) != new_frame->msg_len) { pr_err("Invalid frame message,len=%d,expected=%d\n", From 3f4acb2e8d896640baf42cc9025356126f67b293 Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Mon, 21 Nov 2016 16:03:58 +0530 Subject: [PATCH 039/210] genirq: fix race condition in irq_affinity_notify While irq_affinity_notify notifies each of the registered notifiers, clients already register can call irq_release_affinity_notifier just before it's notify call getting called. If this happens, irq_release_affinity_notifier can remove the notifier function from the list and still irq_affinity_notify tries to call it's notifier. Add notify_lock in irq descriptor and use this mutex to protect the irq_release_affinity_notifier and irq_affinity_notify. Change-Id: I30f44421a20e7642485d9c4efbc476e147855b1b Signed-off-by: Srinivas Rao L --- include/linux/irqdesc.h | 1 + kernel/irq/irqdesc.c | 1 + kernel/irq/manage.c | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index db3509ea165b..f439e4f285ab 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -63,6 +63,7 @@ struct irq_desc { const struct cpumask *affinity_hint; struct list_head affinity_notify; struct work_struct affinity_work; + struct mutex notify_lock; #ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_var_t pending_mask; #endif diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 844dfebf9f3d..2a9d8c17ce66 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -153,6 +153,7 @@ static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) raw_spin_lock_init(&desc->lock); lockdep_set_class(&desc->lock, &irq_desc_lock_class); + mutex_init(&desc->notify_lock); desc_set_defaults(irq, desc, node, owner); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e1ad0d0441d0..071e6cfb57cd 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -234,6 +234,7 @@ void irq_affinity_notify(struct work_struct *work) cpumask_copy(cpumask, desc->irq_data.affinity); raw_spin_unlock_irqrestore(&desc->lock, flags); + mutex_lock(&desc->notify_lock); list_for_each_entry(notify, &desc->affinity_notify, list) { /** * Check and get the kref only if the kref has not been @@ -246,6 +247,7 @@ void irq_affinity_notify(struct work_struct *work) notify->notify(notify, cpumask); kref_put(¬ify->kref, notify->release); } + mutex_unlock(&desc->notify_lock); free_cpumask_var(cpumask); } @@ -279,9 +281,11 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) notify->irq = irq; kref_init(¬ify->kref); INIT_LIST_HEAD(¬ify->list); + mutex_lock(&desc->notify_lock); raw_spin_lock_irqsave(&desc->lock, flags); list_add(¬ify->list, &desc->affinity_notify); raw_spin_unlock_irqrestore(&desc->lock, flags); + mutex_unlock(&desc->notify_lock); return 0; } @@ -300,10 +304,12 @@ int irq_release_affinity_notifier(struct irq_affinity_notify *notify) return -EINVAL; desc = irq_to_desc(notify->irq); + mutex_lock(&desc->notify_lock); raw_spin_lock_irqsave(&desc->lock, flags); list_del(¬ify->list); raw_spin_unlock_irqrestore(&desc->lock, flags); kref_put(¬ify->kref, notify->release); + mutex_unlock(&desc->notify_lock); return 0; } From 48571266d16f6675af5a3dfe8341b9ce19d50b18 Mon Sep 17 00:00:00 2001 From: Sachin Bhayare Date: Fri, 18 Nov 2016 12:10:26 +0530 Subject: [PATCH 040/210] msm: mdss: Fix potential deferencing of null pointer While servicing display post processing ioctl for calib data the driver checks if the calibration addr is valid. During this check it deferences the base address for all pipes without checking if the pipe pointer is NULL. This fix adds this check. CRs-Fixed: 1082568 Change-Id: Id8164e3e9a6e5178d14dfce60eccbdb3f7a1b253 Signed-off-by: Naseer Ahmed Signed-off-by: Sachin Bhayare --- drivers/video/msm/mdss/mdss_mdp_pp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c index f632c8a027d8..2330bcd1c280 100644 --- a/drivers/video/msm/mdss/mdss_mdp_pp.c +++ b/drivers/video/msm/mdss/mdss_mdp_pp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 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 @@ -5916,9 +5916,6 @@ static int is_valid_calib_addr(void *addr, u32 operation) int ret = 0; char __iomem *ptr = addr; char __iomem *mixer_base = mdss_res->mixer_intf->base; - char __iomem *rgb_base = mdss_res->rgb_pipes->base; - char __iomem *dma_base = mdss_res->dma_pipes->base; - char __iomem *vig_base = mdss_res->vig_pipes->base; char __iomem *ctl_base = mdss_res->ctl_off->base; char __iomem *dspp_base = mdss_res->mixer_intf->dspp_base; @@ -5950,17 +5947,20 @@ static int is_valid_calib_addr(void *addr, u32 operation) if (ret) goto valid_addr; } - if (ptr >= vig_base) { + if (mdss_res->vig_pipes && + ptr >= mdss_res->vig_pipes->base) { ret = is_valid_calib_vig_addr(ptr); if (ret) goto valid_addr; } - if (ptr >= rgb_base) { + if (mdss_res->rgb_pipes && + ptr >= mdss_res->rgb_pipes->base) { ret = is_valid_calib_rgb_addr(ptr); if (ret) goto valid_addr; } - if (ptr >= dma_base) { + if (mdss_res->dma_pipes && + ptr >= mdss_res->dma_pipes->base) { ret = is_valid_calib_dma_addr(ptr); if (ret) goto valid_addr; From d12d85b91e68ec0e329eb3b9697aa8d45ee0b114 Mon Sep 17 00:00:00 2001 From: Banajit Goswami Date: Thu, 3 Nov 2016 19:18:07 -0700 Subject: [PATCH 041/210] ASoC: msm: q6dspv2: use correct variable type to store ION buff size The size of the physical memory allocated for ION buffers are of type size_t. Change updates the type of variables sent to ION drivers to size_t to avoid any mismatch. Change-Id: I3d33ed922b979652c64027e6f1c6f0a8ed4850a3 Signed-off-by: Banajit Goswami --- sound/soc/msm/qdsp6v2/q6asm.c | 10 ++++++---- sound/soc/msm/qdsp6v2/q6voice.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 98899244b5fe..d6e34c04c382 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -2791,7 +2791,8 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, int dir) { struct audio_buffer *buf_circ; - int bytes_to_alloc, rc, len; + int bytes_to_alloc, rc; + size_t len; buf_circ = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL); @@ -2810,7 +2811,7 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, rc = msm_audio_ion_alloc("audio_client", &buf_circ->client, &buf_circ->handle, bytes_to_alloc, (ion_phys_addr_t *)&buf_circ->phys, - (size_t *)&len, &buf_circ->data); + &len, &buf_circ->data); if (rc) { pr_err("%s: Audio ION alloc is failed, rc = %d\n", __func__, @@ -2852,7 +2853,8 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, int dir) { struct audio_buffer *buf_pos = &ac->shared_pos_buf; - int len, rc; + int rc; + size_t len; int bytes_to_alloc = sizeof(struct asm_shared_position_buffer); mutex_lock(&ac->cmd_lock); @@ -2861,7 +2863,7 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, rc = msm_audio_ion_alloc("audio_client", &buf_pos->client, &buf_pos->handle, bytes_to_alloc, - (ion_phys_addr_t *)&buf_pos->phys, (size_t *)&len, + (ion_phys_addr_t *)&buf_pos->phys, &len, &buf_pos->data); if (rc) { diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index 430c0e0d08e8..70acca34213f 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -126,7 +126,7 @@ struct share_mem_buf { struct mem_map_table { dma_addr_t phys; void *data; - uint32_t size; /* size of buffer */ + size_t size; /* size of buffer */ struct ion_handle *handle; struct ion_client *client; }; From 7191fa54dd8b4261ed3c30e84a5760153627d58d Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Mon, 24 Oct 2016 10:06:45 -0700 Subject: [PATCH 042/210] qseecom: improve error checks in qseecom_probe() Make change in qseecom_probe() to improve the error return value checks on some subfunctions, and free memory allocated within qseecom_retrieve_ce_data. CRs-fixed: 1075082 Change-Id: I971e555ec8d02ccf4382e83132a696b065a8ff12 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 64b496639a23..993d853d36d2 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -7238,7 +7238,6 @@ static int qseecom_check_whitelist_feature(void) static int qseecom_probe(struct platform_device *pdev) { int rc; - int ret = 0; uint32_t feature = 10; struct device *class_dev; struct msm_bus_scale_pdata *qseecom_platform_support = NULL; @@ -7283,7 +7282,7 @@ static int qseecom_probe(struct platform_device *pdev) class_dev = device_create(driver_class, NULL, qseecom_device_no, NULL, QSEECOM_DEV); - if (!class_dev) { + if (IS_ERR(class_dev)) { pr_err("class_device_create failed %d\n", rc); rc = -ENOMEM; goto exit_destroy_class; @@ -7322,7 +7321,7 @@ static int qseecom_probe(struct platform_device *pdev) qseecom.pdev = class_dev; /* Create ION msm client */ qseecom.ion_clnt = msm_ion_client_create("qseecom-kernel"); - if (qseecom.ion_clnt == NULL) { + if (IS_ERR_OR_NULL(qseecom.ion_clnt)) { pr_err("Ion client cannot be created\n"); rc = -ENOMEM; goto exit_del_cdev; @@ -7467,14 +7466,14 @@ static int qseecom_probe(struct platform_device *pdev) pr_info("CE operating frequency is not defined, setting to default 100MHZ\n"); qseecom.ce_opp_freq_hz = QSEE_CE_CLK_100MHZ; } - ret = __qseecom_init_clk(CLK_QSEE); - if (ret) + rc = __qseecom_init_clk(CLK_QSEE); + if (rc) goto exit_destroy_hw_instance_list; if ((qseecom.qsee.instance != qseecom.ce_drv.instance) && (qseecom.support_pfe || qseecom.support_fde)) { - ret = __qseecom_init_clk(CLK_CE_DRV); - if (ret) { + rc = __qseecom_init_clk(CLK_CE_DRV); + if (rc) { __qseecom_deinit_clk(CLK_QSEE); goto exit_destroy_hw_instance_list; } @@ -7526,7 +7525,7 @@ static int qseecom_probe(struct platform_device *pdev) } else { pr_err("Fail to get secure app region info\n"); rc = -EINVAL; - goto exit_destroy_hw_instance_list; + goto exit_deinit_clock; } rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, @@ -7535,7 +7534,7 @@ static int qseecom_probe(struct platform_device *pdev) pr_err("send secapp reg fail %d resp.res %d\n", rc, resp.result); rc = -EINVAL; - goto exit_destroy_hw_instance_list; + goto exit_deinit_clock; } } /* @@ -7569,6 +7568,11 @@ static int qseecom_probe(struct platform_device *pdev) pr_err("Unable to register bus client\n"); return 0; +exit_deinit_clock: + __qseecom_deinit_clk(CLK_QSEE); + if ((qseecom.qsee.instance != qseecom.ce_drv.instance) && + (qseecom.support_pfe || qseecom.support_fde)) + __qseecom_deinit_clk(CLK_CE_DRV); exit_destroy_hw_instance_list: kzfree(qseecom.ce_info.hlos_ce_hw_instance); exit_destroy_ion_client: From e879fc7eca7e3ba0ab9dcf24d2f717e49718a01e Mon Sep 17 00:00:00 2001 From: kunleiz Date: Tue, 27 Dec 2016 16:15:51 +0800 Subject: [PATCH 043/210] ASoC: msm: qdsp6v2: DAP: Add check to validate param length Return an error code to ensure valid length value is valid. CRs-fixed: 1102987 Change-Id: I6a679d08342d1da58c20b5c3d4e436dd335764ae Signed-off-by: kunleiz --- sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c index 59835e682408..d654b301ce2e 100644 --- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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. @@ -1656,6 +1656,7 @@ static int msm_ds2_dap_param_visualizer_control_get(u32 cmd, void *arg) ret = 0; dolby_data->length = 0; pr_err("%s Incorrect VCNB length", __func__); + return -EINVAL; } params_length = (2*length + DOLBY_VIS_PARAM_HEADER_SIZE) * From 25ab82f5d7d8d8d3b4c8eaaa02944dd5a81be7c3 Mon Sep 17 00:00:00 2001 From: Karthik Reddy Katta Date: Wed, 28 Dec 2016 11:24:33 +0530 Subject: [PATCH 044/210] drivers: soc: qcom: Add overflow check for sound model size Overflow check is added for sound model size to prevent heap overflow while allocating memory for sound model data. CRs-Fixed: 1100682 Change-Id: Id38523a5e79028c692670e84d5fe924a855a5a10 Signed-off-by: Karthik Reddy Katta --- sound/soc/msm/msm-cpe-lsm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c index d5b675f1e0b4..a4daf91d1e2f 100644 --- a/sound/soc/msm/msm-cpe-lsm.c +++ b/sound/soc/msm/msm-cpe-lsm.c @@ -1913,6 +1913,13 @@ static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream, lsm_ops->lsm_get_snd_model_offset(cpe->core_handle, session, &offset); + /* Check if 'p_info->param_size + offset' crosses U32_MAX. */ + if (p_info->param_size > U32_MAX - offset) { + dev_err(rtd->dev, + "%s: Invalid param_size %d\n", + __func__, p_info->param_size); + return -EINVAL; + } session->snd_model_size = p_info->param_size + offset; session->snd_model_data = vzalloc(session->snd_model_size); From e0245d5450da9a2bc5d675aaa9087e63a2a04d91 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Wed, 9 Nov 2016 11:00:56 +0800 Subject: [PATCH 045/210] ASoC: msm: q6dspv2: fix potentional information leak The heap buffer pointed to out_buffer and in_buffer are allocated but uninitlalized. It may cause information leak. Change to kzalloc instead of kmalloc when allocating kernel buffers to avoid information leak. CRs-Fixed: 1087020 Change-Id: I6f9b7a630158355a7f920dcf9cfffe537b1c6a85 Signed-off-by: Meng Wang --- sound/soc/msm/qdsp6v2/q6asm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 98899244b5fe..7351ec326c4a 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -313,12 +313,12 @@ static void config_debug_fs_write(struct audio_buffer *ab) } static void config_debug_fs_init(void) { - out_buffer = kmalloc(OUT_BUFFER_SIZE, GFP_KERNEL); + out_buffer = kzalloc(OUT_BUFFER_SIZE, GFP_KERNEL); if (out_buffer == NULL) { pr_err("%s: kmalloc() for out_buffer failed\n", __func__); goto outbuf_fail; } - in_buffer = kmalloc(IN_BUFFER_SIZE, GFP_KERNEL); + in_buffer = kzalloc(IN_BUFFER_SIZE, GFP_KERNEL); if (in_buffer == NULL) { pr_err("%s: kmalloc() for in_buffer failed\n", __func__); goto inbuf_fail; From 6cc8af9093b1f35c25335bf98810766acf90b54f Mon Sep 17 00:00:00 2001 From: Sanjay Singh Date: Mon, 28 Nov 2016 16:57:13 +0530 Subject: [PATCH 046/210] msm: vidc: WARN_ON() reveals fuction addresses There is a security vulnerability where function addresses are printed in kernel message if WARN_ON() is invoked implicitly. WARN_ON() call is made explicit to avoid this issue. Change-Id: If75581803adf62cb9bda3784ad1d4f4088e0d797 Signed-off-by: Sanjay Singh --- drivers/media/platform/msm/vidc/msm_vidc.c | 3 ++- drivers/media/platform/msm/vidc/venus_hfi.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 59a52063095c..a7d20bb8b422 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -1436,7 +1436,8 @@ static void cleanup_instance(struct msm_vidc_inst *inst) debugfs_remove_recursive(inst->debugfs_root); mutex_lock(&inst->pending_getpropq.lock); - WARN_ON(!list_empty(&inst->pending_getpropq.list)); + WARN_ON(!list_empty(&inst->pending_getpropq.list) + && (msm_vidc_debug & VIDC_INFO)); mutex_unlock(&inst->pending_getpropq.lock); } } diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 0015c84cf85b..7b6dc0974f26 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -266,7 +266,7 @@ static int venus_hfi_acquire_regulator(struct regulator_info *rinfo) rinfo->name); } } - WARN_ON(!regulator_is_enabled(rinfo->regulator)); + WARN_ON(!regulator_is_enabled(rinfo->regulator) && (msm_vidc_debug & VIDC_INFO)); return rc; } @@ -4357,7 +4357,7 @@ static int venus_hfi_disable_regulator(struct regulator_info *rinfo) disable_regulator_failed: /* Bring attention to this issue */ - WARN_ON(1); + WARN_ON(msm_vidc_debug & VIDC_INFO); return rc; } From 665f34ccf66a08e81aa16e95e6e886ad870d547e Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Mon, 21 Nov 2016 16:03:58 +0530 Subject: [PATCH 047/210] genirq: fix race condition in irq_affinity_notify While irq_affinity_notify notifies each of the registered notifiers, clients already register can call irq_release_affinity_notifier just before it's notify call getting called. If this happens, irq_release_affinity_notifier can remove the notifier function from the list and still irq_affinity_notify tries to call it's notifier. Add notify_lock in irq descriptor and use this mutex to protect the irq_release_affinity_notifier and irq_affinity_notify. Change-Id: I30f44421a20e7642485d9c4efbc476e147855b1b Signed-off-by: Srinivas Rao L --- include/linux/irqdesc.h | 1 + kernel/irq/irqdesc.c | 1 + kernel/irq/manage.c | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index db3509ea165b..f439e4f285ab 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -63,6 +63,7 @@ struct irq_desc { const struct cpumask *affinity_hint; struct list_head affinity_notify; struct work_struct affinity_work; + struct mutex notify_lock; #ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_var_t pending_mask; #endif diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 844dfebf9f3d..2a9d8c17ce66 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -153,6 +153,7 @@ static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) raw_spin_lock_init(&desc->lock); lockdep_set_class(&desc->lock, &irq_desc_lock_class); + mutex_init(&desc->notify_lock); desc_set_defaults(irq, desc, node, owner); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e1ad0d0441d0..071e6cfb57cd 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -234,6 +234,7 @@ void irq_affinity_notify(struct work_struct *work) cpumask_copy(cpumask, desc->irq_data.affinity); raw_spin_unlock_irqrestore(&desc->lock, flags); + mutex_lock(&desc->notify_lock); list_for_each_entry(notify, &desc->affinity_notify, list) { /** * Check and get the kref only if the kref has not been @@ -246,6 +247,7 @@ void irq_affinity_notify(struct work_struct *work) notify->notify(notify, cpumask); kref_put(¬ify->kref, notify->release); } + mutex_unlock(&desc->notify_lock); free_cpumask_var(cpumask); } @@ -279,9 +281,11 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) notify->irq = irq; kref_init(¬ify->kref); INIT_LIST_HEAD(¬ify->list); + mutex_lock(&desc->notify_lock); raw_spin_lock_irqsave(&desc->lock, flags); list_add(¬ify->list, &desc->affinity_notify); raw_spin_unlock_irqrestore(&desc->lock, flags); + mutex_unlock(&desc->notify_lock); return 0; } @@ -300,10 +304,12 @@ int irq_release_affinity_notifier(struct irq_affinity_notify *notify) return -EINVAL; desc = irq_to_desc(notify->irq); + mutex_lock(&desc->notify_lock); raw_spin_lock_irqsave(&desc->lock, flags); list_del(¬ify->list); raw_spin_unlock_irqrestore(&desc->lock, flags); kref_put(¬ify->kref, notify->release); + mutex_unlock(&desc->notify_lock); return 0; } From cc1d288e66a43f0c883f5a856a7dd7e0781c2835 Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 048/210] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; From f14fa330b7524f242d91816ff39621dd7f78d760 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Mon, 6 Jul 2015 23:18:37 +0300 Subject: [PATCH 049/210] mm: avoid setting up anonymous pages into file mapping commit 6b7339f4c31ad69c8e9c0b2859276e22cf72176d upstream. Reading page fault handler code I've noticed that under right circumstances kernel would map anonymous pages into file mappings: if the VMA doesn't have vm_ops->fault() and the VMA wasn't fully populated on ->mmap(), kernel would handle page fault to not populated pte with do_anonymous_page(). Let's change page fault handler to use do_anonymous_page() only on anonymous VMA (->vm_ops == NULL) and make sure that the VMA is not shared. For file mappings without vm_ops->fault() or shred VMA without vm_ops, page fault on pte_none() entry would lead to SIGBUS. Signed-off-by: Kirill A. Shutemov Acked-by: Oleg Nesterov Cc: Andrew Morton Cc: Willy Tarreau Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Git-repo: https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable Git-commit: efcbc94afe6dd0f8a4b112a0f3385cdc89ea58ba Change-Id: Ifab61dd2e0f503811ff428ab6b1d8ba62436e920 Signed-off-by: Srinivasa Rao Kuppala --- mm/memory.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index b847e769ccbb..55510ddb2f2d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3269,6 +3269,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, pte_unmap(page_table); + /* File mapping without ->vm_ops ? */ + if (vma->vm_flags & VM_SHARED) + return VM_FAULT_SIGBUS; + /* Check if we need to add a guard page to the stack */ if (check_stack_guard_page(vma, address) < 0) return VM_FAULT_SIGSEGV; @@ -3534,6 +3538,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; pte_unmap(page_table); + /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ + if (!vma->vm_ops->fault) + return VM_FAULT_SIGBUS; return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); } @@ -3745,11 +3752,9 @@ int handle_pte_fault(struct mm_struct *mm, entry = *pte; if (!pte_present(entry)) { if (pte_none(entry)) { - if (vma->vm_ops) { - if (likely(vma->vm_ops->fault)) - return do_linear_fault(mm, vma, address, + if (vma->vm_ops) + return do_linear_fault(mm, vma, address, pte, pmd, flags, entry); - } return do_anonymous_page(mm, vma, address, pte, pmd, flags); } From 9ce878cc849f38b5ea8bd2c1dc178f99c570c7f0 Mon Sep 17 00:00:00 2001 From: Siqi Lin Date: Wed, 2 Nov 2016 16:51:08 -0700 Subject: [PATCH 050/210] ALSA: info: Check for integer overflow in snd_info_entry_write() snd_info_entry_write() resizes the buffer with an unsigned long size argument that gets truncated because resize_info_buffer() takes the size parameter as an unsigned int. On 64-bit kernels, this causes the following copy_to_user() to write out-of-bounds if (pos + count) can't be represented by an unsigned int. Bug: 32510733 Change-Id: I9e8b55f93f2bd606b4a73b5a4525b71ee88c7c23 Signed-off-by: Siqi Lin Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 600c59f1f58bf30716d4a072add85f8da77c145c Signed-off-by: Dennis Cagle --- sound/core/info.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/core/info.c b/sound/core/info.c index 7e13a3b3aacf..88d0981edd0f 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -253,6 +253,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer struct snd_info_buffer *buf; ssize_t size = 0; loff_t pos; + unsigned long realloc_size; data = file->private_data; if (snd_BUG_ON(!data)) @@ -261,7 +262,8 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer pos = *offset; if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) return -EIO; - if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) + realloc_size = (unsigned long) pos + (unsigned long) count; + if (realloc_size < (unsigned long) pos || realloc_size > UINT_MAX) return -EIO; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: From aaa7ee0c1ae6d81465cd956dfa8afe2a574541cc Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 13 May 2016 09:34:12 -0400 Subject: [PATCH 051/210] ring-buffer: Prevent overflow of size in ring_buffer_resize() If the size passed to ring_buffer_resize() is greater than MAX_LONG - BUF_PAGE_SIZE then the DIV_ROUND_UP() will return zero. Here's the details: # echo 18014398509481980 > /sys/kernel/debug/tracing/buffer_size_kb tracing_entries_write() processes this and converts kb to bytes. 18014398509481980 << 10 = 18446744073709547520 and this is passed to ring_buffer_resize() as unsigned long size. size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); Where DIV_ROUND_UP(a, b) is (a + b - 1)/b BUF_PAGE_SIZE is 4080 and here 18446744073709547520 + 4080 - 1 = 18446744073709551599 where 18446744073709551599 is still smaller than 2^64 2^64 - 18446744073709551599 = 17 But now 18446744073709551599 / 4080 = 4521260802379792 and size = size * 4080 = 18446744073709551360 This is checked to make sure its still greater than 2 * 4080, which it is. Then we convert to the number of buffer pages needed. nr_page = DIV_ROUND_UP(size, BUF_PAGE_SIZE) but this time size is 18446744073709551360 and 2^64 - (18446744073709551360 + 4080 - 1) = -3823 Thus it overflows and the resulting number is less than 4080, which makes 3823 / 4080 = 0 an nr_pages is set to this. As we already checked against the minimum that nr_pages may be, this causes the logic to fail as well, and we crash the kernel. There's no reason to have the two DIV_ROUND_UP() (that's just result of historical code changes), clean up the code and fix this bug. Cc: stable@vger.kernel.org # 3.5+ Fixes: 83f40318dab00 ("ring-buffer: Make removal of ring buffer pages atomic") Signed-off-by: Steven Rostedt (cherry picked from commit 59643d1535eb220668692a5359de22545af579f6) Git-repo: http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git Git-commit: 59643d1535eb220668692a5359de22545af579f6 Change-Id: If773b9678be6cbcd1a8821bbd23be798a3289948 Signed-off-by: Srinivasa Rao Kuppala --- kernel/trace/ring_buffer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index af365ed7878e..2fdfff0d2a34 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1646,14 +1646,13 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, !cpumask_test_cpu(cpu_id, buffer->cpumask)) return size; - size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); - size *= BUF_PAGE_SIZE; + nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); /* we need a minimum of two pages */ - if (size < BUF_PAGE_SIZE * 2) - size = BUF_PAGE_SIZE * 2; + if (nr_pages < 2) + nr_pages = 2; - nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); + size = nr_pages * BUF_PAGE_SIZE; /* * Don't succeed if resizing is disabled, as a reader might be From 2b7f95504ba80a9d5e4b456fe4929c30cb6bb6b0 Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Sun, 13 Nov 2016 17:03:13 -0800 Subject: [PATCH 052/210] input: synaptics_dsx: add update bounds checks. Firmware updates contain offsets that are parsed by the kernel driver. Ensure all offsets are within the bounds of the firmware update. TESTED: successfully parsed update firmware on device boot. Bug: 31525965 Bug: 31968442 Change-Id: I074d3f26d33f723a0b239b59ebc3a680d991cdae Signed-off-by: Andrew Chant Git-repo: https://android.googlesource.com/kernel/msm Git-commit: ac2afe08221e0d077befd2e6f216598640af2d51 Signed-off-by: Dennis Cagle --- .../input/touchscreen/synaptics_fw_update.c | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c index c25a47528c41..f50378046f5e 100644 --- a/drivers/input/touchscreen/synaptics_fw_update.c +++ b/drivers/input/touchscreen/synaptics_fw_update.c @@ -258,6 +258,7 @@ struct synaptics_rmi4_fwu_handle { bool interrupt_flag; bool polling_mode; char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1]; + unsigned int full_update_size; unsigned int image_size; unsigned int data_pos; unsigned char intr_mask; @@ -297,6 +298,22 @@ static struct synaptics_rmi4_fwu_handle *fwu; DECLARE_COMPLETION(fwu_remove_complete); DEFINE_MUTEX(fwu_sysfs_mutex); +/* Check offset + size <= bound. 1 if in bounds, 0 otherwise. */ +static bool in_bounds(unsigned long offset, + unsigned long size, + unsigned long bound) +{ + if (offset > bound || size > bound) { + pr_err("%s: %lu or %lu > %lu\n", __func__, offset, size, bound); + return 0; + } + if (offset > (bound - size)) { + pr_err("%s: %lu > %lu - %lu\n", __func__, offset, size, bound); + return 0; + } + return 1; +} + static unsigned int extract_uint(const unsigned char *ptr) { return (unsigned int)ptr[0] + @@ -333,11 +350,17 @@ static void synaptics_rmi4_update_debug_info(void) pkg_id[3] << 8 | pkg_id[2], build_id); } -static void parse_header(void) +static int parse_header(void) { struct image_content *img = &fwu->image_content; struct image_header_data *data = (struct image_header_data *)fwu->data_buffer; + if (fwu->full_update_size < sizeof(*data)) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Provided update too small"); + return -EINVAL; + } + img->checksum = extract_uint(data->file_checksum); img->bootloader_version = data->bootloader_version; img->image_size = extract_uint(data->firmware_size); @@ -374,12 +397,29 @@ static void parse_header(void) img->config_size); /* get UI firmware offset */ - if (img->image_size) + if (img->image_size) { + if (!in_bounds(FW_IMAGE_OFFSET, img->image_size, + fwu->full_update_size)) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "%s: image size out of bounds\n", + __func__); + return -EINVAL; + } img->firmware_data = fwu->data_buffer + FW_IMAGE_OFFSET; + } /* get config offset*/ - if (img->config_size) + if (img->config_size) { + // FW_IMAGE_OFFSET + image_size was ok as above + if (!in_bounds(FW_IMAGE_OFFSET + img->image_size, + img->config_size, fwu->full_update_size)) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "%s: config size out of bounds\n", + __func__); + return -EINVAL; + } img->config_data = fwu->data_buffer + FW_IMAGE_OFFSET + img->image_size; + } /* get lockdown offset*/ switch (img->bootloader_version) { case 3: @@ -398,6 +438,14 @@ static void parse_header(void) img->lockdown_data = NULL; } + if (img->lockdown_block_count * fwu->block_size > FW_IMAGE_OFFSET) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "%s: lockdown size too big\n", + __func__); + return -EINVAL; + } + if (fwu->full_update_size < FW_IMAGE_OFFSET) + return -EINVAL; img->lockdown_data = fwu->data_buffer + FW_IMAGE_OFFSET - img->lockdown_block_count * fwu->block_size; @@ -406,7 +454,7 @@ static void parse_header(void) fwu->lockdown_data = img->lockdown_data; fwu->config_data = img->config_data; fwu->firmware_data = img->firmware_data; - return; + return 0; } static int fwu_read_f01_device_status(struct f01_device_status *status) @@ -1290,8 +1338,8 @@ static int fwu_start_write_config(void) "%s: write config from config file\n", __func__); fwu->config_data = fwu->data_buffer; - } else { - parse_header(); + } else if (parse_header()) { + return -EINVAL; } pr_notice("%s: Start of write config process\n", __func__); @@ -1358,7 +1406,8 @@ exit: static int fwu_start_write_lockdown(void) { - parse_header(); + if (parse_header()) + return -EINVAL; return fwu_do_write_lockdown(true); } @@ -1580,9 +1629,13 @@ static int fwu_start_reflash(void) __func__, fw_entry->size); fwu->data_buffer = fw_entry->data; + fwu->full_update_size = fw_entry->size; } - parse_header(); + if (parse_header()) { + retval = -EINVAL; + goto exit; + } flash_area = fwu_go_nogo(); if (fwu->rmi4_data->sensor_sleep) { @@ -2021,6 +2074,7 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, if (!mutex_trylock(&fwu_sysfs_mutex)) return -EBUSY; + fwu->full_update_size = size; fwu->image_size = size; fwu->data_pos = 0; From eaba82c730e78581328328ccc5633745d60f1eff Mon Sep 17 00:00:00 2001 From: John Dias Date: Wed, 9 Nov 2016 11:03:57 -0800 Subject: [PATCH 053/210] perf: don't leave group_entry on sibling list (use-after-free) When perf_group_detach is called on a group leader, it should empty its sibling list. Otherwise, when a sibling is later deallocated, list_del_event() removes the sibling's group_entry from its current list, which can be the now-deallocated group leader's sibling list (use-after-free bug). Bug: 32402548 Change-Id: I99f6bc97c8518df1cb0035814368012ba72ab1f1 Signed-off-by: John Dias Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 6b6cfb2362f09553b46b3b7e5684b16b6e53e373 Signed-off-by: Dennis Cagle --- kernel/events/core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 5c4b7f7ae69b..a8bf970e8f68 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1324,10 +1324,17 @@ static void perf_group_detach(struct perf_event *event) * If this was a group event with sibling events then * upgrade the siblings to singleton events by adding them * to whatever list we are on. + * If this isn't on a list, make sure we still remove the sibling's + * group_entry from this sibling_list; otherwise, when that sibling + * is later deallocated, it will try to remove itself from this + * sibling_list, which may well have been deallocated already, + * resulting in a use-after-free. */ list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) { if (list) list_move_tail(&sibling->group_entry, list); + else + list_del_init(&sibling->group_entry); sibling->group_leader = sibling; /* Inherit group flags from the previous leader */ From 10132a34e87c22a8d3afab8228343329e2a35f63 Mon Sep 17 00:00:00 2001 From: Puja Gupta Date: Mon, 16 Jan 2017 15:56:27 -0800 Subject: [PATCH 054/210] soc: qcom: pil: Fix kernel pointer leak Replace WARN with pr_warn so that stack trace is not printed with the message. CRs-Fixed: 1111653 Change-Id: Id1c7bbe8a528199261455ba7901e9df81913aef8 Signed-off-by: Puja Gupta --- drivers/soc/qcom/subsystem_restart.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index b429fa9170ac..57c7138eb622 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, 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 @@ -1001,8 +1001,9 @@ int subsystem_restart_dev(struct subsys_device *dev) pr_info("Restart sequence requested for %s, restart_level = %s.\n", name, restart_levels[dev->restart_level]); - if (WARN(disable_restart_work == DISABLE_SSR, - "subsys-restart: Ignoring restart request for %s.\n", name)) { + if (disable_restart_work == DISABLE_SSR) { + pr_warn("subsys-restart: Ignoring restart request for %s.\n", + name); return 0; } From 163582b516b832222d653819d4b1047c512adcb6 Mon Sep 17 00:00:00 2001 From: yidongh Date: Tue, 13 Dec 2016 19:19:01 +0800 Subject: [PATCH 055/210] ASOC: msm: Restrict loop index to avoid buffer overread Add restriction in msm_dolby_dap_param_to_get_control_get to avoid reading buffer data with index over buffer size. Change-Id: I2bd443d4db1a272d20341fbb5b15891a8acf0bc8 CRs-Fixed: 1096076 Signed-off-by: Yidong Huang --- sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c index 5866e46cc6a2..e03165c1f10d 100644 --- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c @@ -1,4 +1,6 @@ -/* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved. +/* +* Copyright (c) 2013-2014, 2016-2017, 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. @@ -803,6 +805,10 @@ int msm_dolby_dap_param_to_get_control_get(struct snd_kcontrol *kcontrol, __func__, copp_idx); return -EINVAL; } + if (dolby_dap_params_get.length > 128 - DOLBY_PARAM_PAYLOAD_SIZE) { + pr_err("%s: Incorrect parameter length", __func__); + return -EINVAL; + } params_value = kzalloc(params_length, GFP_KERNEL); if (!params_value) { pr_err("%s, params memory alloc failed\n", __func__); From 17743ef87b333024b9df69a0ffc7dc9c7849bca1 Mon Sep 17 00:00:00 2001 From: kunleiz Date: Thu, 22 Dec 2016 18:03:37 +0800 Subject: [PATCH 056/210] ASoC: msm: qdspv2: add mutex lock when access output buffer length Add mutex protection to avoid access output_len in parallel. CRs-Fixed: 1104067 Change-Id: I4e17258e2abee9cd68152f4b79520b00003aa80d Signed-off-by: kunleiz --- drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index 940fd08654d2..089a82788643 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016-2017, 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 @@ -29,6 +29,8 @@ struct q6audio_effects { struct audio_client *ac; struct msm_hwacc_effects_config config; + struct mutex lock; + atomic_t in_count; atomic_t out_count; @@ -230,8 +232,11 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, uint32_t idx = 0; uint32_t size = 0; + mutex_lock(&effects->lock); + if (!effects->started) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -241,11 +246,13 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (!rc) { pr_err("%s: write wait_event_timeout\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } if (!atomic_read(&effects->out_count)) { pr_err("%s: pcm stopped out_count 0\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -255,6 +262,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, copy_from_user(bufptr, (void *)arg, effects->config.buf_cfg.output_len)) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } rc = q6asm_write(effects->ac, @@ -262,6 +270,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, 0, 0, NO_TIMESTAMP); if (rc < 0) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } atomic_dec(&effects->out_count); @@ -269,6 +278,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: AUDIO_EFFECTS_WRITE: Buffer dropped\n", __func__); } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_READ: { @@ -466,6 +476,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, break; } case AUDIO_EFFECTS_SET_BUF_LEN: { + mutex_lock(&effects->lock); if (copy_from_user(&effects->config.buf_cfg, (void *)arg, sizeof(effects->config.buf_cfg))) { pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n", @@ -475,6 +486,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, pr_debug("%s: write buf len: %d, read buf len: %d\n", __func__, effects->config.buf_cfg.output_len, effects->config.buf_cfg.input_len); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_GET_BUF_AVAIL: { @@ -719,6 +731,7 @@ static int audio_effects_release(struct inode *inode, struct file *file) } q6asm_audio_client_free(effects->ac); + mutex_destroy(&effects->lock); kfree(effects); pr_debug("%s: close session success\n", __func__); @@ -749,6 +762,7 @@ static int audio_effects_open(struct inode *inode, struct file *file) init_waitqueue_head(&effects->read_wait); init_waitqueue_head(&effects->write_wait); + mutex_init(&effects->lock); effects->opened = 0; effects->started = 0; From 36e4ae739151b95a07257cc763181c931e807644 Mon Sep 17 00:00:00 2001 From: Dhoat Harpal Date: Mon, 9 Jan 2017 17:31:54 +0530 Subject: [PATCH 057/210] soc: qcom: smem: Fix uninitialized usage of a stack variable variable size is output variable and is not initialized, printing it can lead to information leak. variable size is removed from log message. CRs-Fixed: 1093837 Change-Id: I95cf227bb82a2ee7c6f43db151f75a942e8e55ce Signed-off-by: Dhoat Harpal --- drivers/soc/qcom/smem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index f908574b8d8b..616b6d24f5a6 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017 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 @@ -362,7 +362,7 @@ static void *__smem_get_entry_secure(unsigned id, uint32_t a_hdr_size; int rc; - SMEM_DBG("%s(%u, %u, %u, %u, %d, %d)\n", __func__, id, *size, to_proc, + SMEM_DBG("%s(%u, %u, %u, %d, %d)\n", __func__, id, to_proc, flags, skip_init_check, use_rspinlock); if (!skip_init_check && !smem_initialized_check()) @@ -777,7 +777,7 @@ EXPORT_SYMBOL(smem_alloc); void *smem_get_entry(unsigned id, unsigned *size, unsigned to_proc, unsigned flags) { - SMEM_DBG("%s(%u, %u, %u, %u)\n", __func__, id, *size, to_proc, flags); + SMEM_DBG("%s(%u, %u, %u)\n", __func__, id, to_proc, flags); /* * Handle the circular dependecy between SMEM and software implemented From 7482f44517440784eafa94219dbd59f05fbf9052 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 2 Nov 2016 17:43:51 -0700 Subject: [PATCH 058/210] ion: Fix use after free during ION_IOC_ALLOC If a user happens to call ION_IOC_FREE during an ION_IOC_ALLOC on the just allocated id, and the copy_to_user fails, the cleanup code will attempt to free an already freed handle. This adds a wrapper for ion_alloc that adds an ion_handle_get to avoid this. Bug: 31568617 Change-Id: I476e5bd5372b5178a213f1fea143d270cf9361ed Signed-off-by: Daniel Rosenberg Git-repo: https://android.googlesource.com/kernel/msm/ Git-commit: 20a5411d0115b16826f3d327b6abb0192c8a2001 Signed-off-by: Dennis Cagle --- drivers/staging/android/ion/ion.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index b2c2444d2745..bbd6977ee68f 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -503,9 +503,9 @@ static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) return 0; } -struct ion_handle *ion_alloc(struct ion_client *client, size_t len, +static struct ion_handle *__ion_alloc(struct ion_client *client, size_t len, size_t align, unsigned int heap_id_mask, - unsigned int flags) + unsigned int flags, bool grab_handle) { struct ion_handle *handle; struct ion_device *dev = client->dev; @@ -600,6 +600,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, return handle; mutex_lock(&client->lock); + if (grab_handle) + ion_handle_get(handle); ret = ion_handle_add(client, handle); mutex_unlock(&client->lock); if (ret) { @@ -609,6 +611,13 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, return handle; } + +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + size_t align, unsigned int heap_id_mask, + unsigned int flags) +{ + return __ion_alloc(client, len, align, heap_id_mask, flags, false); +} EXPORT_SYMBOL(ion_alloc); static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) @@ -1485,10 +1494,10 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_handle *handle; - handle = ion_alloc(client, data.allocation.len, + handle = __ion_alloc(client, data.allocation.len, data.allocation.align, data.allocation.heap_id_mask, - data.allocation.flags); + data.allocation.flags, true); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1565,11 +1574,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (dir & _IOC_READ) { if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { - if (cleanup_handle) + if (cleanup_handle) { ion_free(client, cleanup_handle); + ion_handle_put(cleanup_handle); + } return -EFAULT; } } + if (cleanup_handle) + ion_handle_put(cleanup_handle); return ret; } From 93dd37c412dbadff9d5b1b6f7b317713192cab2b Mon Sep 17 00:00:00 2001 From: Conner Huff Date: Thu, 26 Jan 2017 11:52:17 -0800 Subject: [PATCH 059/210] net: rmnet_data: Fix incorrect netlink handling rmnet_data netlink handler currently does not check for the incoming process pid and instead just loops back the pid. A malicious root user could potentially send a message with source pid 0 and this could cause rmnet_data to loop the message back till an out of memory situation occurs. rmnet_data also does not check for the message length of the incoming netlink messages and instead casts the netlink message without checking for the boundary. Fix these two scenarios by adding the pid and message length checks respectively. Bug: 31252965 CRs-Fixed: 1098801 Change-Id: I172c1a7112e67e82959b397af7ddfd963d819bdc Signed-off-by: Conner Huff --- net/rmnet_data/rmnet_data_config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index 2a4f56bd9cbe..04d639895381 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017 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 @@ -531,6 +531,11 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) nlmsg_header = (struct nlmsghdr *) skb->data; rmnet_header = (struct rmnet_nl_msg_s *) nlmsg_data(nlmsg_header); + if (!nlmsg_header->nlmsg_pid || + (nlmsg_header->nlmsg_len < sizeof(struct nlmsghdr) + + sizeof(struct rmnet_nl_msg_s))) + return; + LOGL("Netlink message pid=%d, seq=%d, length=%d, rmnet_type=%d", nlmsg_header->nlmsg_pid, nlmsg_header->nlmsg_seq, From ecf169bd6b0c9d5093262347b3407bff6d0cc36a Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Mon, 19 Dec 2016 18:38:53 -0800 Subject: [PATCH 060/210] ASoC: msm: qdsp6v2: Add range checking in msm_dai_q6_set_channel_map Range checking is added to prevent buffer overflow that due to inputs can be set by user space. CRs-Fixed: 1098363 Change-Id: I057261291806240ee6d7b8106a5e83a7665e013d Signed-off-by: Xiaoyu Ye --- sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 4a7b1ee33c93..88dd59f5b66e 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -1382,6 +1382,11 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, pr_err("%s: rx slot not found\n", __func__); return -EINVAL; } + if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { + pr_err("%s: invalid rx num %d\n", __func__, rx_num); + return -EINVAL; + } + for (i = 0; i < rx_num; i++) { dai_data->port_config.slim_sch.shared_ch_mapping[i] = rx_slot[i]; @@ -1412,6 +1417,11 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, pr_err("%s: tx slot not found\n", __func__); return -EINVAL; } + if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { + pr_err("%s: invalid tx num %d\n", __func__, tx_num); + return -EINVAL; + } + for (i = 0; i < tx_num; i++) { dai_data->port_config.slim_sch.shared_ch_mapping[i] = tx_slot[i]; From 0226790bccbaa1f409fa6a731f1a943d6efcc9c9 Mon Sep 17 00:00:00 2001 From: Andrey Markovytch Date: Mon, 23 Jan 2017 10:22:58 +0200 Subject: [PATCH 061/210] security: switched to stackable model for PFT/PFK module Moved hooks from SELINUX framework to general SECURITY framework Change-Id: I37e701b4925c4993f724c32b258c5088f4dcbe4d Signed-off-by: Andrey Markovytch Signed-off-by: Yang Guang --- drivers/platform/msm/pft.c | 8 +++-- security/selinux/hooks.c | 68 ++------------------------------------ 2 files changed, 8 insertions(+), 68 deletions(-) diff --git a/drivers/platform/msm/pft.c b/drivers/platform/msm/pft.c index 9a44c30e0607..470b31bb8158 100644 --- a/drivers/platform/msm/pft.c +++ b/drivers/platform/msm/pft.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, 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 @@ -217,12 +217,14 @@ static int __init pft_lsm_init(struct pft_device *dev) ret = register_security(&pft_security_ops); if (ret) { pr_err("pft lsm registeration failed, ret=%d.\n", ret); - return 0; + return ret; } + dev->is_chosen_lsm = true; pr_debug("pft is the chosen lsm, registered sucessfully !\n"); } else { - pr_debug("pft is not the chosen lsm.\n"); + pr_err("pft is not the chosen lsm.\n"); + return -ENODEV; } return 0; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7e1768dae486..ec14e71d07e9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -84,7 +84,6 @@ #include #include #include -#include #include "avc.h" @@ -1684,14 +1683,8 @@ static int may_create(struct inode *dir, return rc; return avc_has_perm(newsid, sbsec->sid, - SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, &ad); - if (rc) - return rc; - - rc = pft_inode_mknod(dir, dentry, 0, 0); - - return rc; + SECCLASS_FILESYSTEM, + FILESYSTEM__ASSOCIATE, &ad); } /* Check whether a task can create a key. */ @@ -1747,14 +1740,7 @@ static int may_link(struct inode *dir, return 0; } - rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); - if (rc) - return rc; - - if (kind == MAY_UNLINK) - rc = pft_inode_unlink(dir, dentry); - - return rc; + return avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); } static inline int may_rename(struct inode *old_dir, @@ -2653,24 +2639,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) { - int ret; - - ret = pft_inode_create(dir, dentry, mode); - if (ret < 0) - return ret; return may_create(dir, dentry, SECCLASS_FILE); } -static int selinux_inode_post_create(struct inode *dir, struct dentry *dentry, - umode_t mode) -{ - int ret; - - ret = pft_inode_post_create(dir, dentry, mode); - - return ret; -} - static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { return may_link(dir, old_dentry, MAY_LINK); @@ -2704,12 +2675,6 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) { - int rc; - - rc = pft_inode_rename(old_inode, old_dentry, new_inode, new_dentry); - if (rc) - return rc; - return may_rename(old_inode, old_dentry, new_inode, new_dentry); } @@ -2828,9 +2793,6 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) { const struct cred *cred = current_cred(); - if (pft_inode_set_xattr(dentry, name, NULL, 0, 0) < 0) - return -EACCES; - if (!strncmp(name, XATTR_SECURITY_PREFIX, sizeof XATTR_SECURITY_PREFIX - 1)) { if (!strcmp(name, XATTR_NAME_CAPS)) { @@ -3074,16 +3036,11 @@ static int selinux_file_permission(struct file *file, int mask) struct file_security_struct *fsec = file->f_security; struct inode_security_struct *isec = inode->i_security; u32 sid = current_sid(); - int ret; if (!mask) /* No permission to check. Existence test. */ return 0; - ret = pft_file_permission(file, mask); - if (ret < 0) - return ret; - if (sid == fsec->sid && fsec->isid == isec->sid && fsec->pseqno == avc_policy_seqno()) /* No change since file_open check. */ @@ -3377,11 +3334,6 @@ static int selinux_file_open(struct file *file, const struct cred *cred) { struct file_security_struct *fsec; struct inode_security_struct *isec; - int ret; - - ret = pft_file_open(file, cred); - if (ret < 0) - return ret; fsec = file->f_security; isec = file_inode(file)->i_security; @@ -3405,17 +3357,6 @@ static int selinux_file_open(struct file *file, const struct cred *cred) return path_has_perm(cred, &file->f_path, open_file_to_av(file)); } -static int selinux_file_close(struct file *file) -{ - return pft_file_close(file); -} - - -static bool selinux_allow_merge_bio(struct bio *bio1, struct bio *bio2) -{ - return pft_allow_merge_bio(bio1, bio2); -} - /* task security operations */ static int selinux_task_create(unsigned long clone_flags) @@ -5818,7 +5759,6 @@ static struct security_operations selinux_ops = { .inode_free_security = selinux_inode_free_security, .inode_init_security = selinux_inode_init_security, .inode_create = selinux_inode_create, - .inode_post_create = selinux_inode_post_create, .inode_link = selinux_inode_link, .inode_unlink = selinux_inode_unlink, .inode_symlink = selinux_inode_symlink, @@ -5855,8 +5795,6 @@ static struct security_operations selinux_ops = { .file_receive = selinux_file_receive, .file_open = selinux_file_open, - .file_close = selinux_file_close, - .allow_merge_bio = selinux_allow_merge_bio, .task_create = selinux_task_create, .cred_alloc_blank = selinux_cred_alloc_blank, From 9d6c3a2ff78c657b7268f5f3c3f46d48d8df09d6 Mon Sep 17 00:00:00 2001 From: Sharad Sangle Date: Mon, 19 Dec 2016 17:00:25 +0530 Subject: [PATCH 062/210] ASoC: msm: qdsp6v2: DAP: Add check to validate param length To avoid buffer overflow, validate input length used to set Dolby params. Change-Id: I3f9d6040f118f63b60c20c83b0d8cae638f4a530 CRs-Fixed: 1095947 Signed-off-by: Sharad Sangle --- sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c index e03165c1f10d..d04d80c95340 100644 --- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c @@ -683,7 +683,7 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0, port_id, copp_idx; - uint32_t idx, j; + uint32_t idx, j, current_offset; uint32_t device = ucontrol->value.integer.value[0]; uint32_t param_id = ucontrol->value.integer.value[1]; uint32_t offset = ucontrol->value.integer.value[2]; @@ -760,6 +760,19 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, default: { /* cache the parameters */ dolby_dap_params_modified[idx] += 1; + current_offset = dolby_dap_params_offset[idx] + offset; + if (current_offset >= TOTAL_LENGTH_DOLBY_PARAM) { + pr_err("%s: invalid offset %d at idx %d\n", + __func__, offset, idx); + return -EINVAL; + } + if ((0 == length) || (current_offset + length - 1 + < current_offset) || (current_offset + length + > TOTAL_LENGTH_DOLBY_PARAM)) { + pr_err("%s: invalid length %d at idx %d\n", + __func__, length, idx); + return -EINVAL; + } dolby_dap_params_length[idx] = length; pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n", __func__, device, param_id, offset, length); From 9c9c161925e106e7fd126f738f17cd2065b9cb5f Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Wed, 11 Jan 2017 12:12:31 -0800 Subject: [PATCH 063/210] qseecom: improve input validatation for qseecom_send_service_cmd Make change to improve input validation on request and response buffers' address and length for qseecom_send_service_cmd. Change-Id: I047e3264333d767541e43b7dadd1727232fd48ef Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 152 ++++++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 64 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 993d853d36d2..39f784124bfe 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1,6 +1,6 @@ /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver * - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 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 @@ -2345,11 +2345,6 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, return -EINVAL; } - if ((!req_ptr->cmd_req_buf) || (!req_ptr->resp_buf)) { - pr_err("Invalid req/resp buffer, exiting\n"); - return -EINVAL; - } - /* Clients need to ensure req_buf is at base offset of shared buffer */ if ((uintptr_t)req_ptr->cmd_req_buf != data_ptr->client.user_virt_sb_base) { @@ -2357,15 +2352,11 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, return -EINVAL; } - if (((uintptr_t)req_ptr->resp_buf < - data_ptr->client.user_virt_sb_base) || - ((uintptr_t)req_ptr->resp_buf >= - (data_ptr->client.user_virt_sb_base + - data_ptr->client.sb_length))){ - pr_err("response buffer address not within shared bufffer\n"); + if (data_ptr->client.sb_length < + sizeof(struct qseecom_rpmb_provision_key)) { + pr_err("shared buffer is too small to hold key type\n"); return -EINVAL; } - req_buf = data_ptr->client.sb_virt; send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id; @@ -2392,36 +2383,6 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, return -EINVAL; } - if (((uintptr_t)req_ptr->cmd_req_buf < - data_ptr->client.user_virt_sb_base) || - ((uintptr_t)req_ptr->cmd_req_buf >= - (data_ptr->client.user_virt_sb_base + - data_ptr->client.sb_length))) { - pr_err("cmd buffer address not within shared bufffer\n"); - return -EINVAL; - } - - if (((uintptr_t)req_ptr->resp_buf < - data_ptr->client.user_virt_sb_base) || - ((uintptr_t)req_ptr->resp_buf >= - (data_ptr->client.user_virt_sb_base + - data_ptr->client.sb_length))){ - pr_err("response buffer address not within shared bufffer\n"); - return -EINVAL; - } - - if ((req_ptr->cmd_req_len == 0) || (req_ptr->resp_len == 0) || - req_ptr->cmd_req_len > data_ptr->client.sb_length || - req_ptr->resp_len > data_ptr->client.sb_length) { - pr_err("cmd buffer length or response buffer length not valid\n"); - return -EINVAL; - } - - if (req_ptr->cmd_req_len > UINT_MAX - req_ptr->resp_len) { - pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); - return -EINVAL; - } - reqd_len_sb_in = req_ptr->cmd_req_len + req_ptr->resp_len; if (reqd_len_sb_in > data_ptr->client.sb_length) { pr_err("Not enough memory to fit cmd_buf and resp_buf. "); @@ -2443,28 +2404,11 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, return ret; } -static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, - void __user *argp) +static int __validate_send_service_cmd_inputs(struct qseecom_dev_handle *data, + struct qseecom_send_svc_cmd_req *req) { - int ret = 0; - struct qseecom_client_send_service_ireq send_svc_ireq; - struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; - struct qseecom_command_scm_resp resp; - struct qseecom_send_svc_cmd_req req; - void *send_req_ptr; - size_t req_buf_size; - - /*struct qseecom_command_scm_resp resp;*/ - - if (copy_from_user(&req, - (void __user *)argp, - sizeof(req))) { - pr_err("copy_from_user failed\n"); - return -EFAULT; - } - - if ((req.resp_buf == NULL) || (req.cmd_req_buf == NULL)) { - pr_err("cmd buffer or response buffer is null\n"); + if (!req || !req->resp_buf || !req->cmd_req_buf) { + pr_err("req or cmd buffer or response buffer is null\n"); return -EINVAL; } @@ -2488,6 +2432,86 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, return -EINVAL; } + if (((uintptr_t)req->cmd_req_buf < + data->client.user_virt_sb_base) || + ((uintptr_t)req->cmd_req_buf >= + (data->client.user_virt_sb_base + data->client.sb_length))) { + pr_err("cmd buffer address not within shared bufffer\n"); + return -EINVAL; + } + if (((uintptr_t)req->resp_buf < + data->client.user_virt_sb_base) || + ((uintptr_t)req->resp_buf >= + (data->client.user_virt_sb_base + data->client.sb_length))) { + pr_err("response buffer address not within shared bufffer\n"); + return -EINVAL; + } + if ((req->cmd_req_len == 0) || (req->resp_len == 0) || + (req->cmd_req_len > data->client.sb_length) || + (req->resp_len > data->client.sb_length)) { + pr_err("cmd buf length or response buf length not valid\n"); + return -EINVAL; + } + if (req->cmd_req_len > UINT_MAX - req->resp_len) { + pr_err("Integer overflow detected in req_len & rsp_len\n"); + return -EINVAL; + } + + if ((req->cmd_req_len + req->resp_len) > data->client.sb_length) { + pr_debug("Not enough memory to fit cmd_buf.\n"); + pr_debug("resp_buf. Required: %u, Available: %zu\n", + (req->cmd_req_len + req->resp_len), + data->client.sb_length); + return -ENOMEM; + } + if ((uintptr_t)req->cmd_req_buf > (ULONG_MAX - req->cmd_req_len)) { + pr_err("Integer overflow in req_len & cmd_req_buf\n"); + return -EINVAL; + } + if ((uintptr_t)req->resp_buf > (ULONG_MAX - req->resp_len)) { + pr_err("Integer overflow in resp_len & resp_buf\n"); + return -EINVAL; + } + if (data->client.user_virt_sb_base > + (ULONG_MAX - data->client.sb_length)) { + pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); + return -EINVAL; + } + if ((((uintptr_t)req->cmd_req_buf + req->cmd_req_len) > + ((uintptr_t)data->client.user_virt_sb_base + + data->client.sb_length)) || + (((uintptr_t)req->resp_buf + req->resp_len) > + ((uintptr_t)data->client.user_virt_sb_base + + data->client.sb_length))) { + pr_err("cmd buf or resp buf is out of shared buffer region\n"); + return -EINVAL; + } + return 0; +} + +static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, + void __user *argp) +{ + int ret = 0; + struct qseecom_client_send_service_ireq send_svc_ireq; + struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; + struct qseecom_command_scm_resp resp; + struct qseecom_send_svc_cmd_req req; + void *send_req_ptr; + size_t req_buf_size; + + /*struct qseecom_command_scm_resp resp;*/ + + if (copy_from_user(&req, + (void __user *)argp, + sizeof(req))) { + pr_err("copy_from_user failed\n"); + return -EFAULT; + } + + if (__validate_send_service_cmd_inputs(data, &req)) + return -EINVAL; + data->type = QSEECOM_SECURE_SERVICE; switch (req.cmd_id) { From 859d6579af5dd26db3eb9ac44a93a250542eba64 Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Mon, 5 Dec 2016 12:26:52 -0800 Subject: [PATCH 064/210] ASoC: msm: qdsp6v2: return error when copy from userspace fails A copy_from_user is not always expected to succeed. Therefore, check for an error before operating on the buffer post copy. Change-Id: Ibba9a47c84e735d30e32eeac5b80d51044b7a9e8 CRs-Fixed: 1094852 Signed-off-by: Siena Richard --- sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c index 08c4f2ac6401..53f57cd39a94 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c @@ -827,6 +827,11 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, (sizeof(buf_node->frame.frm_hdr) + sizeof(buf_node->frame.pktlen)); } + if (ret) { + pr_err("%s: copy from user failed %d\n", + __func__, ret); + return -EFAULT; + } spin_lock_irqsave(&prtd->dsp_lock, dsp_flags); list_add_tail(&buf_node->list, &prtd->in_queue); spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags); From e023a636d245708fad2b2563514dacda9f05e77f Mon Sep 17 00:00:00 2001 From: Karthik Reddy Katta Date: Tue, 3 Jan 2017 11:09:05 +0530 Subject: [PATCH 065/210] drivers: soc: qcom: Add overflow check in ADM driver Add overflow check for param length to prevent heap overflow while allocating memory for ADM parameters. CRs-Fixed: 1103334 Change-Id: I1163aeaabbc84dba4cd0739a35ecbdee18b42717 Signed-off-by: Karthik Reddy Katta --- sound/soc/msm/qdsp6v2/q6adm.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 5f20b81d8c02..a9d23e75ee15 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2016, 2017 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 @@ -969,9 +969,10 @@ int adm_get_params_v2(int port_id, int copp_idx, uint32_t module_id, char *params, uint32_t client_id) { struct adm_cmd_get_pp_params_v5 *adm_params = NULL; - int sz, rc = 0, i = 0; + int rc = 0, i = 0; int port_idx, idx; int *params_data = (int *)params; + uint64_t sz = 0; port_id = afe_convert_virtual_to_portid(port_id); port_idx = adm_validate_and_get_port_index(port_id); @@ -980,7 +981,16 @@ int adm_get_params_v2(int port_id, int copp_idx, uint32_t module_id, return -EINVAL; } - sz = sizeof(struct adm_cmd_get_pp_params_v5) + params_length; + sz = (uint64_t)sizeof(struct adm_cmd_get_pp_params_v5) + + (uint64_t)params_length; + /* + * Check if the value of "sz" (which is ultimately assigned to + * "hdr.pkt_size") crosses U16_MAX. + */ + if (sz > U16_MAX) { + pr_err("%s: Invalid params_length\n", __func__); + return -EINVAL; + } adm_params = kzalloc(sz, GFP_KERNEL); if (!adm_params) { pr_err("%s: adm params memory alloc failed", __func__); From 96230c3f66cd1b97e8ee981dfb2d33116fdd93ac Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Tue, 20 Dec 2016 10:56:59 -0800 Subject: [PATCH 066/210] mfd: wcd9xxx: Add range checking in function wcd9xxx_init_slimslave Range checking is added to prevent buffer overflow. CRs-Fixed: 1098363 Change-Id: I5871a3a11ec5f5106a386bf149d7ec22605f3db8 Signed-off-by: Xiaoyu Ye --- drivers/mfd/wcd9xxx-slimslave.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c index 3ad63abf5b27..fd35c2642389 100644 --- a/drivers/mfd/wcd9xxx-slimslave.c +++ b/drivers/mfd/wcd9xxx-slimslave.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -62,6 +62,10 @@ int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la, goto err; } + if (!rx_num || rx_num > wcd9xxx->num_rx_port) { + pr_err("%s: invalid rx num %d\n", __func__, rx_num); + return -EINVAL; + } if (wcd9xxx->rx_chs) { wcd9xxx->num_rx_port = rx_num; for (i = 0; i < rx_num; i++) { @@ -84,6 +88,10 @@ int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la, wcd9xxx->num_rx_port); } + if (!tx_num || tx_num > wcd9xxx->num_tx_port) { + pr_err("%s: invalid tx num %d\n", __func__, tx_num); + return -EINVAL; + } if (wcd9xxx->tx_chs) { wcd9xxx->num_tx_port = tx_num; for (i = 0; i < tx_num; i++) { From 2ebf105d6fa9eb4f2b94c1623d20777099676188 Mon Sep 17 00:00:00 2001 From: Banajit Goswami Date: Wed, 6 Jan 2016 12:21:13 -0800 Subject: [PATCH 067/210] Revert "ASoC: wcd_cpe_core: Perform irq cleanup once the bus is up" This reverts commit 74041210be67 ("ASoC: wcd_cpe_core: Perform irq cleanup once the bus is up") CRs-Fixed: 1102353 Change-Id: I7883615b009051c20e11b95b7fca0ef82225e6f5 Signed-off-by: Banajit Goswami Signed-off-by: Bhalchandra Gajare --- sound/soc/codecs/wcd_cpe_core.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c index 16582fabfb41..d3713885836e 100644 --- a/sound/soc/codecs/wcd_cpe_core.c +++ b/sound/soc/codecs/wcd_cpe_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -889,14 +889,7 @@ static int wcd_cpe_enable(struct wcd_cpe_core *core, * instead SSR handler will control CPE. */ wcd_cpe_enable_cpe_clks(core, false); - /* - * During BUS_DOWN event, possibly the - * irq driver is under cleanup, do not request - * cleanup of irqs here, rather cleanup irqs - * once BUS_UP event is received. - */ - if (core->ssr_type != WCD_CPE_BUS_DOWN_EVENT) - wcd_cpe_cleanup_irqs(core); + wcd_cpe_cleanup_irqs(core); goto done; } @@ -1147,7 +1140,6 @@ int wcd_cpe_ssr_event(void *core_handle, break; case WCD_CPE_BUS_UP_EVENT: - wcd_cpe_cleanup_irqs(core); wcd_cpe_set_and_complete(core, WCD_CPE_BUS_READY); /* * In case of bus up event ssr_type will be changed From 12cae94bb20836722551a113be28663a9d3d362c Mon Sep 17 00:00:00 2001 From: Walter Yang Date: Wed, 21 Dec 2016 14:43:46 +0800 Subject: [PATCH 068/210] ASoC: msm-cpe-lsm: cleanup ioctl functions Some of the ioctl command handling is not properly using the copy_from_user interface. Fix these issues and cleanup the ioctl functions to make sure there is no illegal memory access. CRs-Fixed: 1090482 Change-Id: Ib18e4b132d3487a3103335768aad5df2ebe13f2d Signed-off-by: Walter Yang --- sound/soc/msm/msm-cpe-lsm.c | 54 +++++++++++-------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c index a4daf91d1e2f..100fa64a4d55 100644 --- a/sound/soc/msm/msm-cpe-lsm.c +++ b/sound/soc/msm/msm-cpe-lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -1192,13 +1192,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_REG_SND_MODEL_V2"); - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid argument to ioctl %s\n", - __func__, - "SNDRV_LSM_REG_SND_MODEL_V2"); - return -EINVAL; - } memcpy(&snd_model, arg, sizeof(struct snd_lsm_sound_model_v2)); @@ -1341,13 +1334,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_EVENT_STATUS"); - if (!arg) { - dev_err(rtd->dev, - "%s: Invalid argument to ioctl %s\n", - __func__, - "SNDRV_LSM_EVENT_STATUS"); - return -EINVAL; - } user = arg; @@ -1458,12 +1444,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_SET_PARAMS: - if (!arg) { - dev_err(rtd->dev, - "%s: %s Invalid argument\n", - __func__, "SNDRV_LSM_SET_PARAMS"); - return -EINVAL; - } memcpy(&det_params, arg, sizeof(det_params)); if (det_params.num_confidence_levels <= 0) { @@ -2340,12 +2320,6 @@ done: } #ifdef CONFIG_COMPAT -struct snd_lsm_event_status32 { - u16 status; - u16 payload_size; - u8 payload[0]; -}; - struct snd_lsm_sound_model_v2_32 { compat_uptr_t data; compat_uptr_t confidence_level; @@ -2377,8 +2351,6 @@ struct snd_lsm_module_params_32 { }; enum { - SNDRV_LSM_EVENT_STATUS32 = - _IOW('U', 0x02, struct snd_lsm_event_status32), SNDRV_LSM_REG_SND_MODEL_V2_32 = _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), SNDRV_LSM_SET_PARAMS32 = @@ -2473,7 +2445,7 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, err); } break; - case SNDRV_LSM_EVENT_STATUS32: { + case SNDRV_LSM_EVENT_STATUS: { struct snd_lsm_event_status *event_status = NULL; struct snd_lsm_event_status u_event_status32; struct snd_lsm_event_status *udata_32 = NULL; @@ -2515,7 +2487,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, } else { event_status->payload_size = u_event_status32.payload_size; - cmd = SNDRV_LSM_EVENT_STATUS; err = msm_cpe_lsm_ioctl_shared(substream, cmd, event_status); if (err) @@ -2617,14 +2588,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, goto done; } - if (!arg) { - dev_err(rtd->dev, - "%s: %s: No Param data to set\n", - __func__, "SET_MODULE_PARAMS_32"); - err = -EINVAL; - goto done; - } - if (copy_from_user(&p_data_32, arg, sizeof(p_data_32))) { dev_err(rtd->dev, @@ -2709,6 +2672,19 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, kfree(params32); break; } + case SNDRV_LSM_REG_SND_MODEL_V2: + case SNDRV_LSM_SET_PARAMS: + case SNDRV_LSM_SET_MODULE_PARAMS: + /* + * In ideal cases, the compat_ioctl should never be called + * with the above unlocked ioctl commands. Print error + * and return error if it does. + */ + dev_err(rtd->dev, + "%s: Invalid cmd for compat_ioctl\n", + __func__); + err = -EINVAL; + break; default: err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg); break; From ea1eb5865a2e7365b694d1eccc8888f817ec2871 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Mon, 7 Nov 2016 15:39:43 -0800 Subject: [PATCH 069/210] qseecom: fix incomplete error handling for several functions Perform a complete or adequate check of return codes for several functions, including __qseecom_enable_clk, ion_do_cache_op and ion_sg_table(), used by qseecom. Change-Id: Ib1682bdc6d3034a22586af62a3d8986c54d369d5 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 214 +++++++++++++++++++++++++++++++---------- 1 file changed, 162 insertions(+), 52 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 993d853d36d2..539e3c5eab09 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1219,9 +1219,11 @@ static int __qseecom_set_msm_bus_request(uint32_t mode) pr_err("Bandwidth req failed(%d) MODE (%d)\n", ret, mode); if (qclk->ce_core_src_clk != NULL) { - if (mode == INACTIVE) - __qseecom_enable_clk(CLK_QSEE); - else + if (mode == INACTIVE) { + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + pr_err("CLK enable failed\n"); + } else __qseecom_disable_clk(CLK_QSEE); } } @@ -1520,12 +1522,21 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data, pr_warn("listener_id:%x, lstnr: %x\n", ptr_svc->svc.listener_id, lstnr); - if (ptr_svc && ptr_svc->ihandle) - msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, + if (ptr_svc && ptr_svc->ihandle) { + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, ION_IOC_CLEAN_INV_CACHES); - if (lstnr == RPMB_SERVICE) - __qseecom_enable_clk(CLK_QSEE); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } + } + + if (lstnr == RPMB_SERVICE) { + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; + } ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, send_data_rsp, sizeof(send_data_rsp), resp, sizeof(*resp)); @@ -1668,13 +1679,22 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, else *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; - if (ptr_svc) - msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, + if (ptr_svc) { + ret = msm_ion_do_cache_op(qseecom.ion_clnt, + ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, - ION_IOC_CLEAN_INV_CACHES); + ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } + } - if ((lstnr == RPMB_SERVICE) || (lstnr == SSD_SERVICE)) - __qseecom_enable_clk(CLK_QSEE); + if ((lstnr == RPMB_SERVICE) || (lstnr == SSD_SERVICE)) { + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; + } ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, resp, sizeof(*resp)); @@ -1814,13 +1834,21 @@ static int __qseecom_reentrancy_process_incomplete_cmd( else *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; - if (ptr_svc) - msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, + if (ptr_svc) { + ret = msm_ion_do_cache_op(qseecom.ion_clnt, + ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, - ION_IOC_CLEAN_INV_CACHES); - - if (lstnr == RPMB_SERVICE) - __qseecom_enable_clk(CLK_QSEE); + ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } + } + if (lstnr == RPMB_SERVICE) { + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; + } ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, resp, sizeof(*resp)); @@ -2075,8 +2103,12 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) cmd_len = sizeof(struct qseecom_load_app_64bit_ireq); } - msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto loadapp_err; + } __qseecom_reentrancy_check_if_no_app_blocked(); @@ -2538,15 +2570,16 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, } } - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, data->client.sb_length, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto exit; + } ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)send_req_ptr, req_buf_size, &resp, sizeof(resp)); - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, - data->client.sb_virt, data->client.sb_length, - ION_IOC_INV_CACHES); if (ret) { pr_err("qseecom_scm_call failed with err: %d\n", ret); if (!qseecom.support_bus_scaling) { @@ -2558,7 +2591,13 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, } goto exit; } - + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + data->client.sb_virt, data->client.sb_length, + ION_IOC_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto exit; + } switch (resp.result) { case QSEOS_RESULT_SUCCESS: break; @@ -2824,10 +2863,14 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, else *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } __qseecom_reentrancy_check_if_this_app_blocked(ptr_app); @@ -2858,9 +2901,11 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, } } } - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, data->client.sb_length, ION_IOC_INV_CACHES); + if (ret) + pr_err("cache operation failed %d\n", ret); return ret; } @@ -2972,7 +3017,7 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, } /* Populate the cmd data structure with the phys_addr */ sg_ptr = ion_sg_table(qseecom.ion_clnt, ihandle); - if (sg_ptr == NULL) { + if (IS_ERR_OR_NULL(sg_ptr)) { pr_err("IOn client could not retrieve sg table\n"); goto err; } @@ -3080,13 +3125,21 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, } if (cleanup) { - msm_ion_do_cache_op(qseecom.ion_clnt, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto err; + } } else { - msm_ion_do_cache_op(qseecom.ion_clnt, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto err; + } if (data->type == QSEECOM_CLIENT_APP) { offset = req->ifd_data[i].cmd_buf_offset; data->sglistinfo_ptr[i].indexAndFlags = @@ -3227,7 +3280,7 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, } /* Populate the cmd data structure with the phys_addr */ sg_ptr = ion_sg_table(qseecom.ion_clnt, ihandle); - if (sg_ptr == NULL) { + if (IS_ERR_OR_NULL(sg_ptr)) { pr_err("IOn client could not retrieve sg table\n"); goto err; } @@ -3310,13 +3363,21 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, } cleanup: if (cleanup) { - msm_ion_do_cache_op(qseecom.ion_clnt, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto err; + } } else { - msm_ion_do_cache_op(qseecom.ion_clnt, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto err; + } if (data->type == QSEECOM_CLIENT_APP) { offset = req->ifd_data[i].cmd_buf_offset; data->sglistinfo_ptr[i].indexAndFlags = @@ -3805,9 +3866,13 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) goto exit_unregister_bus_bw_need; } - msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, img_data, fw_size, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto exit_disable_clk_vote; + } __qseecom_reentrancy_check_if_no_app_blocked(); /* SCM_CALL to load the image */ @@ -3922,9 +3987,13 @@ static int qseecom_load_commonlib_image(struct qseecom_dev_handle *data, goto exit_unregister_bus_bw_need; } - msm_ion_do_cache_op(qseecom.ion_clnt, qseecom.cmnlib_ion_handle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, qseecom.cmnlib_ion_handle, img_data, fw_size, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto exit_disable_clk_vote; + } /* SCM_CALL to load the image */ ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, @@ -4490,9 +4559,10 @@ static int __qseecom_enable_clk(enum qseecom_ce_hw_instance ce) } mutex_lock(&clk_access_lock); - if (qclk->clk_access_cnt == ULONG_MAX) + if (qclk->clk_access_cnt == ULONG_MAX) { + pr_err("clk_access_cnt beyond limitation\n"); goto err; - + } if (qclk->clk_access_cnt > 0) { qclk->clk_access_cnt++; mutex_unlock(&clk_access_lock); @@ -4805,9 +4875,13 @@ static int qseecom_load_external_elf(struct qseecom_dev_handle *data, ret = -EIO; goto exit_register_bus_bandwidth_needs; } - msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); __qseecom_reentrancy_check_if_no_app_blocked(); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto exit_disable_clock; + } /* SCM_CALL to load the external elf */ ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, &resp, sizeof(resp)); @@ -5051,7 +5125,9 @@ static int __qseecom_generate_and_save_key(struct qseecom_dev_handle *data, pr_err("Error:: unsupported usage %d\n", usage); return -EFAULT; } - __qseecom_enable_clk(CLK_QSEE); + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, ireq, sizeof(struct qseecom_key_generate_ireq), @@ -5109,7 +5185,9 @@ static int __qseecom_delete_saved_key(struct qseecom_dev_handle *data, pr_err("Error:: unsupported usage %d\n", usage); return -EFAULT; } - __qseecom_enable_clk(CLK_QSEE); + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, ireq, sizeof(struct qseecom_key_delete_ireq), @@ -5168,10 +5246,15 @@ static int __qseecom_set_clear_ce_key(struct qseecom_dev_handle *data, pr_err("Error:: unsupported usage %d\n", usage); return -EFAULT; } + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; - __qseecom_enable_clk(CLK_QSEE); - if (qseecom.qsee.instance != qseecom.ce_drv.instance) - __qseecom_enable_clk(CLK_CE_DRV); + if (qseecom.qsee.instance != qseecom.ce_drv.instance) { + ret = __qseecom_enable_clk(CLK_CE_DRV); + if (ret) + return ret; + } ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, ireq, sizeof(struct qseecom_key_select_ireq), @@ -5246,8 +5329,9 @@ static int __qseecom_update_current_key_user_info( pr_err("Error:: unsupported usage %d\n", usage); return -EFAULT; } - - __qseecom_enable_clk(CLK_QSEE); + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + return ret; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, ireq, sizeof(struct qseecom_key_userinfo_update_ireq), @@ -5725,7 +5809,9 @@ static int qseecom_mdtp_cipher_dip(void __user *argp) desc.args[3] = req.out_buf_size; desc.args[4] = req.direction; - __qseecom_enable_clk(CLK_QSEE); + ret = __qseecom_enable_clk(CLK_QSEE); + if (ret) + break; ret = scm_call2(TZ_MDTP_CIPHER_DIP_ID, &desc); @@ -5912,7 +5998,7 @@ static int __qseecom_update_qteec_req_buf(struct qseecom_qteec_modfd_req *req, } /* Populate the cmd data structure with the phys_addr */ sg_ptr = ion_sg_table(qseecom.ion_clnt, ihandle); - if (sg_ptr == NULL) { + if (IS_ERR_OR_NULL(sg_ptr)) { pr_err("IOn client could not retrieve sg table\n"); goto err; } @@ -5968,13 +6054,21 @@ static int __qseecom_update_qteec_req_buf(struct qseecom_qteec_modfd_req *req, } clean: if (cleanup) { - msm_ion_do_cache_op(qseecom.ion_clnt, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, sg->length, ION_IOC_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto err; + } } else { - msm_ion_do_cache_op(qseecom.ion_clnt, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, sg->length, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + goto err; + } data->sglistinfo_ptr[i].indexAndFlags = SGLISTINFO_SET_INDEX_FLAG( (sg_ptr->nents == 1), 0, @@ -6089,10 +6183,14 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, *(uint32_t *)cmd_buf = cmd_id; reqd_len_sb_in = req->req_len + req->resp_len; - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } __qseecom_reentrancy_check_if_this_app_blocked(ptr_app); @@ -6123,9 +6221,13 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, } } } - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, data->client.sb_length, ION_IOC_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { @@ -6271,10 +6373,14 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, else *(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND; - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, reqd_len_sb_in, ION_IOC_CLEAN_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } __qseecom_reentrancy_check_if_this_app_blocked(ptr_app); @@ -6309,9 +6415,13 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, if (ret) return ret; - msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, data->client.sb_virt, data->client.sb_length, ION_IOC_INV_CACHES); + if (ret) { + pr_err("cache operation failed %d\n", ret); + return ret; + } return 0; } From 7f12d5986afc99f95439526601afe8368957f3a4 Mon Sep 17 00:00:00 2001 From: ahmedsh Date: Wed, 4 Jan 2017 16:00:27 -0500 Subject: [PATCH 070/210] seemp: use local stack mem when encoding params Avoid race condition in driver when encoding param by reading contents from a local copy instead of msg buffer itself which can be mapped to user space. Change-Id: I9f111c078baefca6e6f1fcda30af1044891a3356 Signed-off-by: Ahmed Sheikh --- .../msm/seemp_core/seemp_event_encoder.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/platform/msm/seemp_core/seemp_event_encoder.c b/drivers/platform/msm/seemp_core/seemp_event_encoder.c index 7bf61d953455..36901f5fbee7 100644 --- a/drivers/platform/msm/seemp_core/seemp_event_encoder.c +++ b/drivers/platform/msm/seemp_core/seemp_event_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -48,9 +48,15 @@ static void check_param_range(char *section_eq, bool param, void encode_seemp_params(struct seemp_logk_blk *blk) { - char *s = blk->payload.msg + 1; + struct seemp_logk_blk tmp; + char *s = 0; + char *msg_section_start = 0; + char *msg_section_eq = 0; + char *msg_s = 0; - blk->payload.msg[BLK_MAX_MSG_SZ - 1] = 0; /* zero-terminate */ + memcpy(tmp.payload.msg, blk->payload.msg, BLK_MAX_MSG_SZ); + s = tmp.payload.msg + 1; + tmp.payload.msg[BLK_MAX_MSG_SZ - 1] = 0; /* zero-terminate */ while (true) { char *section_start = s; @@ -105,8 +111,13 @@ void encode_seemp_params(struct seemp_logk_blk *blk) } } - encode_seemp_section(section_start, section_eq, s, param, - numeric, id, numeric_value); + msg_section_start = blk->payload.msg + (section_start - + tmp.payload.msg); + msg_section_eq = blk->payload.msg + (section_eq - + tmp.payload.msg); + msg_s = blk->payload.msg + (s - tmp.payload.msg); + encode_seemp_section(msg_section_start, msg_section_eq, + msg_s, param, numeric, id, numeric_value); if (*s == 0) break; From 5e9c8dba56825505303f73cb59e679e583c4541e Mon Sep 17 00:00:00 2001 From: Xiaojun Sang Date: Wed, 16 Nov 2016 15:10:20 +0800 Subject: [PATCH 071/210] ASoC: qdsp6v2: prevent null pointer dereference for _vol_cmds In case of memory allocation failure, _vol_cmd_cnt is not reset. In _volume_cmds_free, null pointer dereference would happen for _vol_cmds[i]. To prevent it, reset _vol_cmd_cnt when memory allocation fails. CRs-Fixed: 1089598 Change-Id: Icb998549cdb999c6db2fd52aef505f200e630da5 Signed-off-by: Xiaojun Sang --- sound/soc/msm/qdsp6v2/msm-dts-eagle.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c index 465947f18e7c..3e76acf9ea09 100644 --- a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +++ b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c @@ -236,7 +236,8 @@ static s32 _volume_cmds_alloc1(s32 size) if (_vol_cmds) { _vol_cmds_d = kzalloc(_vol_cmd_cnt * sizeof(struct vol_cmds_d), GFP_KERNEL); - } + } else + _vol_cmd_cnt = 0; if (_vol_cmds_d) return 0; _volume_cmds_free(); From 4d8c8e1cb7a89637160a6f54c827d7f1f2cceecc Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Thu, 19 Jan 2017 14:59:44 -0800 Subject: [PATCH 072/210] crypto: msm: check integer overflow on total data len in qcedev.c qcedev_vbuf_ablk_cipher will calculate total data length. It starts with the value of "areq->cipher_op_req.byteoffset", which is controlled by the user. Make change to check if this total data length has integer overflow issue in qcedev_check_cipher_params. Change-Id: Ice42dca6d47eb8febfe8a34e566c69e4799fab57 Signed-off-by: Zhen Kong --- drivers/crypto/msm/qcedev.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index db1134fdbf35..fd8f7e25ea42 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1472,6 +1472,15 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, pr_err("%s: Invalid byte offset\n", __func__); goto error; } + total = req->byteoffset; + for (i = 0; i < req->entries; i++) { + if (total > U32_MAX - req->vbuf.src[i].len) { + pr_err("%s:Integer overflow on total src len\n", + __func__); + goto error; + } + total += req->vbuf.src[i].len; + } } if (req->data_len < req->byteoffset) { @@ -1507,7 +1516,7 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, } } /* Check for sum of all dst length is equal to data_len */ - for (i = 0; i < req->entries; i++) { + for (i = 0, total = 0; i < req->entries; i++) { if (req->vbuf.dst[i].len >= U32_MAX - total) { pr_err("%s: Integer overflow on total req dst vbuf length\n", __func__); From 4d013c0dee482b545fde4191cc8db8f1e44808f0 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 20 Jan 2017 16:38:16 +0800 Subject: [PATCH 073/210] spmi: Add flag to make SPMI debugfs write optional Currently, the SPMI debugfs entries support peek/poke functionality to access PMIC register directly. This is a possible way to access the PMIC and change some unexpected setting which is very dangerous. Add a flag CONFIG_MSM_SPMI_DEBUGFS_RO to make the write operation through debugfs optional, it can be defined if SPMI debugfs write is not desired. CRs-Fixed: 1103178 Change-Id: Iedbbf57a4a24a18f755a8b304591cc151b10bd4c Signed-off-by: Fenglin Wu --- drivers/spmi/Kconfig | 7 +++++++ drivers/spmi/spmi-dbgfs.c | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig index c32978e8cc64..15499c7d0d16 100644 --- a/drivers/spmi/Kconfig +++ b/drivers/spmi/Kconfig @@ -27,4 +27,11 @@ config MSM_QPNP_INT help Say 'y' here to include support for the Qualcomm QPNP interrupt support. QPNP is a SPMI based PMIC implementation. + +config MSM_SPMI_DEBUGFS_RO + depends on DEBUG_FS + depends on SPMI + bool "Disable SPMI debugfs write" + help + Say 'y' here to disable the SPMI debugfs register write operation. endif diff --git a/drivers/spmi/spmi-dbgfs.c b/drivers/spmi/spmi-dbgfs.c index b0a354b59a50..3ebcbc387ba6 100644 --- a/drivers/spmi/spmi-dbgfs.c +++ b/drivers/spmi/spmi-dbgfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2017, 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 @@ -46,6 +46,12 @@ static const char *DFS_ROOT_NAME = "spmi"; static const mode_t DFS_MODE = S_IRUSR | S_IWUSR; +#ifndef CONFIG_MSM_SPMI_DEBUGFS_RO +static const mode_t DFS_DATA_MODE = S_IRUSR | S_IWUSR; +#else +static const mode_t DFS_DATA_MODE = S_IRUSR; +#endif + /* Log buffer */ struct spmi_log_buffer { size_t rpos; /* Current 'read' position in buffer */ @@ -241,6 +247,7 @@ done: return ret; } +#ifndef CONFIG_MSM_SPMI_DEBUGFS_RO /** * spmi_write_data: writes data across the SPMI bus * @ctrl: The SPMI controller @@ -277,6 +284,7 @@ spmi_write_data(struct spmi_controller *ctrl, uint8_t *buf, int offset, int cnt) done: return ret; } +#endif /** * print_to_log: format a string and place into the log buffer @@ -456,6 +464,7 @@ static int get_log_data(struct spmi_trans *trans) return total_items_read; } +#ifndef CONFIG_MSM_SPMI_DEBUGFS_RO /** * spmi_dfs_reg_write: write user's byte array (coded as string) over SPMI. * @file: file pointer @@ -519,6 +528,9 @@ free_buf: kfree(kbuf); return ret; } +#else +#define spmi_dfs_reg_write NULL +#endif /** * spmi_dfs_reg_read: reads value(s) over SPMI and fill user's buffer a @@ -671,14 +683,14 @@ int spmi_dfs_add_controller(struct spmi_controller *ctrl) goto err_remove_fs; } - file = debugfs_create_file("data", DFS_MODE, dir, ctrl_data, + file = debugfs_create_file("data", DFS_DATA_MODE, dir, ctrl_data, &spmi_dfs_reg_fops); if (!file) { pr_err("error creating 'data' entry\n"); goto err_remove_fs; } - file = debugfs_create_file("data_raw", DFS_MODE, dir, ctrl_data, + file = debugfs_create_file("data_raw", DFS_DATA_MODE, dir, ctrl_data, &spmi_dfs_raw_data_fops); if (!file) { pr_err("error creating 'data' entry\n"); From abbe909b746dba69a3af6cc57c05b75e939d4a3a Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Fri, 20 Jan 2017 12:22:23 -0800 Subject: [PATCH 074/210] qseecom: release memory when failed to get fw size release app list entry when __qseecom_get_fw_size() returns error. Change-Id: I82406c39a2def87395811f442f39b57201766091 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 993d853d36d2..8953aa884eea 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -4109,6 +4109,7 @@ int qseecom_start_app(struct qseecom_handle **handle, strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE); if (__qseecom_get_fw_size(app_name, &fw_size, &app_arch)) { ret = -EIO; + kfree(entry); goto err; } entry->app_arch = app_arch; From 54ad9cc98bd9fa60f7e9844ff42baffe1ac92202 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Fri, 29 Apr 2016 18:52:01 +0530 Subject: [PATCH 075/210] msm: kgsl: Add support to read the efuse register Speed bin information is sometimes written to efuses to specify a GPU frequency plan available on a platform. The current code only supports reading the speed bin info for msm8909 and msm8916. Hence specify it in the platform device tree node to support multiple platforms. Change-Id: I101667a197220d94b4b1787df2973f3dafd3e30a Signed-off-by: Hareesh Gundu --- .../devicetree/bindings/gpu/adreno.txt | 6 ++ arch/arm/boot/dts/qcom/msm8909-gpu.dtsi | 4 +- arch/arm/boot/dts/qcom/msm8916-gpu.dtsi | 4 +- arch/arm/boot/dts/qcom/msm8976-gpu.dtsi | 91 ++++++++++++++++++- drivers/gpu/msm/adreno.c | 19 ++-- 5 files changed, 107 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt index b70486ba5789..4634493a6927 100644 --- a/Documentation/devicetree/bindings/gpu/adreno.txt +++ b/Documentation/devicetree/bindings/gpu/adreno.txt @@ -113,6 +113,12 @@ Optional Properties: - qcom,gpu-speed-config: This property enables support for dynamic GPU powerlevel configuration based on the efuse register. + + offset - offset of the efuse register from the base. + shift - number of bits to right shift to get the speed value. + mask - mask for the relevant bits in the efuse register. + speed - speed for loading specific GPU powerlevel. + - qcom,popp-enable: Boolean. Enables the POPP feature in the gpu kernel driver. diff --git a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi index c891bea138cf..ba881d076157 100644 --- a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -46,7 +46,7 @@ interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; - qcom,gpu-speed-config = <0>; + qcom,gpu-speed-config = <0xc 0x2 0x7 0x0>; qcom,chipid = <0x03000400>; diff --git a/arch/arm/boot/dts/qcom/msm8916-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8916-gpu.dtsi index a7e10313b6d8..9a5dd19259ee 100644 --- a/arch/arm/boot/dts/qcom/msm8916-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8916-gpu.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -23,7 +23,7 @@ interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; - qcom,gpu-speed-config = <2>; + qcom,gpu-speed-config = <0xc 0x2 0x7 0x2>; qcom,chipid = <0x03000600>; diff --git a/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi index 5da429685b12..6a6fac3d7b95 100644 --- a/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi @@ -39,12 +39,16 @@ label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; reg = <0x1C00000 0x40000 - 0x1C40000 0x10000>; - reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory"; + 0x1C40000 0x10000 + 0xA4000 0x800>; + reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory", + "qfprom_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; + qcom,gpu-speed-config = <0x160 0x14 0x1 0x1>; + qcom,chipid = <0x05010000>; qcom,initial-pwrlevel = <5>; @@ -187,5 +191,88 @@ qcom,bus-max = <0>; }; }; + + qcom,gpu-speed-config@1 { + compatible = "gpu-speed-config@1"; + + /* Power levels */ + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + + /* SUPER TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <621330000>; + qcom,bus-freq = <10>; + qcom,bus-min = <10>; + qcom,bus-max = <10>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <600000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <10>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <550000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <10>; + }; + + /* NOM+ */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <480000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <7>; + qcom,bus-max = <9>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <432000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <5>; + qcom,bus-max = <9>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <300000000>; + qcom,bus-freq = <5>; + qcom,bus-min = <4>; + qcom,bus-max = <7>; + }; + + /* Low SVS+ */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <266666667>; + qcom,bus-freq = <4>; + qcom,bus-min = <4>; + qcom,bus-max = <5>; + }; + + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + }; }; }; diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index a96a04f368d4..1ad8737175d5 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-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 @@ -48,9 +48,6 @@ #define KGSL_LOG_LEVEL_DEFAULT 3 -/* QFPROM_CORR_PTE2 register offset*/ -#define QFPROM_CORR_PTE2_OFFSET 0xC - #define SECVID_PROGRAM_PATH_UNKNOWN 0x0 #define SECVID_PROGRAM_PATH_GPU 0x1 #define SECVID_PROGRAM_PATH_CPU 0x2 @@ -1029,12 +1026,12 @@ static struct device_node *get_gpu_speed_config_data(struct platform_device struct resource *res; void __iomem *base; u32 pte_reg_val; - int speed_bin, speed_config; + int speed_bin, speed_config[4]; char prop_name[32]; /* Load default configuration, if speed config is not required */ - if (of_property_read_u32(pdev->dev.of_node, - "qcom,gpu-speed-config", &speed_config)) + if (of_property_read_u32_array(pdev->dev.of_node, + "qcom,gpu-speed-config", speed_config, 4)) return pdev->dev.of_node; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -1047,14 +1044,14 @@ static struct device_node *get_gpu_speed_config_data(struct platform_device if (!base) return NULL; - pte_reg_val = __raw_readl(base + QFPROM_CORR_PTE2_OFFSET); + pte_reg_val = __raw_readl(base + speed_config[0]); + speed_bin = (pte_reg_val >> speed_config[1]) & speed_config[2]; iounmap(base); - speed_bin = (pte_reg_val >> 0x2) & 0x7; - if (speed_bin == speed_config) { + if (speed_bin == speed_config[3]) { snprintf(prop_name, ARRAY_SIZE(prop_name), "%s%d", - "gpu-speed-config@", speed_config); + "gpu-speed-config@", speed_bin); return adreno_of_find_subnode(pdev->dev.of_node, prop_name); } From 8a0033cd8ea167200108757aad5f4b8fb2ad660e Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 26 Oct 2016 15:01:54 +0100 Subject: [PATCH 076/210] KEYS: Fix short sprintf buffer in /proc/keys show function This fixes CVE-2016-7042. Fix a short sprintf buffer in proc_keys_show(). If the gcc stack protector is turned on, this can cause a panic due to stack corruption. The problem is that xbuf[] is not big enough to hold a 64-bit timeout rendered as weeks: (gdb) p 0xffffffffffffffffULL/(60*60*24*7) $2 = 30500568904943 That's 14 chars plus NUL, not 11 chars plus NUL. Expand the buffer to 16 chars. I think the unpatched code apparently works if the stack-protector is not enabled because on a 32-bit machine the buffer won't be overflowed and on a 64-bit machine there's a 64-bit aligned pointer at one side and an int that isn't checked again on the other side. The panic incurred looks something like: Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81352ebe CPU: 0 PID: 1692 Comm: reproducer Not tainted 4.7.2-201.fc24.x86_64 #1 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 0000000000000086 00000000fbbd2679 ffff8800a044bc00 ffffffff813d941f ffffffff81a28d58 ffff8800a044bc98 ffff8800a044bc88 ffffffff811b2cb6 ffff880000000010 ffff8800a044bc98 ffff8800a044bc30 00000000fbbd2679 Call Trace: [] dump_stack+0x63/0x84 [] panic+0xde/0x22a [] ? proc_keys_show+0x3ce/0x3d0 [] __stack_chk_fail+0x19/0x30 [] proc_keys_show+0x3ce/0x3d0 [] ? key_validate+0x50/0x50 [] ? key_default_cmp+0x20/0x20 [] seq_read+0x2cc/0x390 [] proc_reg_read+0x42/0x70 [] __vfs_read+0x37/0x150 [] ? security_file_permission+0xa0/0xc0 [] vfs_read+0x96/0x130 [] SyS_read+0x55/0xc0 [] entry_SYSCALL_64_fastpath+0x1a/0xa4 Change-Id: I38877fcf9eb3c1204588cdab1e47141c30f373b4 Reported-by: Ondrej Kozina Signed-off-by: David Howells Tested-by: Ondrej Kozina cc: stable@vger.kernel.org Signed-off-by: James Morris Git-repo: http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git Git-commit:03dab869b7b239c4e013ec82aea22e181e441cfc Signed-off-by: Srinivasa Rao Kuppala --- security/keys/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/proc.c b/security/keys/proc.c index 217b6855e815..374c3301b802 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -188,7 +188,7 @@ static int proc_keys_show(struct seq_file *m, void *v) struct timespec now; unsigned long timo; key_ref_t key_ref, skey_ref; - char xbuf[12]; + char xbuf[16]; int rc; key_ref = make_key_ref(key, 0); From b9f8ec96165304ae5d1994c5df4ab30c2b9b6c71 Mon Sep 17 00:00:00 2001 From: Brahmaji K Date: Mon, 24 Oct 2016 20:28:18 +0530 Subject: [PATCH 077/210] crypto : ice: Fix NULL pointer exception in ice. While enabling ICE setup and on error conditions, the regulator is disabled. Before disabling the regulator, check if the regulator is up and able to access the registers of regulator. Change-Id: I94dd2b3e25444818f7bdf2f791f4fa9efaefce15 Signed-off-by: Brahmaji K --- drivers/crypto/msm/ice.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index 7255973d493d..8789b2dbd28b 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -1595,7 +1595,18 @@ static int enable_ice_setup(struct ice_device *ice_dev) out_clocks: qcom_ice_enable_clocks(ice_dev, false); out_reg: - regulator_disable(ice_dev->reg); + if (ice_dev->is_regulator_available) { + if (qcom_ice_get_vreg(ice_dev)) { + pr_err("%s: Could not get regulator\n", __func__); + goto out; + } + ret = regulator_disable(ice_dev->reg); + if (ret) { + pr_err("%s:%p: Could not disable regulator\n", + __func__, ice_dev); + goto out; + } + } out: return ret; } From 5ffb66e3e5043c240d136447cf7f0f4ffc19ca57 Mon Sep 17 00:00:00 2001 From: Deepak Kushwah Date: Wed, 26 Oct 2016 13:13:45 +0530 Subject: [PATCH 078/210] msm: vidc: Allow clients to suggest I-frame sizes Clients that want to influence the size I-frames emitted by the encoder can set V4L2_CID_MPEG_VIDC_VIDEO_VENC_IFRAMESIZE_TYPE. Change-Id: I4e6853022b558069304cde4cff7bc1445fd66213 Signed-off-by: Deepak Kushwah Signed-off-by: Sanjay Singh --- .../platform/msm/vidc/hfi_packetization.c | 27 ++++++++++++ drivers/media/platform/msm/vidc/msm_venc.c | 44 ++++++++++++++++++- .../media/platform/msm/vidc/vidc_hfi_api.h | 8 ++++ .../media/platform/msm/vidc/vidc_hfi_helper.h | 11 +++++ include/uapi/linux/v4l2-controls.h | 9 ++++ 5 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c index 990bb7453954..0ab2559e8b97 100644 --- a/drivers/media/platform/msm/vidc/hfi_packetization.c +++ b/drivers/media/platform/msm/vidc/hfi_packetization.c @@ -2066,6 +2066,33 @@ int create_pkt_cmd_session_set_property( pkt->size += sizeof(u32) + sizeof(struct hfi_enable); break; } + case HAL_PARAM_VENC_IFRAMESIZE_TYPE: + { + enum hal_iframesize_type hal = + *(enum hal_iframesize_type *)pdata; + struct hfi_iframe_size *hfi = (struct hfi_iframe_size *) + &pkt->rg_property_data[1]; + + switch (hal) { + case HAL_IFRAMESIZE_TYPE_DEFAULT: + hfi->type = HFI_IFRAME_SIZE_DEFAULT; + break; + case HAL_IFRAMESIZE_TYPE_MEDIUM: + hfi->type = HFI_IFRAME_SIZE_MEDIUM; + break; + case HAL_IFRAMESIZE_TYPE_HUGE: + hfi->type = HFI_IFRAME_SIZE_HIGH; + break; + case HAL_IFRAMESIZE_TYPE_UNLIMITED: + hfi->type = HFI_IFRAME_SIZE_UNLIMITED; + break; + default: + return -ENOTSUPP; + } + pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_VENC_IFRAMESIZE; + pkt->size += sizeof(u32) + sizeof(struct hfi_iframe_size); + break; + } /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */ case HAL_CONFIG_BUFFER_REQUIREMENTS: case HAL_CONFIG_PRIORITY: diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 9861e82bd7be..e6a6d0fddc66 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -179,6 +179,13 @@ static const char *const timestamp_mode[] = { "Ignore", }; +static const char *const iframe_sizes[] = { + "Default", + "Medium", + "Huge", + "Unlimited" +}; + static struct msm_vidc_ctrl msm_venc_ctrls[] = { { .id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD, @@ -1169,9 +1176,23 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .default_value = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_DISABLE, .step = 1, }, - + { + .id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE, + .name = "Bounds of I-frame size", + .type = V4L2_CTRL_TYPE_MENU, + .minimum = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + .maximum = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED, + .default_value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + .menu_skip_mask = ~( + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED)), + .qmenu = iframe_sizes, + }, }; + #define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls) static u32 get_frame_size_nv12(int plane, u32 height, u32 width) @@ -1936,6 +1957,19 @@ static inline int venc_v4l2_to_hal(int id, int value) default: goto unknown_value; } + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE: + switch (value) { + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT: + return HAL_IFRAMESIZE_TYPE_DEFAULT; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM: + return HAL_IFRAMESIZE_TYPE_MEDIUM; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE: + return HAL_IFRAMESIZE_TYPE_HUGE; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED: + return HAL_IFRAMESIZE_TYPE_UNLIMITED; + default: + goto unknown_value; + } } unknown_value: @@ -1975,6 +2009,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) struct hal_venc_perf_mode venc_mode; int max_hierp_layers; struct hal_video_signal_info signal_info = {0}; + enum hal_iframesize_type iframesize_type = HAL_IFRAMESIZE_TYPE_DEFAULT; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s invalid parameters\n", __func__); @@ -2986,6 +3021,13 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) dprintk(VIDC_ERR, "fail to set csc: %d\n", rc); } break; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE: + property_id = HAL_PARAM_VENC_IFRAMESIZE_TYPE; + iframesize_type = venc_v4l2_to_hal( + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE, + ctrl->val); + pdata = &iframesize_type; + break; default: dprintk(VIDC_ERR, "Unsupported index: %x\n", ctrl->id); rc = -ENOTSUPP; diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index 5d1e3c8af4cf..47de8b270147 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -226,6 +226,7 @@ enum hal_property { HAL_PARAM_VENC_BITRATE_TYPE, HAL_PARAM_VENC_VIDEO_SIGNAL_INFO, HAL_PARAM_VENC_CONSTRAINED_INTRA_PRED, + HAL_PARAM_VENC_IFRAMESIZE_TYPE, }; enum hal_domain { @@ -972,6 +973,13 @@ struct hal_video_signal_info { bool full_range; }; +enum hal_iframesize_type { + HAL_IFRAMESIZE_TYPE_DEFAULT, + HAL_IFRAMESIZE_TYPE_MEDIUM, + HAL_IFRAMESIZE_TYPE_HUGE, + HAL_IFRAMESIZE_TYPE_UNLIMITED, +}; + enum vidc_resource_id { VIDC_RESOURCE_OCMEM = 0x00000001, VIDC_UNUSED_RESORUCE = 0x10000000, diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h index 6a7f3dc76309..687e3b056322 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h @@ -369,6 +369,8 @@ struct hfi_buffer_info { (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x02F) #define HFI_PROPERTY_PARAM_VENC_BITRATE_TYPE \ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x031) +#define HFI_PROPERTY_PARAM_VENC_IFRAMESIZE \ + (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x034) #define HFI_PROPERTY_CONFIG_VENC_COMMON_START \ (HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x6000) @@ -817,6 +819,15 @@ struct hfi_aspect_ratio { u32 aspect_width; u32 aspect_height; }; + +#define HFI_IFRAME_SIZE_DEFAULT (HFI_COMMON_BASE + 0x1) +#define HFI_IFRAME_SIZE_MEDIUM (HFI_COMMON_BASE + 0x2) +#define HFI_IFRAME_SIZE_HIGH (HFI_COMMON_BASE + 0x3) +#define HFI_IFRAME_SIZE_UNLIMITED (HFI_COMMON_BASE + 0x4) +struct hfi_iframe_size { + u32 type; +}; + #define HFI_MVC_BUFFER_LAYOUT_TOP_BOTTOM (0) #define HFI_MVC_BUFFER_LAYOUT_SIDEBYSIDE (1) #define HFI_MVC_BUFFER_LAYOUT_SEQ (2) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 6c5d37de9b2a..5d3cf02f88f4 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1071,6 +1071,15 @@ enum v4l2_cid_mpeg_vidc_video_vpe_csc_type_enable { V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_ENABLE = 1 }; +#define V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE \ + (V4L2_CID_MPEG_MSM_VIDC_BASE + 100) +enum v4l2_mpeg_vidc_video_venc_iframesize_type { + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED, +}; + /* Camera class control IDs */ #define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) From fce62f12495fc5b1185818309958095d4c0c5ac4 Mon Sep 17 00:00:00 2001 From: Archana Sriram Date: Wed, 4 Jan 2017 14:54:24 +0530 Subject: [PATCH 079/210] msm: kgsl: Increase GPU fault detection threshold value The current value is leading to spurious fault interrupts from the GPU. Increase the threshold so that hardware fault detection won't be triggered as quickly. CRs-Fixed: 1105559 Change-Id: I88cf7efc553f6bcb1026b7e86d4600490b36e332 Signed-off-by: Archana Sriram Signed-off-by: Srinivasarao P --- drivers/gpu/msm/adreno_a4xx.c | 4 ++-- drivers/gpu/msm/adreno_a5xx.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c index f35a1781c0df..01bf2415254c 100644 --- a/drivers/gpu/msm/adreno_a4xx.c +++ b/drivers/gpu/msm/adreno_a4xx.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017, 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 @@ -662,7 +662,7 @@ static void a4xx_start(struct adreno_device *adreno_dev) set_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv); gpudev->irq->mask |= (1 << A4XX_INT_MISC_HANG_DETECT); kgsl_regwrite(device, A4XX_RBBM_INTERFACE_HANG_INT_CTL, - (1 << 30) | 0xFFFF); + (1 << 30) | 0x1FFFF); /* Set the GMEM/OCMEM base address for A4XX */ kgsl_regwrite(device, A4XX_RB_GMEM_BASE_ADDR, diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index fe27e94bef93..0b25f5fb2fb7 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1357,11 +1357,11 @@ static void a5xx_start(struct adreno_device *adreno_dev) set_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv); gpudev->irq->mask |= (1 << A5XX_INT_MISC_HANG_DETECT); /* - * Set hang detection threshold to 1 million cycles - * (0xFFFF*16) + * Set hang detection threshold to 4 million cycles + * (0x3FFFF*16) */ kgsl_regwrite(device, A5XX_RBBM_INTERFACE_HANG_INT_CNTL, - (1 << 30) | 0xFFFF); + (1 << 30) | 0x3FFFF); } From f0724cac09ee3b0732093df9dab1e230cfd73e4b Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Fri, 6 Jan 2017 15:37:09 +0530 Subject: [PATCH 080/210] msm: kgsl: Fix incomplete IB2 dump in the snapshot If there is IB2 address overlap with IB object list, driver is dumping pending dwords size of active IB2 data into snapshot. Fix this by updating IB2 size while active IB1 parsing instead later point. Change-Id: Ibb12a876ebf73846424232ef28e00d3dc9f9be59 Signed-off-by: Hareesh Gundu Signed-off-by: Archana Sriram Signed-off-by: Srinivasarao P --- drivers/gpu/msm/adreno_cp_parser.c | 35 ++++++---- drivers/gpu/msm/adreno_cp_parser.h | 4 +- drivers/gpu/msm/adreno_snapshot.c | 100 +++++++++++++---------------- drivers/gpu/msm/kgsl_snapshot.h | 4 +- 4 files changed, 69 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/msm/adreno_cp_parser.c b/drivers/gpu/msm/adreno_cp_parser.c index db2f3d207059..297bbbb47fef 100644 --- a/drivers/gpu/msm/adreno_cp_parser.c +++ b/drivers/gpu/msm/adreno_cp_parser.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017, 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 @@ -53,7 +53,7 @@ static int load_state_unit_sizes[7][2] = { static int adreno_ib_find_objs(struct kgsl_device *device, struct kgsl_process_private *process, uint64_t gpuaddr, uint64_t dwords, - int obj_type, + uint64_t ib2base, int obj_type, struct adreno_ib_object_list *ib_obj_list, int ib_level); @@ -479,7 +479,7 @@ static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt, ret = adreno_ib_find_objs(device, process, ib_parse_vars->set_draw_groups[i].cmd_stream_addr, ib_parse_vars->set_draw_groups[i].cmd_stream_dwords, - SNAPSHOT_GPU_OBJECT_DRAW, + 0, SNAPSHOT_GPU_OBJECT_DRAW, ib_obj_list, 2); if (ret) break; @@ -682,8 +682,8 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device, if (cmd_stream_dwords) ret = adreno_ib_find_objs(device, process, cmd_stream_addr, cmd_stream_dwords, - SNAPSHOT_GPU_OBJECT_DRAW, ib_obj_list, - 2); + 0, SNAPSHOT_GPU_OBJECT_DRAW, + ib_obj_list, 2); if (ret) break; continue; @@ -694,7 +694,7 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device, gpuaddr = gpuaddr << 32 | ptr[i + 1]; ret = adreno_ib_find_objs(device, process, gpuaddr, (ptr[i] & 0x0000FFFF), - SNAPSHOT_GPU_OBJECT_IB, + 0, SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 2); if (ret) break; @@ -756,7 +756,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device, if (flags & 0x8) { ret = adreno_ib_find_objs(device, process, ptr[i + 1], (ptr[i] & 0x0000FFFF), - SNAPSHOT_GPU_OBJECT_IB, + 0, SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 2); if (ret) break; @@ -771,6 +771,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device, * @process: Process in which the IB is allocated * @gpuaddr: IB2 gpuaddr * @dwords: IB2 size in dwords + * @ib2base: Base address of active IB2 * @ib_obj_list: List of objects found in IB * @ib_level: The level from which function is called, either from IB1 or IB2 * @@ -779,7 +780,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device, */ static int adreno_cp_parse_ib2(struct kgsl_device *device, struct kgsl_process_private *process, - uint64_t gpuaddr, uint64_t dwords, + uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base, struct adreno_ib_object_list *ib_obj_list, int ib_level) { @@ -791,6 +792,10 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device, */ if (2 == ib_level) return -EINVAL; + + /* Save current IB2 statically */ + if (ib2base == gpuaddr) + kgsl_snapshot_push_object(process, gpuaddr, dwords); /* * only try to find sub objects iff this IB has * not been processed already @@ -805,7 +810,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device, return 0; } - return adreno_ib_find_objs(device, process, gpuaddr, dwords, + return adreno_ib_find_objs(device, process, gpuaddr, dwords, ib2base, SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 2); } @@ -814,6 +819,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device, * @device: The device pointer on which the IB executes * @process: The process in which the IB and all contained objects are mapped. * @gpuaddr: The gpu address of the IB + * @ib2base: IB2 base address * @dwords: Size of ib in dwords * @obj_type: The object type can be either an IB or a draw state sequence * @ib_obj_list: The list in which the IB and the objects in it are added. @@ -826,7 +832,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device, static int adreno_ib_find_objs(struct kgsl_device *device, struct kgsl_process_private *process, uint64_t gpuaddr, uint64_t dwords, - int obj_type, + uint64_t ib2base, int obj_type, struct adreno_ib_object_list *ib_obj_list, int ib_level) { @@ -899,7 +905,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device, uint64_t size = src[i + 2]; ret = adreno_cp_parse_ib2(device, process, - gpuaddrib2, size, + gpuaddrib2, size, ib2base, ib_obj_list, ib_level); if (ret) goto done; @@ -925,7 +931,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device, gpuaddrib2 = gpuaddrib2 << 32 | src[i + 1]; ret = adreno_cp_parse_ib2(device, process, - gpuaddrib2, size, + gpuaddrib2, size, ib2base, ib_obj_list, ib_level); if (ret) goto done; @@ -977,6 +983,7 @@ done: * @process: The process in which the IB and all contained objects are mapped * @gpuaddr: The gpu address of the IB * @dwords: Size of ib in dwords + * @ib2base: Base address of active IB2 * @ib_obj_list: The list in which the IB and the objects in it are added. * * Find all the memory objects that an IB needs for execution and place @@ -988,7 +995,7 @@ done: */ int adreno_ib_create_object_list(struct kgsl_device *device, struct kgsl_process_private *process, - uint64_t gpuaddr, uint64_t dwords, + uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base, struct adreno_ib_object_list **out_ib_obj_list) { int ret = 0; @@ -1011,7 +1018,7 @@ int adreno_ib_create_object_list(struct kgsl_device *device, return -ENOMEM; } - ret = adreno_ib_find_objs(device, process, gpuaddr, dwords, + ret = adreno_ib_find_objs(device, process, gpuaddr, dwords, ib2base, SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 1); /* Even if there was an error return the remaining objects found */ diff --git a/drivers/gpu/msm/adreno_cp_parser.h b/drivers/gpu/msm/adreno_cp_parser.h index 5b7c77fcbae9..80bb7dc4e916 100644 --- a/drivers/gpu/msm/adreno_cp_parser.h +++ b/drivers/gpu/msm/adreno_cp_parser.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017, 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 @@ -178,7 +178,7 @@ static inline int adreno_cp_parser_regindex(struct adreno_device *adreno_dev, int adreno_ib_create_object_list( struct kgsl_device *device, struct kgsl_process_private *process, - uint64_t gpuaddr, uint64_t dwords, + uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base, struct adreno_ib_object_list **out_ib_obj_list); void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list); diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index f18e635e1f61..179943ff3b4e 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015,2017, 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 @@ -29,8 +29,6 @@ #define SNAPSHOT_OBJ_BUFSIZE 64 -#define SNAPSHOT_OBJ_TYPE_IB 0 - /* Used to print error message if an IB has too many objects in it */ static int ib_max_objs; @@ -50,8 +48,7 @@ static inline int adreno_rb_ctxtswitch(struct adreno_device *adreno_dev, } /* Push a new buffer object onto the list */ -static void push_object(int type, - struct kgsl_process_private *process, +void kgsl_snapshot_push_object(struct kgsl_process_private *process, uint64_t gpuaddr, uint64_t dwords) { int index; @@ -91,7 +88,6 @@ static void push_object(int type, } /* Put it on the list of things to parse */ - objbuf[objbufptr].type = type; objbuf[objbufptr].gpuaddr = gpuaddr; objbuf[objbufptr].size = dwords << 2; objbuf[objbufptr++].entry = entry; @@ -102,8 +98,7 @@ static void push_object(int type, * to be dumped */ -static int find_object(int type, uint64_t gpuaddr, - struct kgsl_process_private *process) +static int find_object(uint64_t gpuaddr, struct kgsl_process_private *process) { int index; @@ -122,14 +117,12 @@ static int find_object(int type, uint64_t gpuaddr, * @snapshot: The snapshot data. * @process: The process to which the IB belongs * @ib_obj_list: List of the IB objects - * @ib2base: IB2 base address at time of the fault * * Returns 0 on success else error code */ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot, struct kgsl_process_private *process, - struct adreno_ib_object_list *ib_obj_list, - uint64_t ib2base) + struct adreno_ib_object_list *ib_obj_list) { int ret = 0; struct adreno_ib_object *ib_objs; @@ -154,21 +147,15 @@ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot, } if (freeze) { - /* Save current IB2 statically */ - if (ib2base == ib_objs->gpuaddr) { - push_object(SNAPSHOT_OBJ_TYPE_IB, - process, ib_objs->gpuaddr, ib_objs->size >> 2); + temp_ret = kgsl_snapshot_get_object(snapshot, + process, ib_objs->gpuaddr, + ib_objs->size, + ib_objs->snapshot_obj_type); + if (temp_ret < 0) { + if (ret >= 0) + ret = temp_ret; } else { - temp_ret = kgsl_snapshot_get_object(snapshot, - process, ib_objs->gpuaddr, - ib_objs->size, - ib_objs->snapshot_obj_type); - if (temp_ret < 0) { - if (ret >= 0) - ret = temp_ret; - } else { - snapshot_frozen_objsize += temp_ret; - } + snapshot_frozen_objsize += temp_ret; } } } @@ -187,7 +174,7 @@ static inline void parse_ib(struct kgsl_device *device, uint64_t gpuaddr, uint64_t dwords) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - uint64_t ib1base; + uint64_t ib1base, ib2base; struct adreno_ib_object_list *ib_obj_list; /* @@ -198,10 +185,11 @@ static inline void parse_ib(struct kgsl_device *device, adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE, ADRENO_REG_CP_IB1_BASE_HI, &ib1base); + adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB2_BASE, + ADRENO_REG_CP_IB2_BASE_HI, &ib2base); if (gpuaddr == ib1base) { - push_object(SNAPSHOT_OBJ_TYPE_IB, process, - gpuaddr, dwords); + kgsl_snapshot_push_object(process, gpuaddr, dwords); return; } @@ -210,7 +198,7 @@ static inline void parse_ib(struct kgsl_device *device, return; if (-E2BIG == adreno_ib_create_object_list(device, process, - gpuaddr, dwords, &ib_obj_list)) + gpuaddr, dwords, ib2base, &ib_obj_list)) ib_max_objs = 1; if (ib_obj_list) @@ -448,6 +436,7 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf, struct adreno_ib_object_list *ib_obj_list; struct kgsl_snapshot *snapshot; struct kgsl_snapshot_object *obj; + struct kgsl_memdesc *memdesc; if (meta == NULL || meta->snapshot == NULL || meta->obj == NULL) { KGSL_CORE_ERR("snapshot: bad metadata"); @@ -455,6 +444,11 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf, } snapshot = meta->snapshot; obj = meta->obj; + memdesc = &obj->entry->memdesc; + + /* If size is zero get it from the medesc size */ + if (!obj->size) + obj->size = (memdesc->size - (obj->gpuaddr - memdesc->gpuaddr)); if (obj->size > SIZE_MAX) { KGSL_CORE_ERR("snapshot: GPU memory object 0x%016llX is too large to snapshot\n", @@ -467,7 +461,7 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf, return 0; } - src = kgsl_gpuaddr_to_vaddr(&obj->entry->memdesc, obj->gpuaddr); + src = kgsl_gpuaddr_to_vaddr(memdesc, obj->gpuaddr); if (src == NULL) { KGSL_DRV_ERR(device, "snapshot: Unable to map GPU memory object 0x%016llX into the kernel\n", @@ -485,13 +479,14 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf, if (-E2BIG == adreno_ib_create_object_list(device, obj->entry->priv, obj->gpuaddr, obj->size >> 2, + meta->ib2base, &ib_obj_list)) ib_max_objs = 1; if (ib_obj_list) { /* freeze the IB objects in the IB */ snapshot_freeze_obj_list(snapshot, obj->entry->priv, - ib_obj_list, meta->ib2base); + ib_obj_list); adreno_ib_destroy_obj_list(ib_obj_list); } } @@ -521,26 +516,18 @@ static void dump_object(struct kgsl_device *device, int obj, { struct snapshot_ib_meta meta; - switch (objbuf[obj].type) { - case SNAPSHOT_OBJ_TYPE_IB: - meta.snapshot = snapshot; - meta.obj = &objbuf[obj]; - meta.ib1base = ib1base; - meta.ib1size = ib1size; - meta.ib2base = ib2base; - meta.ib2size = ib2size; + meta.snapshot = snapshot; + meta.obj = &objbuf[obj]; + meta.ib1base = ib1base; + meta.ib1size = ib1size; + meta.ib2base = ib2base; + meta.ib2size = ib2size; - kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB, + kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB, snapshot, snapshot_ib, &meta); - if (objbuf[obj].entry) { - kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc)); - kgsl_mem_entry_put(objbuf[obj].entry); - } - break; - default: - KGSL_CORE_ERR("snapshot: Invalid snapshot object type: %d\n", - objbuf[obj].type); - break; + if (objbuf[obj].entry) { + kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc)); + kgsl_mem_entry_put(objbuf[obj].entry); } } @@ -701,10 +688,10 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot, * figure how often this really happens. */ - if (!find_object(SNAPSHOT_OBJ_TYPE_IB, (uint64_t) ib1base, - snapshot->process) && ib1size) { - push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process, - (uint64_t) ib1base, ib1size); + if (!find_object((uint64_t) ib1base, snapshot->process)) { + kgsl_snapshot_push_object(snapshot->process, (uint64_t) ib1base, + ib1size); + KGSL_CORE_ERR( "CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n", ib1size); @@ -718,10 +705,9 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot, * correct size. */ - if (!find_object(SNAPSHOT_OBJ_TYPE_IB, (uint64_t) ib2base, - snapshot->process) && ib2size) { - push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process, - (uint64_t) ib2base, ib2size); + if (!find_object((uint64_t) ib2base, snapshot->process)) { + kgsl_snapshot_push_object(snapshot->process, (uint64_t) ib2base, + ib2size); } /* diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h index 407cfd51a193..c8528a482573 100644 --- a/drivers/gpu/msm/kgsl_snapshot.h +++ b/drivers/gpu/msm/kgsl_snapshot.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015,2017, 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 @@ -190,4 +190,6 @@ struct kgsl_snapshot_gpu_object { int size; /* Size of the object (in dwords) */ }; +void kgsl_snapshot_push_object(struct kgsl_process_private *process, + uint64_t gpuaddr, uint64_t dwords); #endif From 93615bab935e582aa056eb627b6ac1989a7d2b7c Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Tue, 4 Oct 2016 18:31:13 +0530 Subject: [PATCH 081/210] msm: kgsl: Add multiple GPU speed fuse read support This change supports the driver to read the fuse and speed bins from the two different address regions to configure the dynamic GPU powerlevels. CRs-Fixed: 1073582 Change-Id: I8e852f974e4fdedc498030c6ccc5fcf432816c1e Signed-off-by: Hareesh Gundu --- .../devicetree/bindings/gpu/adreno.txt | 19 ++- arch/arm/boot/dts/qcom/msm8976-gpu.dtsi | 140 ++++++++++-------- drivers/gpu/msm/adreno.c | 80 ++++++++++ 3 files changed, 176 insertions(+), 63 deletions(-) diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt index 4634493a6927..1db29b8070d6 100644 --- a/Documentation/devicetree/bindings/gpu/adreno.txt +++ b/Documentation/devicetree/bindings/gpu/adreno.txt @@ -113,12 +113,29 @@ Optional Properties: - qcom,gpu-speed-config: This property enables support for dynamic GPU powerlevel configuration based on the efuse register. - + offset - offset of the efuse register from the base. shift - number of bits to right shift to get the speed value. mask - mask for the relevant bits in the efuse register. speed - speed for loading specific GPU powerlevel. +- qcom,gpu-fuse-numconfigs: Number of PTE fuse configuration. +- qcom,gpu-fuse-config: This property enables support for dynamic GPU powerlevel + configuration based on the PTE fuse bin (OR) PTE speed bin registers. + First entry speed/fuse bit will fit into the MSB of speed plan value + later bit values will added towards LSB. + A series of 3 cell properties, format of which is: + + offset - offset of the fuse/speedbin register from the base. + shift - number of bits to right shift to get the bin/fuse value. + mask - mask for the relevant bits in the fuse register. + +- qcom,gpu-speed-numplans: Number of Powerlevels configuration. +- qcom,gpu-speed-plan: This property enables to defines the various GPU powerlevel plans. + A series of 2 cell properties, format of which is: + + value - Value of speed bin to choose the proper PowerLevel Plan. + plan - Number for a spedd config Powerlevels. - qcom,popp-enable: Boolean. Enables the POPP feature in the gpu kernel driver. diff --git a/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi index 6a6fac3d7b95..c420a1ce0ea3 100644 --- a/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976-gpu.dtsi @@ -40,15 +40,13 @@ compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; reg = <0x1C00000 0x40000 0x1C40000 0x10000 - 0xA4000 0x800>; + 0xA0000 0x4800>; reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory", "qfprom_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; - qcom,gpu-speed-config = <0x160 0x14 0x1 0x1>; - qcom,chipid = <0x05010000>; qcom,initial-pwrlevel = <5>; @@ -122,73 +120,91 @@ coresight-child-list = <&funnel_in0>; coresight-child-ports = <4>; - /* Power levels */ - qcom,gpu-pwrlevels { - #address-cells = <1>; - #size-cells = <0>; + /* Power level configuration */ + qcom,gpu-fuse-numconfigs = <2>; + qcom,gpu-fuse-config = + <0x4160 0x14 0x1>, + <0x0120 0x1F 0x1>; - compatible = "qcom,gpu-pwrlevels"; + qcom,gpu-speed-numplans = <3>; + qcom,gpu-speed-plan = + <0x0 0x0>, + <0x2 0x1>, + <0x3 0x0>; - /* TURBO */ - qcom,gpu-pwrlevel@0 { - reg = <0>; - qcom,gpu-freq = <600000000>; - qcom,bus-freq = <9>; - qcom,bus-min = <9>; - qcom,bus-max = <10>; - }; + qcom,gpu-speed-config@0 { + compatible = "gpu-speed-config@0"; - /* TURBO */ - qcom,gpu-pwrlevel@1 { - reg = <1>; - qcom,gpu-freq = <550000000>; - qcom,bus-freq = <9>; - qcom,bus-min = <9>; - qcom,bus-max = <10>; - }; + qcom,initial-pwrlevel = <5>; - /* NOM+ */ - qcom,gpu-pwrlevel@2 { - reg = <2>; - qcom,gpu-freq = <480000000>; - qcom,bus-freq = <8>; - qcom,bus-min = <7>; - qcom,bus-max = <9>; - }; + /* Power levels */ + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; - /* NOM */ - qcom,gpu-pwrlevel@3 { - reg = <3>; - qcom,gpu-freq = <432000000>; - qcom,bus-freq = <7>; - qcom,bus-min = <5>; - qcom,bus-max = <9>; - }; + compatible = "qcom,gpu-pwrlevels"; - /* SVS */ - qcom,gpu-pwrlevel@4 { - reg = <4>; - qcom,gpu-freq = <300000000>; - qcom,bus-freq = <5>; - qcom,bus-min = <4>; - qcom,bus-max = <7>; - }; + /* SUPER TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <600000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <10>; + }; - /* Low SVS+ */ - qcom,gpu-pwrlevel@5 { - reg = <5>; - qcom,gpu-freq = <266666667>; - qcom,bus-freq = <4>; - qcom,bus-min = <4>; - qcom,bus-max = <5>; - }; + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <550000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <10>; + }; - qcom,gpu-pwrlevel@6 { - reg = <6>; - qcom,gpu-freq = <19200000>; - qcom,bus-freq = <0>; - qcom,bus-min = <0>; - qcom,bus-max = <0>; + /* NOM+ */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <480000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <7>; + qcom,bus-max = <9>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <432000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <5>; + qcom,bus-max = <9>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <300000000>; + qcom,bus-freq = <5>; + qcom,bus-min = <4>; + qcom,bus-max = <7>; + }; + + /* Low SVS+ */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <266666667>; + qcom,bus-freq = <4>; + qcom,bus-min = <4>; + qcom,bus-max = <5>; + }; + + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; }; diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 1ad8737175d5..c5eff53e1fbe 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1017,6 +1017,79 @@ err: return result; } +/* + * Read the Speed fuse data and return device node. + */ +static struct device_node *get_gpu_speed_fuse_data(struct platform_device + *pdev) +{ + struct resource *res; + void __iomem *base; + u32 pte_reg_val; + uint32_t speed_bin = 0, speed_bits, speed_level = 0; + char prop_name[32]; + int i, len, num_config; + const uint32_t *vec_arr = NULL; + + /* Load default configuration, if speed fuse is not defined */ + if (of_property_read_u32(pdev->dev.of_node, + "qcom,gpu-fuse-numconfigs", &num_config)) + return pdev->dev.of_node; + + vec_arr = of_get_property(pdev->dev.of_node, + "qcom,gpu-fuse-config", &len); + if (vec_arr == NULL) + return NULL; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "qfprom_memory"); + if (!res) + return NULL; + + base = ioremap(res->start, resource_size(res)); + if (!base) + return NULL; + + for (i = 0; i < num_config; i++) { + int mask; + + pte_reg_val = __raw_readl(base + be32_to_cpu(vec_arr[i*3])); + mask = be32_to_cpu(vec_arr[(i*3)+2]); + speed_bits = (pte_reg_val >> be32_to_cpu(vec_arr[(i*3)+1])) & + mask; + speed_bin = (speed_bin << ilog2(mask+1)) | speed_bits; + } + + if (of_property_read_u32(pdev->dev.of_node, + "qcom,gpu-speed-numplans", &num_config)) + goto err; + + vec_arr = of_get_property(pdev->dev.of_node, + "qcom,gpu-speed-plan", &len); + if (vec_arr == NULL) + goto err; + + for (i = 0; i < num_config; i++) { + int value, plan; + + value = be32_to_cpu(vec_arr[i*2]); + plan = be32_to_cpu(vec_arr[(i*2)+1]); + if (speed_bin == value) { + speed_level = plan; + break; + } + } + + iounmap(base); + + snprintf(prop_name, ARRAY_SIZE(prop_name), "%s%d", + "gpu-speed-config@", speed_level); + return adreno_of_find_subnode(pdev->dev.of_node, prop_name); + +err: + iounmap(base); + return NULL; +} /* * Read the Speed bin data and return device node. */ @@ -1083,6 +1156,13 @@ static int adreno_of_get_pdata(struct platform_device *pdev) if (node == NULL) goto err; + /* Get Speed fuse Data */ + if (node == pdev->dev.of_node) { + node = get_gpu_speed_fuse_data(pdev); + if (node == NULL) + goto err; + } + /* pwrlevel Data */ ret = adreno_of_get_pwrlevels(node, pdata); if (ret) From 24970068ad279e2d200d8ad46064fbad7b4f513e Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 082/210] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; From 16b12a71cbb90d9b37e15d6be5069dba726187b4 Mon Sep 17 00:00:00 2001 From: Brahmaji K Date: Mon, 24 Oct 2016 20:28:18 +0530 Subject: [PATCH 083/210] crypto : ice: Fix NULL pointer exception in ice. While enabling ICE setup and on error conditions, the regulator is disabled. Before disabling the regulator, check if the regulator is up and able to access the registers of regulator. Change-Id: I94dd2b3e25444818f7bdf2f791f4fa9efaefce15 Signed-off-by: Brahmaji K --- drivers/crypto/msm/ice.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index 7255973d493d..8789b2dbd28b 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -1595,7 +1595,18 @@ static int enable_ice_setup(struct ice_device *ice_dev) out_clocks: qcom_ice_enable_clocks(ice_dev, false); out_reg: - regulator_disable(ice_dev->reg); + if (ice_dev->is_regulator_available) { + if (qcom_ice_get_vreg(ice_dev)) { + pr_err("%s: Could not get regulator\n", __func__); + goto out; + } + ret = regulator_disable(ice_dev->reg); + if (ret) { + pr_err("%s:%p: Could not disable regulator\n", + __func__, ice_dev); + goto out; + } + } out: return ret; } From b480c38177e4f519d71bcac0b435574b039a38cf Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Mon, 16 Jan 2017 00:17:04 +0200 Subject: [PATCH 084/210] msm: ipa: Prevent multiple header deletion from user space An IPA header or processing context can be added once and later deleted once from user space. Multiple deletion may cause invalid state of the headers software cache. Change-Id: Ic0b8472b7fd8a76233a007d90c832af726184574 CRs-fixed: 1097714 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/ipa/ipa.c | 13 ++--- drivers/platform/msm/ipa/ipa_hdr.c | 77 ++++++++++++++++++++++++------ drivers/platform/msm/ipa/ipa_i.h | 11 ++++- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c index 476f2ae8c706..d2b9db199297 100644 --- a/drivers/platform/msm/ipa/ipa.c +++ b/drivers/platform/msm/ipa/ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -549,7 +549,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa_del_hdr((struct ipa_ioc_del_hdr *)param)) { + if (ipa_del_hdr_by_user((struct ipa_ioc_del_hdr *)param, + true)) { retval = -EFAULT; break; } @@ -1230,8 +1231,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa_del_hdr_proc_ctx( - (struct ipa_ioc_del_hdr_proc_ctx *)param)) { + if (ipa_del_hdr_proc_ctx_by_user( + (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) { retval = -EFAULT; break; } @@ -2512,7 +2513,7 @@ fail_schedule_delayed_work: if (ipa_ctx->dflt_v4_rt_rule_hdl) __ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl); if (ipa_ctx->excp_hdr_hdl) - __ipa_del_hdr(ipa_ctx->excp_hdr_hdl); + __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false); ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd); fail_cmd: return result; @@ -2524,7 +2525,7 @@ static void ipa_teardown_apps_pipes(void) ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_data_in); __ipa_del_rt_rule(ipa_ctx->dflt_v6_rt_rule_hdl); __ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl); - __ipa_del_hdr(ipa_ctx->excp_hdr_hdl); + __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false); ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd); } diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c index bb31a3d17474..f4cd470d22ae 100644 --- a/drivers/platform/msm/ipa/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_hdr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -731,7 +731,8 @@ error: return -EPERM; } -static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) +static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, + bool release_hdr, bool by_user) { struct ipa_hdr_proc_ctx_entry *entry; struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; @@ -745,6 +746,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) IPADBG("del ctx proc cnt=%d ofst=%d\n", htbl->proc_ctx_cnt, entry->offset_entry->offset); + if (by_user && entry->user_deleted) { + IPAERR("proc_ctx already deleted by user\n"); + return -EINVAL; + } + + if (by_user) + entry->user_deleted = true; + if (--entry->ref_cnt) { IPADBG("proc_ctx_hdl %x ref_cnt %d\n", proc_ctx_hdl, entry->ref_cnt); @@ -752,7 +761,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) } if (release_hdr) - __ipa_release_hdr(entry->hdr->id); + __ipa_del_hdr(entry->hdr->id, false); /* move the offset entry to appropriate free list */ list_move(&entry->offset_entry->link, @@ -769,7 +778,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) } -int __ipa_del_hdr(u32 hdr_hdl) +int __ipa_del_hdr(u32 hdr_hdl, bool by_user) { struct ipa_hdr_entry *entry; struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; @@ -788,6 +797,14 @@ int __ipa_del_hdr(u32 hdr_hdl) IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len, htbl->hdr_cnt, entry->offset_entry->offset); + if (by_user && entry->user_deleted) { + IPAERR("hdr already deleted by user\n"); + return -EINVAL; + } + + if (by_user) + entry->user_deleted = true; + if (--entry->ref_cnt) { IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt); return 0; @@ -798,7 +815,7 @@ int __ipa_del_hdr(u32 hdr_hdl) entry->phys_base, entry->hdr_len, DMA_TO_DEVICE); - __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false); + __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false, false); } else { /* move the offset entry to appropriate free list */ list_move(&entry->offset_entry->link, @@ -866,15 +883,16 @@ bail: EXPORT_SYMBOL(ipa_add_hdr); /** - * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them - * to IPA HW + * ipa_del_hdr_by_user() - Remove the specified headers + * from SW and optionally commit them to IPA HW * @hdls: [inout] set of headers to delete + * @by_user: Operation requested by user? * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) +int ipa_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user) { int i; int result = -EFAULT; @@ -891,7 +909,7 @@ int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { - if (__ipa_del_hdr(hdls->hdl[i].hdl)) { + if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) { IPAERR("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { @@ -910,6 +928,20 @@ bail: mutex_unlock(&ipa_ctx->lock); return result; } + +/** + * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them + * to IPA HW + * @hdls: [inout] set of headers to delete + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) +{ + return ipa_del_hdr_by_user(hdls, false); +} EXPORT_SYMBOL(ipa_del_hdr); /** @@ -965,16 +997,18 @@ bail: EXPORT_SYMBOL(ipa_add_hdr_proc_ctx); /** - * ipa_del_hdr_proc_ctx() - + * ipa_del_hdr_proc_ctx_by_user() - * Remove the specified processing context headers from SW and * optionally commit them to IPA HW. * @hdls: [inout] set of processing context headers to delete + * @by_user: Operation requested by user? * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) +int ipa_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, + bool by_user) { int i; int result; @@ -993,7 +1027,7 @@ int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { - if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) { + if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) { IPAERR("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { @@ -1012,6 +1046,21 @@ bail: mutex_unlock(&ipa_ctx->lock); return result; } + +/** + * ipa_del_hdr_proc_ctx() - + * Remove the specified processing context headers from SW and + * optionally commit them to IPA HW. + * @hdls: [inout] set of processing context headers to delete + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) +{ + return ipa_del_hdr_proc_ctx_by_user(hdls, false); +} EXPORT_SYMBOL(ipa_del_hdr_proc_ctx); /** @@ -1238,7 +1287,7 @@ int __ipa_release_hdr(u32 hdr_hdl) { int result = 0; - if (__ipa_del_hdr(hdr_hdl)) { + if (__ipa_del_hdr(hdr_hdl, false)) { IPADBG("fail to del hdr %x\n", hdr_hdl); result = -EFAULT; goto bail; @@ -1266,7 +1315,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl) { int result = 0; - if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true)) { + if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) { IPADBG("fail to del hdr %x\n", proc_ctx_hdl); result = -EFAULT; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h index 45ef7ecfa7bd..2ea952c8bd8e 100644 --- a/drivers/platform/msm/ipa/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -242,6 +242,7 @@ struct ipa_rt_tbl { * @id: header entry id * @is_eth2_ofst_valid: is eth2_ofst field valid? * @eth2_ofst: offset to start of Ethernet-II/802.3 header + * @user_deleted: is the header deleted by the user? */ struct ipa_hdr_entry { struct list_head link; @@ -259,6 +260,7 @@ struct ipa_hdr_entry { int id; u8 is_eth2_ofst_valid; u16 eth2_ofst; + bool user_deleted; }; /** @@ -334,6 +336,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { * @cookie: cookie used for validity check * @ref_cnt: reference counter of routing table * @id: processing context header entry id + * @user_deleted: is the hdr processing context deleted by the user? */ struct ipa_hdr_proc_ctx_entry { struct list_head link; @@ -343,6 +346,7 @@ struct ipa_hdr_proc_ctx_entry { u32 cookie; u32 ref_cnt; int id; + bool user_deleted; }; /** @@ -1489,8 +1493,11 @@ void ipa_inc_client_enable_clks(void); int ipa_inc_client_enable_clks_no_block(void); void ipa_dec_client_disable_clks(void); int ipa_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev); +int ipa_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); +int ipa_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, + bool by_user); int __ipa_del_rt_rule(u32 rule_hdl); -int __ipa_del_hdr(u32 hdr_hdl); +int __ipa_del_hdr(u32 hdr_hdl, bool by_user); int __ipa_release_hdr(u32 hdr_hdl); int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl); int _ipa_read_gen_reg_v1_1(char *buff, int max_len); From 2f37d91374d5d8b6a89a8cfdef3d5c34c084024e Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Wed, 8 Feb 2017 14:16:58 +0530 Subject: [PATCH 085/210] msm: camera: Add check to ensure task wont hog CPU In case the userspace code manipulates the list to be circular This way the task will hog the CPU in while loop. CRs-Fixed: 1064608 Change-Id: Ie896fd3da326e5e972266d8004baecf8681aea6d Signed-off-by: VijayaKumar T M --- .../platform/msm/camera_v2/isp/msm_isp_util.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index dcc28f18b6a9..3f483ec6a47a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2017 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 @@ -22,6 +22,7 @@ #include "cam_smmu_api.h" #define MAX_ISP_V4l2_EVENTS 100 +#define MAX_ISP_REG_LIST 100 static DEFINE_MUTEX(bandwidth_mgr_mutex); static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr; @@ -861,6 +862,7 @@ static int msm_isp_set_dual_HW_master_slave_mode( static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg) { int rc = 0; + uint32_t count = 0; struct msm_vfe_cfg_cmd_list *proc_cmd = (struct msm_vfe_cfg_cmd_list *)arg; struct msm_vfe_cfg_cmd_list cmd, cmd_next; @@ -884,6 +886,11 @@ static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg) sizeof(struct msm_vfe_cfg_cmd_list)); break; } + if (++count >= MAX_ISP_REG_LIST) { + pr_err("%s:%d Error exceeding the max register count:%u\n", + __func__, __LINE__, count); + break; + } if (copy_from_user(&cmd_next, (void __user *)cmd.next, sizeof(struct msm_vfe_cfg_cmd_list))) { rc = -EFAULT; @@ -930,6 +937,7 @@ static void msm_isp_compat_to_proc_cmd(struct msm_vfe_cfg_cmd2 *proc_cmd, static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg) { int rc = 0; + uint32_t count = 0; struct msm_vfe_cfg_cmd_list_32 *proc_cmd = (struct msm_vfe_cfg_cmd_list_32 *)arg; struct msm_vfe_cfg_cmd_list_32 cmd, cmd_next; @@ -954,6 +962,11 @@ static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg) sizeof(struct msm_vfe_cfg_cmd_list)); break; } + if (++count >= MAX_ISP_REG_LIST) { + pr_err("%s:%d Error exceeding the max register count:%u\n", + __func__, __LINE__, count); + break; + } if (copy_from_user(&cmd_next, compat_ptr(cmd.next), sizeof(struct msm_vfe_cfg_cmd_list_32))) { rc = -EFAULT; @@ -2004,7 +2017,7 @@ static void msm_isp_process_overflow_irq( error_event.frame_id = vfe_dev->axi_data.src_info[input_src].frame_id; error_event.u.error_info.err_type = ISP_ERROR_BUS_OVERFLOW; - error_event.u.error_info.stream_id_mask= input_src; + error_event.u.error_info.stream_id_mask = input_src; msm_isp_send_event(vfe_dev, ISP_EVENT_ERROR, &error_event); } } @@ -2192,7 +2205,7 @@ static int msm_vfe_iommu_fault_handler(struct iommu_domain *domain, HALT_ENFORCED); msm_isp_enqueue_tasklet_cmd(vfe_dev, 0, 0, 1); } else { - pr_err("%s cannot handle vfe_cnt %d",__func__, + pr_err("%s cannot handle vfe_cnt %d", __func__, vfe_dev->vfe_open_cnt); } mutex_unlock(&vfe_dev->core_mutex); From 2d8121e6eb0d79542bb29311f03559df92e93a31 Mon Sep 17 00:00:00 2001 From: Gidon Studinski Date: Mon, 23 Jan 2017 11:55:53 +0200 Subject: [PATCH 086/210] ecm_ipa: remove redundant code Remove ECM_IPA debugging capabilities which are no longer needed, nor used. CRs-Fixed: 1112912 Change-Id: I20765d84ca7351c436d39d0f10b7f7a819bcc40b Signed-off-by: Gidon Studinski --- drivers/net/ethernet/msm/ecm_ipa.c | 269 +---------------------------- 1 file changed, 4 insertions(+), 265 deletions(-) diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c index 8dc0db7d4446..a6057f9a5375 100644 --- a/drivers/net/ethernet/msm/ecm_ipa.c +++ b/drivers/net/ethernet/msm/ecm_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -9,7 +9,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - #include #include #include @@ -106,10 +105,6 @@ enum ecm_ipa_operation { * struct ecm_ipa_dev - main driver context parameters * @net: network interface struct implemented by this driver * @directory: debugfs directory for various debuging switches - * @tx_enable: flag that enable/disable Tx path to continue to IPA - * @rx_enable: flag that enable/disable Rx path to continue to IPA - * @rm_enable: flag that enable/disable Resource manager request prior to Tx - * @dma_enable: flag that allow on-the-fly DMA mode for IPA * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table * @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table * @usb_to_ipa_hdl: save handle for IPA pipe operations @@ -129,10 +124,6 @@ enum ecm_ipa_operation { */ struct ecm_ipa_dev { struct net_device *net; - u32 tx_enable; - u32 rx_enable; - u32 rm_enable; - bool dma_enable; struct dentry *directory; uint32_t eth_ipv4_hdr_hdl; uint32_t eth_ipv6_hdr_hdl; @@ -167,32 +158,16 @@ static void ecm_ipa_rm_notify(void *user_data, enum ipa_rm_event event, static struct net_device_stats *ecm_ipa_get_stats(struct net_device *net); static int ecm_ipa_create_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx); static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx); -static bool rx_filter(struct sk_buff *skb); -static bool tx_filter(struct sk_buff *skb); -static bool rm_enabled(struct ecm_ipa_dev *ecm_ipa_ctx); static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx); static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx); static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, struct net_device *net); -static int ecm_ipa_debugfs_stall_open(struct inode *inode, - struct file *file); -static ssize_t ecm_ipa_debugfs_stall_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file); -static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file); -static ssize_t ecm_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos); static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx); static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *ecm_ipa_ctx); static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl); -static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl, - enum ipa_client_type prod_client); static int ecm_ipa_set_device_ethernet_addr(u8 *dev_ethaddr, u8 device_ethaddr[]); static enum ecm_ipa_state ecm_ipa_next_state(enum ecm_ipa_state current_state, @@ -210,22 +185,11 @@ static const struct net_device_ops ecm_ipa_netdev_ops = { .ndo_get_stats = ecm_ipa_get_stats, }; -const struct file_operations ecm_ipa_debugfs_dma_ops = { - .open = ecm_ipa_debugfs_dma_open, - .read = ecm_ipa_debugfs_enable_read, - .write = ecm_ipa_debugfs_enable_write_dma, -}; - const struct file_operations ecm_ipa_debugfs_atomic_ops = { .open = ecm_ipa_debugfs_atomic_open, .read = ecm_ipa_debugfs_atomic_read, }; -const struct file_operations ecm_ipa_debugfs_stall_ops = { - .open = ecm_ipa_debugfs_stall_open, - .write = ecm_ipa_debugfs_stall_write, -}; - static void ecm_ipa_msg_free_cb(void *buff, u32 len, u32 type) { kfree(buff); @@ -286,9 +250,6 @@ int ecm_ipa_init(struct ecm_ipa_params *params) ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p\n", ecm_ipa_ctx); ecm_ipa_ctx->net = net; - ecm_ipa_ctx->tx_enable = true; - ecm_ipa_ctx->rx_enable = true; - ecm_ipa_ctx->rm_enable = true; ecm_ipa_ctx->outstanding_high = DEFAULT_OUTSTANDING_HIGH; ecm_ipa_ctx->outstanding_low = DEFAULT_OUTSTANDING_LOW; atomic_set(&ecm_ipa_ctx->outstanding_pkts, 0); @@ -604,12 +565,6 @@ static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (unlikely(tx_filter(skb))) { - dev_kfree_skb_any(skb); - ECM_IPA_DEBUG("packet got filtered out on Tx path\n"); - status = NETDEV_TX_OK; - goto out; - } ret = resource_request(ecm_ipa_ctx); if (ret) { ECM_IPA_DEBUG("Waiting to resource\n"); @@ -682,11 +637,6 @@ static void ecm_ipa_packet_receive_notify(void *priv, skb->dev = ecm_ipa_ctx->net; skb->protocol = eth_type_trans(skb, ecm_ipa_ctx->net); - if (rx_filter(skb)) { - ECM_IPA_DEBUG("packet got filtered out on Rx path\n"); - dev_kfree_skb_any(skb); - return; - } result = netif_rx_ni(skb); if (result) @@ -1149,42 +1099,15 @@ static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_LOG_EXIT(); } -static bool rx_filter(struct sk_buff *skb) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(skb->dev); - return !ecm_ipa_ctx->rx_enable; -} - -static bool tx_filter(struct sk_buff *skb) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(skb->dev); - return !ecm_ipa_ctx->tx_enable; -} - -static bool rm_enabled(struct ecm_ipa_dev *ecm_ipa_ctx) -{ - return ecm_ipa_ctx->rm_enable; -} - static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx) { - int result = 0; - - if (!rm_enabled(ecm_ipa_ctx)) - goto out; - result = ipa_rm_inactivity_timer_request_resource( - IPA_RM_RESOURCE_STD_ECM_PROD); -out: - return result; + return ipa_rm_inactivity_timer_request_resource( + IPA_RM_RESOURCE_STD_ECM_PROD); } static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx) { - if (!rm_enabled(ecm_ipa_ctx)) - goto out; ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_STD_ECM_PROD); -out: - return; } /** @@ -1257,45 +1180,6 @@ static void ecm_ipa_tx_timeout(struct net_device *net) net->stats.tx_errors++; } -static int ecm_ipa_debugfs_stall_open(struct inode *inode, - struct file *file) -{ - ECM_IPA_LOG_ENTRY(); - - ECM_IPA_LOG_EXIT(); - - return 0; -} - -static ssize_t ecm_ipa_debugfs_stall_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - u32 cmdq_cfg_mmio_phy = 0xFD4E3038; - void *cmdq_cfg_mmio_virt; - int result; - bool val = 0; - - ECM_IPA_LOG_ENTRY(); - - file->private_data = &val; - result = ecm_ipa_debugfs_enable_write(file, buf, count, ppos); - - cmdq_cfg_mmio_virt = ioremap(cmdq_cfg_mmio_phy, sizeof(u32)); - if (!cmdq_cfg_mmio_virt) { - ECM_IPA_ERROR("fail on mmio for cmdq_cfg_mmio_phy=0x%x", - cmdq_cfg_mmio_phy); - return result; - } - - iowrite32(val, cmdq_cfg_mmio_virt); - ECM_IPA_DEBUG("Value %d was written to cfgq", val); - - ECM_IPA_LOG_EXIT(); - - return result; - -} - static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) { struct ecm_ipa_dev *ecm_ipa_ctx = inode->i_private; @@ -1305,78 +1189,6 @@ static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) return 0; } -static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = file->private_data; - int result; - ECM_IPA_LOG_ENTRY(); - file->private_data = &ecm_ipa_ctx->dma_enable; - result = ecm_ipa_debugfs_enable_write(file, buf, count, ppos); - if (ecm_ipa_ctx->dma_enable) - ecm_ipa_ep_registers_dma_cfg(ecm_ipa_ctx->usb_to_ipa_hdl, - ecm_ipa_ctx->ipa_to_usb_client); - else - ecm_ipa_ep_registers_cfg(ecm_ipa_ctx->usb_to_ipa_hdl, - ecm_ipa_ctx->usb_to_ipa_hdl); - ECM_IPA_LOG_EXIT(); - return result; -} - -static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = inode->i_private; - ECM_IPA_LOG_ENTRY(); - file->private_data = ecm_ipa_ctx; - ECM_IPA_LOG_EXIT(); - return 0; -} - -static ssize_t ecm_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long missing; - char input; - bool *enable = file->private_data; - if (count != sizeof(input) + 1) { - ECM_IPA_ERROR("wrong input length(%zd)\n", count); - return -EINVAL; - } - if (!buf) { - ECM_IPA_ERROR("Bad argument\n"); - return -EINVAL; - } - missing = copy_from_user(&input, buf, 1); - if (missing) - return -EFAULT; - ECM_IPA_DEBUG("input received %c\n", input); - *enable = input - '0'; - ECM_IPA_DEBUG("value was set to %d\n", *enable); - return count; -} - -static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int nbytes; - int size = 0; - int ret; - loff_t pos; - u8 enable_str[sizeof(char)*3] = {0}; - bool *enable = file->private_data; - pos = *ppos; - nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); - ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); - if (ret < 0) { - ECM_IPA_ERROR("simple_read_from_buffer problem\n"); - return ret; - } - size += ret; - count -= nbytes; - *ppos = pos + size; - return size; -} - static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { @@ -1393,7 +1205,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) { const mode_t flags_read_write = S_IRUGO | S_IWUGO; const mode_t flags_read_only = S_IRUGO; - const mode_t flags_write_only = S_IWUGO; struct dentry *file; ECM_IPA_LOG_ENTRY(); @@ -1406,24 +1217,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_ERROR("could not create debugfs directory entry\n"); goto fail_directory; } - file = debugfs_create_bool("tx_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->tx_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs tx file\n"); - goto fail_file; - } - file = debugfs_create_bool("rx_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->rx_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs rx file\n"); - goto fail_file; - } - file = debugfs_create_bool("rm_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->rm_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs rm file\n"); - goto fail_file; - } file = debugfs_create_u8("outstanding_high", flags_read_write, ecm_ipa_ctx->directory, &ecm_ipa_ctx->outstanding_high); if (!file) { @@ -1436,13 +1229,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_ERROR("could not create outstanding_low file\n"); goto fail_file; } - file = debugfs_create_file("dma_enable", flags_read_write, - ecm_ipa_ctx->directory, - ecm_ipa_ctx, &ecm_ipa_debugfs_dma_ops); - if (!file) { - ECM_IPA_ERROR("could not create debugfs dma file\n"); - goto fail_file; - } file = debugfs_create_file("outstanding", flags_read_only, ecm_ipa_ctx->directory, ecm_ipa_ctx, &ecm_ipa_debugfs_atomic_ops); @@ -1451,14 +1237,7 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) goto fail_file; } - file = debugfs_create_file("stall_ipa_rx_proc", flags_write_only, - ecm_ipa_ctx->directory, - ecm_ipa_ctx, &ecm_ipa_debugfs_stall_ops); - if (!file) { - ECM_IPA_ERROR("could not create stall_ipa_rx_proc file\n"); - goto fail_file; - } - + ECM_IPA_DEBUG("debugfs entries were created\n"); ECM_IPA_LOG_EXIT(); return 0; @@ -1521,46 +1300,6 @@ out: return result; } -/** - * ecm_ipa_ep_registers_dma_cfg() - configure the USB endpoints for ECM - * DMA - * @usb_to_ipa_hdl: handle received from ipa_connect - * - * This function will override the previous configuration - * which is needed for cores that does not support blocks logic - * Note that client handles are the actual pipe index - */ -static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl, - enum ipa_client_type prod_client) -{ - int result = 0; - struct ipa_ep_cfg_mode cfg_mode; - u32 apps_to_ipa_hdl = 2; - - ECM_IPA_LOG_ENTRY(); - - memset(&cfg_mode, 0 , sizeof(cfg_mode)); - cfg_mode.mode = IPA_DMA; - cfg_mode.dst = prod_client; - result = ipa_cfg_ep_mode(apps_to_ipa_hdl, &cfg_mode); - if (result) { - ECM_IPA_ERROR("failed to configure Apps to IPA\n"); - goto out; - } - memset(&cfg_mode, 0 , sizeof(cfg_mode)); - cfg_mode.mode = IPA_DMA; - cfg_mode.dst = IPA_CLIENT_A5_LAN_WAN_CONS; - result = ipa_cfg_ep_mode(usb_to_ipa_hdl, &cfg_mode); - if (result) { - ECM_IPA_ERROR("failed to configure USB to IPA\n"); - goto out; - } - ECM_IPA_DEBUG("end-point registers successfully configured\n"); -out: - ECM_IPA_LOG_EXIT(); - return result; -} - /** * ecm_ipa_set_device_ethernet_addr() - set device etherenet address * @dev_ethaddr: device etherenet address From b463edce6909b6be9f453fac627a5990f02ec382 Mon Sep 17 00:00:00 2001 From: ansharma Date: Thu, 9 Feb 2017 18:01:42 +0530 Subject: [PATCH 087/210] power: qpnp-fg: Fix possible race condition in FG debugfs There is a possible race condition when FG debugfs files are concurrently accessed by multiple threads. Fix this. CRs-Fixed: 1105481 Change-Id: I154e7f3cdd8d51cf67ef1dfd9d78f423f183cb64 Signed-off-by: ansharma --- drivers/power/qpnp-fg.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c index e01eb52ff472..bd3bdc6ac734 100644 --- a/drivers/power/qpnp-fg.c +++ b/drivers/power/qpnp-fg.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2017 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 @@ -526,6 +526,7 @@ struct fg_trans { struct fg_chip *chip; struct fg_log_buffer *log; /* log buffer */ u8 *data; /* fg data that is read */ + struct mutex memif_dfs_lock; /* Prevent thread concurrency */ }; struct fg_dbgfs { @@ -5260,6 +5261,7 @@ static int fg_memif_data_open(struct inode *inode, struct file *file) trans->addr = dbgfs_data.addr; trans->chip = dbgfs_data.chip; trans->offset = trans->addr; + mutex_init(&trans->memif_dfs_lock); file->private_data = trans; return 0; @@ -5271,6 +5273,7 @@ static int fg_memif_dfs_close(struct inode *inode, struct file *file) if (trans && trans->log && trans->data) { file->private_data = NULL; + mutex_destroy(&trans->memif_dfs_lock); kfree(trans->log); kfree(trans->data); kfree(trans); @@ -5428,10 +5431,13 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, size_t ret; size_t len; + mutex_lock(&trans->memif_dfs_lock); /* Is the the log buffer empty */ if (log->rpos >= log->wpos) { - if (get_log_data(trans) <= 0) - return 0; + if (get_log_data(trans) <= 0) { + len = 0; + goto unlock_mutex; + } } len = min(count, log->wpos - log->rpos); @@ -5439,7 +5445,8 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret == len) { pr_err("error copy sram register values to user\n"); - return -EFAULT; + len = -EFAULT; + goto unlock_mutex; } /* 'ret' is the number of bytes not copied */ @@ -5447,6 +5454,9 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, *ppos += len; log->rpos += len; + +unlock_mutex: + mutex_unlock(&trans->memif_dfs_lock); return len; } @@ -5467,14 +5477,20 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, int cnt = 0; u8 *values; size_t ret = 0; + char *kbuf; + u32 offset; struct fg_trans *trans = file->private_data; - u32 offset = trans->offset; + + mutex_lock(&trans->memif_dfs_lock); + offset = trans->offset; /* Make a copy of the user data */ - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -5513,6 +5529,8 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&trans->memif_dfs_lock); return ret; } From c32d2c02f24e7e08aa14190f69e870db8a802c7c Mon Sep 17 00:00:00 2001 From: ansharma Date: Thu, 9 Feb 2017 20:43:08 +0530 Subject: [PATCH 088/210] platform: msm: spmi: Fix possible race condition in debugfs There is a possible race condition when debugfs files are concurrently accessed by multiple threads. Fix this. CRs-Fixed: 1106842 Change-Id: Ifd092143f428db3cf73c45ec4f0aaa96318ae165 Signed-off-by: ansharma --- drivers/spmi/spmi-dbgfs.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/spmi/spmi-dbgfs.c b/drivers/spmi/spmi-dbgfs.c index 3ebcbc387ba6..363a0697164d 100644 --- a/drivers/spmi/spmi-dbgfs.c +++ b/drivers/spmi/spmi-dbgfs.c @@ -75,6 +75,7 @@ struct spmi_trans { u32 addr; /* 20-bit address: SID + PID + Register offset */ u32 offset; /* Offset of last read data */ bool raw_data; /* Set to true for raw data dump */ + struct mutex spmi_dfs_lock; /* Prevent thread concurrency */ struct spmi_controller *ctrl; struct spmi_log_buffer *log; /* log buffer */ }; @@ -174,6 +175,7 @@ static int spmi_dfs_open(struct spmi_ctrl_data *ctrl_data, struct file *file) trans->addr = ctrl_data->addr; trans->ctrl = ctrl_data->ctrl; trans->offset = trans->addr; + mutex_init(&trans->spmi_dfs_lock); file->private_data = trans; return 0; @@ -203,6 +205,7 @@ static int spmi_dfs_close(struct inode *inode, struct file *file) if (trans && trans->log) { file->private_data = NULL; + mutex_destroy(&trans->spmi_dfs_lock); kfree(trans->log); kfree(trans); } @@ -482,14 +485,20 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf, int cnt = 0; u8 *values; size_t ret = 0; - + u32 offset; + char *kbuf; struct spmi_trans *trans = file->private_data; - u32 offset = trans->offset; + + mutex_lock(&trans->spmi_dfs_lock); + + offset = trans->offset; /* Make a copy of the user data */ - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -526,6 +535,8 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&trans->spmi_dfs_lock); return ret; } #else @@ -549,10 +560,13 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, size_t ret; size_t len; + mutex_lock(&trans->spmi_dfs_lock); /* Is the the log buffer empty */ if (log->rpos >= log->wpos) { - if (get_log_data(trans) <= 0) - return 0; + if (get_log_data(trans) <= 0) { + len = 0; + goto unlock_mutex; + } } len = min(count, log->wpos - log->rpos); @@ -560,7 +574,8 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret == len) { pr_err("error copy SPMI register values to user\n"); - return -EFAULT; + len = -EFAULT; + goto unlock_mutex; } /* 'ret' is the number of bytes not copied */ @@ -568,6 +583,9 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, *ppos += len; log->rpos += len; + +unlock_mutex: + mutex_unlock(&trans->spmi_dfs_lock); return len; } From 202abda348fc789383c1a6a217a59116e12676fe Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Tue, 22 Nov 2016 13:51:51 -0800 Subject: [PATCH 089/210] ASoC: msm: qdsp6v2: Fix an incorrect string comparison logic A conditional branch is skipped due to incorrect string comparison. It is fixed by using "strcmp" to perform string comparison. CRs-fixed: 1085889 Change-Id: I12be44ac272fc5079230feb6ae24c68ccde99cf2 Signed-off-by: Xiaoyu Ye Signed-off-by: Bhalchandra Gajare --- sound/soc/msm/qdsp6v2/q6afe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index ffc72a2164fe..29c1cb632e4c 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -3492,7 +3492,7 @@ static ssize_t afe_debug_write(struct file *filp, lbuf[cnt] = '\0'; - if (!strncmp(lb_str, "afe_loopback", 12)) { + if (!strcmp(lb_str, "afe_loopback")) { rc = afe_get_parameters(lbuf, param, 3); if (!rc) { pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1], @@ -3521,7 +3521,7 @@ static ssize_t afe_debug_write(struct file *filp, rc = -EINVAL; } - } else if (!strncmp(lb_str, "afe_loopback_gain", 17)) { + } else if (!strcmp(lb_str, "afe_loopback_gain")) { rc = afe_get_parameters(lbuf, param, 2); if (!rc) { pr_info("%s: %s %lu %lu\n", From d1735a02abe8a7ecb5bd8270198425eefde16344 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Mon, 16 Jan 2017 00:17:04 +0200 Subject: [PATCH 090/210] msm: ipa: Prevent multiple header deletion from user space An IPA header or processing context can be added once and later deleted once from user space. Multiple deletion may cause invalid state of the headers software cache. Change-Id: Ic0b8472b7fd8a76233a007d90c832af726184574 CRs-fixed: 1097714 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/ipa/ipa.c | 13 ++--- drivers/platform/msm/ipa/ipa_hdr.c | 77 ++++++++++++++++++++++++------ drivers/platform/msm/ipa/ipa_i.h | 11 ++++- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c index 476f2ae8c706..8e498715f0e1 100644 --- a/drivers/platform/msm/ipa/ipa.c +++ b/drivers/platform/msm/ipa/ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017 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 @@ -549,7 +549,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa_del_hdr((struct ipa_ioc_del_hdr *)param)) { + if (ipa_del_hdr_by_user((struct ipa_ioc_del_hdr *)param, + true)) { retval = -EFAULT; break; } @@ -1230,8 +1231,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa_del_hdr_proc_ctx( - (struct ipa_ioc_del_hdr_proc_ctx *)param)) { + if (ipa_del_hdr_proc_ctx_by_user( + (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) { retval = -EFAULT; break; } @@ -2512,7 +2513,7 @@ fail_schedule_delayed_work: if (ipa_ctx->dflt_v4_rt_rule_hdl) __ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl); if (ipa_ctx->excp_hdr_hdl) - __ipa_del_hdr(ipa_ctx->excp_hdr_hdl); + __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false); ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd); fail_cmd: return result; @@ -2524,7 +2525,7 @@ static void ipa_teardown_apps_pipes(void) ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_data_in); __ipa_del_rt_rule(ipa_ctx->dflt_v6_rt_rule_hdl); __ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl); - __ipa_del_hdr(ipa_ctx->excp_hdr_hdl); + __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false); ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd); } diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c index bb31a3d17474..f4cd470d22ae 100644 --- a/drivers/platform/msm/ipa/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_hdr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -731,7 +731,8 @@ error: return -EPERM; } -static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) +static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, + bool release_hdr, bool by_user) { struct ipa_hdr_proc_ctx_entry *entry; struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; @@ -745,6 +746,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) IPADBG("del ctx proc cnt=%d ofst=%d\n", htbl->proc_ctx_cnt, entry->offset_entry->offset); + if (by_user && entry->user_deleted) { + IPAERR("proc_ctx already deleted by user\n"); + return -EINVAL; + } + + if (by_user) + entry->user_deleted = true; + if (--entry->ref_cnt) { IPADBG("proc_ctx_hdl %x ref_cnt %d\n", proc_ctx_hdl, entry->ref_cnt); @@ -752,7 +761,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) } if (release_hdr) - __ipa_release_hdr(entry->hdr->id); + __ipa_del_hdr(entry->hdr->id, false); /* move the offset entry to appropriate free list */ list_move(&entry->offset_entry->link, @@ -769,7 +778,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) } -int __ipa_del_hdr(u32 hdr_hdl) +int __ipa_del_hdr(u32 hdr_hdl, bool by_user) { struct ipa_hdr_entry *entry; struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; @@ -788,6 +797,14 @@ int __ipa_del_hdr(u32 hdr_hdl) IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len, htbl->hdr_cnt, entry->offset_entry->offset); + if (by_user && entry->user_deleted) { + IPAERR("hdr already deleted by user\n"); + return -EINVAL; + } + + if (by_user) + entry->user_deleted = true; + if (--entry->ref_cnt) { IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt); return 0; @@ -798,7 +815,7 @@ int __ipa_del_hdr(u32 hdr_hdl) entry->phys_base, entry->hdr_len, DMA_TO_DEVICE); - __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false); + __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false, false); } else { /* move the offset entry to appropriate free list */ list_move(&entry->offset_entry->link, @@ -866,15 +883,16 @@ bail: EXPORT_SYMBOL(ipa_add_hdr); /** - * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them - * to IPA HW + * ipa_del_hdr_by_user() - Remove the specified headers + * from SW and optionally commit them to IPA HW * @hdls: [inout] set of headers to delete + * @by_user: Operation requested by user? * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) +int ipa_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user) { int i; int result = -EFAULT; @@ -891,7 +909,7 @@ int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { - if (__ipa_del_hdr(hdls->hdl[i].hdl)) { + if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) { IPAERR("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { @@ -910,6 +928,20 @@ bail: mutex_unlock(&ipa_ctx->lock); return result; } + +/** + * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them + * to IPA HW + * @hdls: [inout] set of headers to delete + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) +{ + return ipa_del_hdr_by_user(hdls, false); +} EXPORT_SYMBOL(ipa_del_hdr); /** @@ -965,16 +997,18 @@ bail: EXPORT_SYMBOL(ipa_add_hdr_proc_ctx); /** - * ipa_del_hdr_proc_ctx() - + * ipa_del_hdr_proc_ctx_by_user() - * Remove the specified processing context headers from SW and * optionally commit them to IPA HW. * @hdls: [inout] set of processing context headers to delete + * @by_user: Operation requested by user? * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) +int ipa_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, + bool by_user) { int i; int result; @@ -993,7 +1027,7 @@ int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { - if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) { + if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) { IPAERR("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { @@ -1012,6 +1046,21 @@ bail: mutex_unlock(&ipa_ctx->lock); return result; } + +/** + * ipa_del_hdr_proc_ctx() - + * Remove the specified processing context headers from SW and + * optionally commit them to IPA HW. + * @hdls: [inout] set of processing context headers to delete + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) +{ + return ipa_del_hdr_proc_ctx_by_user(hdls, false); +} EXPORT_SYMBOL(ipa_del_hdr_proc_ctx); /** @@ -1238,7 +1287,7 @@ int __ipa_release_hdr(u32 hdr_hdl) { int result = 0; - if (__ipa_del_hdr(hdr_hdl)) { + if (__ipa_del_hdr(hdr_hdl, false)) { IPADBG("fail to del hdr %x\n", hdr_hdl); result = -EFAULT; goto bail; @@ -1266,7 +1315,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl) { int result = 0; - if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true)) { + if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) { IPADBG("fail to del hdr %x\n", proc_ctx_hdl); result = -EFAULT; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h index 45ef7ecfa7bd..a3d6051b7596 100644 --- a/drivers/platform/msm/ipa/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017 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 @@ -242,6 +242,7 @@ struct ipa_rt_tbl { * @id: header entry id * @is_eth2_ofst_valid: is eth2_ofst field valid? * @eth2_ofst: offset to start of Ethernet-II/802.3 header + * @user_deleted: is the header deleted by the user? */ struct ipa_hdr_entry { struct list_head link; @@ -259,6 +260,7 @@ struct ipa_hdr_entry { int id; u8 is_eth2_ofst_valid; u16 eth2_ofst; + bool user_deleted; }; /** @@ -334,6 +336,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { * @cookie: cookie used for validity check * @ref_cnt: reference counter of routing table * @id: processing context header entry id + * @user_deleted: is the hdr processing context deleted by the user? */ struct ipa_hdr_proc_ctx_entry { struct list_head link; @@ -343,6 +346,7 @@ struct ipa_hdr_proc_ctx_entry { u32 cookie; u32 ref_cnt; int id; + bool user_deleted; }; /** @@ -1489,8 +1493,11 @@ void ipa_inc_client_enable_clks(void); int ipa_inc_client_enable_clks_no_block(void); void ipa_dec_client_disable_clks(void); int ipa_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev); +int ipa_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); +int ipa_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, + bool by_user); int __ipa_del_rt_rule(u32 rule_hdl); -int __ipa_del_hdr(u32 hdr_hdl); +int __ipa_del_hdr(u32 hdr_hdl, bool by_user); int __ipa_release_hdr(u32 hdr_hdl); int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl); int _ipa_read_gen_reg_v1_1(char *buff, int max_len); From 552843b4b07230376dd853c1d22fd7a5fbd0dd7c Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Thu, 3 Nov 2016 15:24:35 +0530 Subject: [PATCH 091/210] mm: cma: check the max limit for cma allocation CMA allocation request size is represented by size_t that gets truncated when same is passed as int to bitmap_find_next_zero_area_off. We observe that during fuzz testing when cma allocation request is too high, bitmap_find_next_zero_area_off still returns success due to the truncation. This leads to kernel crash, as subsequent code assumes that requested memory is available. Fail cma allocation in case the request breaches the corresponding cma region size. Change-Id: Ieb5fd8429726efd7686387bccb55952fb053280a Signed-off-by: Shiraz Hashim --- drivers/base/dma-contiguous.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index cf24219d8c96..ee521f7b3397 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -667,6 +667,9 @@ unsigned long dma_alloc_from_contiguous(struct device *dev, size_t count, if (!count) return 0; + if (count > cma->count) + return 0; + mask = (1 << align) - 1; From 789b39529f8421d8ca07c152bcd93d9ed15cb26e Mon Sep 17 00:00:00 2001 From: "Sravan Kumar D.V.N" Date: Tue, 17 Jan 2017 12:11:56 +0530 Subject: [PATCH 092/210] msm: mdss: Fix possible integer overflow Avoid possible integer overflow while validating mdp3 lut config parameters. Change-Id: Ie3f59748e613fbbf755a98dcc688491a8c4e2cca CRs-Fixed: 1104664 Signed-off-by: Sravan Kumar D.V.N --- drivers/video/msm/mdss/mdp3_ctrl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index ed18a082421b..5844b4ba571d 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017, 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 @@ -1984,8 +1984,10 @@ static int mdp3_ctrl_lut_config(struct msm_fb_data_type *mfd, dma = mdp3_session->dma; - if (cfg->cmap.start + cfg->cmap.len > MDP_LUT_SIZE) { - pr_err("Invalid arguments\n"); + if ((cfg->cmap.start > MDP_LUT_SIZE) || + (cfg->cmap.len > MDP_LUT_SIZE) || + (cfg->cmap.start + cfg->cmap.len > MDP_LUT_SIZE)) { + pr_err("Invalid arguments.\n"); return -EINVAL; } From b8f70068650a6e6bef0a41de2e30c17087d3a84d Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Tue, 14 Feb 2017 13:52:08 +0530 Subject: [PATCH 093/210] defconfig: disable cp_access cpaccess module gives userspace control over system control registers so disable cp_access module. Change-Id: Ib49412957f91ce65f4350c5c72358b1c53eed43e Signed-off-by: Srinivasarao P --- arch/arm/configs/msm8916-perf_defconfig | 2 +- arch/arm/configs/msm8916_defconfig | 2 +- arch/arm64/configs/msm_defconfig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/msm8916-perf_defconfig b/arch/arm/configs/msm8916-perf_defconfig index 08a43dec0f4c..94d2321e6e30 100644 --- a/arch/arm/configs/msm8916-perf_defconfig +++ b/arch/arm/configs/msm8916-perf_defconfig @@ -64,7 +64,7 @@ CONFIG_AEABI=y CONFIG_BALANCE_ANON_FILE_RECLAIM=y CONFIG_HIGHMEM=y CONFIG_ENABLE_VMALLOC_SAVING=y -CONFIG_CP_ACCESS=y +# CONFIG_CP_ACCESS is not set CONFIG_AUTO_ZRELADDR=y CONFIG_ARM_DECOMPRESSOR_LIMIT=0x3200000 CONFIG_SCHED_FREQ_INPUT=y diff --git a/arch/arm/configs/msm8916_defconfig b/arch/arm/configs/msm8916_defconfig index b7caf59b54ee..30a81e365346 100644 --- a/arch/arm/configs/msm8916_defconfig +++ b/arch/arm/configs/msm8916_defconfig @@ -62,7 +62,7 @@ CONFIG_AEABI=y CONFIG_BALANCE_ANON_FILE_RECLAIM=y CONFIG_HIGHMEM=y CONFIG_ENABLE_VMALLOC_SAVING=y -CONFIG_CP_ACCESS=y +# CONFIG_CP_ACCESS is not set CONFIG_AUTO_ZRELADDR=y CONFIG_ARM_DECOMPRESSOR_LIMIT=0x3200000 CONFIG_SCHED_FREQ_INPUT=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index 4a26793486ee..d8e8a8263a47 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -528,7 +528,7 @@ CONFIG_CORESIGHT_REMOTE_ETM=y CONFIG_CORESIGHT_QPDI=y CONFIG_SENSORS=y CONFIG_SENSORS_SSC=y -CONFIG_CP_ACCESS64=y +# CONFIG_CP_ACCESS64 is not set CONFIG_MSM_GLADIATOR_ERP=y CONFIG_MSM_BAM_DMUX=y CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y From 58c7003d4024a270810c9dc62c4bb5bc7efc2541 Mon Sep 17 00:00:00 2001 From: "Raju P.L.S.S.S.N" Date: Tue, 31 Jan 2017 23:00:00 +0530 Subject: [PATCH 094/210] msm: pm: Add mutex lock for shared data The buffer allocated in file open operations need to be protected as there can be a possiblity of use-after-free scenario. Process A B | | open | | | read started | | close Add mutex lock to protect the buffer to avoid this. Change-Id: I1e066fd0a047bcec2af7829015089d5c882fb2f3 Signed-off-by: Raju P.L.S.S.S.N Signed-off-by: Naresh Malladi --- drivers/power/qcom/msm-pm.c | 45 +++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/power/qcom/msm-pm.c b/drivers/power/qcom/msm-pm.c index 42a44dfc5f5c..ed66f87810fb 100644 --- a/drivers/power/qcom/msm-pm.c +++ b/drivers/power/qcom/msm-pm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015,2017, 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,6 +87,7 @@ static long *msm_pc_debug_counters; static cpumask_t retention_cpus; static DEFINE_SPINLOCK(retention_lock); +static DEFINE_MUTEX(msm_pc_debug_mutex); static bool msm_pm_is_L1_writeback(void) { @@ -669,33 +670,48 @@ static ssize_t msm_pc_debug_counters_file_read(struct file *file, char __user *bufu, size_t count, loff_t *ppos) { struct msm_pc_debug_counters_buffer *data; + ssize_t ret; + mutex_lock(&msm_pc_debug_mutex); data = file->private_data; - if (!data) - return -EINVAL; + if (!data) { + ret = -EINVAL; + goto exit; + } - if (!bufu) - return -EINVAL; + if (!bufu) { + ret = -EINVAL; + goto exit; + } - if (!access_ok(VERIFY_WRITE, bufu, count)) - return -EFAULT; + if (!access_ok(VERIFY_WRITE, bufu, count)) { + ret = -EFAULT; + goto exit; + } if (*ppos >= data->len && data->len == 0) data->len = msm_pc_debug_counters_copy(data); - return simple_read_from_buffer(bufu, count, ppos, + ret = simple_read_from_buffer(bufu, count, ppos, data->buf, data->len); +exit: + mutex_unlock(&msm_pc_debug_mutex); + return ret; } static int msm_pc_debug_counters_file_open(struct inode *inode, struct file *file) { struct msm_pc_debug_counters_buffer *buf; + int ret = 0; + mutex_lock(&msm_pc_debug_mutex); - if (!inode->i_private) - return -EINVAL; + if (!inode->i_private) { + ret = -EINVAL; + goto exit; + } file->private_data = kzalloc( sizeof(struct msm_pc_debug_counters_buffer), GFP_KERNEL); @@ -704,19 +720,24 @@ static int msm_pc_debug_counters_file_open(struct inode *inode, pr_err("%s: ERROR kmalloc failed to allocate %zu bytes\n", __func__, sizeof(struct msm_pc_debug_counters_buffer)); - return -ENOMEM; + ret = -ENOMEM; + goto exit; } buf = file->private_data; buf->reg = (long *)inode->i_private; - return 0; +exit: + mutex_unlock(&msm_pc_debug_mutex); + return ret; } static int msm_pc_debug_counters_file_close(struct inode *inode, struct file *file) { + mutex_lock(&msm_pc_debug_mutex); kfree(file->private_data); + mutex_unlock(&msm_pc_debug_mutex); return 0; } From eceae9444c6c946c9f2b0cabfcc81b42dfd9509e Mon Sep 17 00:00:00 2001 From: Ankit Sharma Date: Thu, 19 Jan 2017 20:22:14 +0530 Subject: [PATCH 095/210] leds: qpnp-flash: Fix possible race condition in debugfs There is a possible race condition when debugfs files are concurrently accessed by multiple threads. Fix this. CRs-Fixed: 1109420, 1109326 Change-Id: I19e9107079ac8d039b12a37ae612727f824552d4 Signed-off-by: Ankit Sharma --- drivers/leds/leds-qpnp-flash.c | 82 ++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 03a38a94a0b8..6cc8e0986b91 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017, 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 @@ -218,6 +218,7 @@ struct flash_led_platform_data { }; struct qpnp_flash_led_buffer { + struct mutex debugfs_lock; /* Prevent thread concurrency */ size_t rpos; size_t wpos; size_t len; @@ -271,6 +272,7 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, log->rpos = 0; log->wpos = 0; log->len = logbufsize - sizeof(*log); + mutex_init(&log->debugfs_lock); led->log = log; led->buffer_cnt = 1; @@ -291,20 +293,26 @@ static int flash_led_dfs_close(struct inode *inode, struct file *file) if (led && led->log) { file->private_data = NULL; + mutex_destroy(&led->log->debugfs_lock); kfree(led->log); } return 0; } +#define MIN_BUFFER_WRITE_LEN 20 static int print_to_log(struct qpnp_flash_led_buffer *log, const char *fmt, ...) { va_list args; int cnt; - char *log_buf = &log->data[log->wpos]; + char *log_buf; size_t size = log->len - log->wpos; + if (size < MIN_BUFFER_WRITE_LEN) + return 0; /* not enough buffer left */ + + log_buf = &log->data[log->wpos]; va_start(args, fmt); cnt = vscnprintf(log_buf, size, fmt, args); va_end(args); @@ -318,12 +326,14 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, struct qpnp_flash_led *led = fp->private_data; struct qpnp_flash_led_buffer *log = led->log; u8 val; - int rc; + int rc = 0; size_t len; size_t ret; - if (log->rpos >= log->wpos && led->buffer_cnt == 0) - return 0; + mutex_lock(&log->debugfs_lock); + if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid, INT_LATCHED_STS(led->base), &val, 1); @@ -331,17 +341,17 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, dev_err(&led->spmi_dev->dev, "Unable to read from address %x, rc(%d)\n", INT_LATCHED_STS(led->base), rc); - return -EINVAL; + goto unlock_mutex; } led->buffer_cnt--; rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); if (rc == 0) - return rc; + goto unlock_mutex; rc = print_to_log(log, "0x%02X ", val); if (rc == 0) - return rc; + goto unlock_mutex; if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') log->data[log->wpos - 1] = '\n'; @@ -351,36 +361,43 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret) { pr_err("error copy register value to user\n"); - return -EFAULT; + rc = -EFAULT; + goto unlock_mutex; } len -= ret; *ppos += len; log->rpos += len; - return len; + rc = len; + +unlock_mutex: + mutex_unlock(&log->debugfs_lock); + return rc; } static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { struct qpnp_flash_led *led = fp->private_data; struct qpnp_flash_led_buffer *log = led->log; - int rc; + int rc = 0; size_t len; size_t ret; - if (log->rpos >= log->wpos && led->buffer_cnt == 0) - return 0; + mutex_lock(&log->debugfs_lock); + if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; led->buffer_cnt--; rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); if (rc == 0) - return rc; + goto unlock_mutex; rc = print_to_log(log, "0x%02X ", led->fault_reg); if (rc == 0) - return rc; + goto unlock_mutex; if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') log->data[log->wpos - 1] = '\n'; @@ -390,14 +407,19 @@ static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret) { pr_err("error copy register value to user\n"); - return -EFAULT; + rc = -EFAULT; + goto unlock_mutex; } len -= ret; *ppos += len; log->rpos += len; - return len; + rc = len; + +unlock_mutex: + mutex_unlock(&log->debugfs_lock); + return rc; } static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, @@ -410,9 +432,14 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, size_t ret = 0; struct qpnp_flash_led *led = file->private_data; - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + char *kbuf; + + mutex_lock(&led->log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (!ret) { @@ -441,6 +468,8 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&led->log->debugfs_lock); return ret; } @@ -454,9 +483,14 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, size_t ret = 0; struct qpnp_flash_led *led = file->private_data; - char *kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + char *kbuf; + + mutex_lock(&led->log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -484,6 +518,8 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&led->log->debugfs_lock); return ret; } From 833bace94bb2fa47ab1131f25b2fe0bd7ed2deb6 Mon Sep 17 00:00:00 2001 From: Adrian Salido Date: Thu, 1 Dec 2016 18:07:42 -0800 Subject: [PATCH 096/210] fs/proc/array.c: make safe access to group_leader As mentioned in commit 52ee2dfdd4f51cf422ea6a96a0846dc94244aa37 ("pids: refactor vnr/nr_ns helpers to make them safe"). *_nr_ns helpers used to be buggy. The commit addresses most of the helpers but is missing task_tgid_xxx() Without this protection there is a possible use after free reported by kasan instrumented kernel: ================================================================== BUG: KASAN: use-after-free in task_tgid_nr_ns+0x2c/0x44 at addr *** Read of size 8 by task cat/2472 CPU: 1 PID: 2472 Comm: cat Tainted: **** Hardware name: Google Tegra210 Smaug Rev 1,3+ (DT) Call trace: [] dump_backtrace+0x0/0x17c [] show_stack+0x18/0x24 [] dump_stack+0x94/0x100 [] kasan_report+0x308/0x554 [] __asan_load8+0x20/0x7c [] task_tgid_nr_ns+0x28/0x44 [] proc_pid_status+0x444/0x1080 [] proc_single_show+0x8c/0xdc [] seq_read+0x2e8/0x6f0 [] vfs_read+0xd8/0x1e0 [] SyS_read+0x68/0xd4 Accessing group_leader while holding rcu_lock and using the now safe helpers introduced in the commit mentioned, this race condition is addressed. Signed-off-by: Adrian Salido Change-Id: I4315217922dda375a30a3581c0c1740dda7b531b Bug: 31495866 Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-3.10.git Git-commit: 1d6d364ee174676a225a77dc7ca8dac887199718 Signed-off-by: Srinivasa Rao Kuppala --- fs/proc/array.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 09f0d9c374a3..6ed95802239d 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -168,16 +168,16 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, int g; struct fdtable *fdt = NULL; const struct cred *cred; - pid_t ppid, tpid; + pid_t ppid = 0, tpid = 0; + struct task_struct *leader = NULL; rcu_read_lock(); - ppid = pid_alive(p) ? - task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; - tpid = 0; if (pid_alive(p)) { struct task_struct *tracer = ptrace_parent(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); + ppid = task_tgid_nr_ns(rcu_dereference(p->real_parent), ns); + leader = p->group_leader; } cred = get_task_cred(p); seq_printf(m, @@ -189,7 +189,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), - task_tgid_nr_ns(p, ns), + leader ? task_pid_nr_ns(leader, ns) : 0, pid_nr_ns(pid, ns), ppid, tpid, from_kuid_munged(user_ns, cred->uid), From 7443381b6b86d701f529d44e694c40d53345b9f5 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 18 Nov 2016 10:44:16 -0800 Subject: [PATCH 097/210] BACKPORT: aio: mark AIO pseudo-fs noexec This ensures that do_mmap() won't implicitly make AIO memory mappings executable if the READ_IMPLIES_EXEC personality flag is set. Such behavior is problematic because the security_mmap_file LSM hook doesn't catch this case, potentially permitting an attacker to bypass a W^X policy enforced by SELinux. I have tested the patch on my machine. To test the behavior, compile and run this: #define _GNU_SOURCE #include #include #include #include #include #include #include int main(void) { personality(READ_IMPLIES_EXEC); aio_context_t ctx = 0; if (syscall(__NR_io_setup, 1, &ctx)) err(1, "io_setup"); char cmd[1000]; sprintf(cmd, "cat /proc/%d/maps | grep -F '/[aio]'", (int)getpid()); system(cmd); return 0; } In the output, "rw-s" is good, "rwxs" is bad. Signed-off-by: Jann Horn Signed-off-by: Linus Torvalds (cherry picked from commit 22f6b4d34fcf039c63a94e7670e0da24f8575a5a) Bug: 31711619 Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-3.10 Git-commit: I9f2872703bef240d6b82320c744529459bb076dc Change-Id: I9f2872703bef240d6b82320c744529459bb076dc Signed-off-by: Srinivasa Rao Kuppala --- fs/aio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/aio.c b/fs/aio.c index 9798d4edfd8f..0f2c38f29c4a 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -153,6 +154,9 @@ static int aio_setup_ring(struct kioctx *ctx) unsigned long size, populate; int nr_pages; + if (current->personality & READ_IMPLIES_EXEC) + return -EPERM; + /* Compensate for the ring buffer's head/tail overlap entry */ nr_events += 2; /* 1 is required, 2 for good luck */ From cc5831f111ae10676fde286470142696152bddbd Mon Sep 17 00:00:00 2001 From: Rajesh Bondugula Date: Tue, 7 Feb 2017 10:17:25 -0800 Subject: [PATCH 098/210] msm: camera: sensor: Validate destination step position dest_step_position is sent from userspace and is used in kernel to calculate the final DAC value. dest_step_position must be validated against total steps. Actuator will have an unexpected behavior if lens value is programed to actuator based on invalid dest_step_position. CRs-Fixed: 1102580 Change-Id: Idcd97043d3bd583d8577233d446a99d1829a4ee6 Signed-off-by: Rajesh Bondugula --- .../platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index 8c10d10890e5..e46ebe381fd4 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, 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 @@ -517,6 +517,12 @@ static int32_t msm_actuator_piezo_move_focus( return -EFAULT; } + if (dest_step_position > a_ctrl->total_steps) { + pr_err("Step pos greater than total steps = %d\n", + dest_step_position); + return -EFAULT; + } + a_ctrl->i2c_tbl_index = 0; a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl, (num_steps * From d8ee44e2546fa15df4760365106bb879c01597ea Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Mon, 13 Feb 2017 18:11:17 +0530 Subject: [PATCH 099/210] msm: camera: Validate size param before allocating memory When ever i2c write is initiated check size param for NULL and in case of sequence write check for maximun allowed size per i2c sequence write. CRs-Fixed: 779253 Change-Id: Ib9fa1d620e888ba8410b241d08895af993b6d960 Signed-off-by: VijayaKumar T M --- drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c index 8aebd780f7e9..1ec825524a28 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017 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 @@ -299,7 +299,8 @@ static int32_t msm_ois_config(struct msm_ois_ctrl_t *o_ctrl, break; } - if (!conf_array.size) { + if (!conf_array.size || + conf_array.size > I2C_SEQ_REG_DATA_MAX) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; From 6da39810612770dba6de8d1984a11fc8dc179d1d Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Tue, 31 Jan 2017 12:07:10 -0800 Subject: [PATCH 100/210] crypto: msm: check length before copying to buf in _debug_stats_read Make sure that `len` is not larger than `count` before copying data to userspace `buf` in _debug_stats_read(). Change-Id: Iafb7cfa3828653f8c28183c812797c3d9a183da1 Signed-off-by: Zhen Kong --- drivers/crypto/msm/ota_crypto.c | 6 +++--- drivers/crypto/msm/qcedev.c | 4 ++-- drivers/crypto/msm/qcrypto.c | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c index 9fc548d73e60..80e810dbeb64 100644 --- a/drivers/crypto/msm/ota_crypto.c +++ b/drivers/crypto/msm/ota_crypto.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, 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 @@ -880,8 +880,8 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, int len; len = _disp_stats(); - - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); return rc; diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index fd8f7e25ea42..2ccb7bab6994 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -2077,9 +2077,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcedev); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index b460cc20611f..f670d2d58c23 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -1,6 +1,6 @@ /* Qualcomm Crypto driver * - * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2017, 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 @@ -5149,9 +5149,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcrypto); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } From 39ee7a70359e1ede3edd3f5ed6138de6695bca50 Mon Sep 17 00:00:00 2001 From: Sahitya Tummala Date: Fri, 3 Feb 2017 13:24:19 +0530 Subject: [PATCH 101/210] uio: fix potential use after free issue when accessing debug_buffer The variable debug_buffer is a global variable which is allocated and free'd when open/close is called on debugfs file - "/sys/kernel/debug/rmt_storage/info". The current code doesn't have locks to handle concurrent accesses to the above file. This results into use after free issue when debug_buffer is accessed by two threads at the same time. Fix this by adding a mutex lock to protect this global variable. Change-Id: I6bc3f0ae2d7fca3ca9fe8561612f5863b6c3268a Signed-off-by: Sahitya Tummala --- drivers/uio/msm_sharedmem/sharedmem_qmi.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.c b/drivers/uio/msm_sharedmem/sharedmem_qmi.c index 3b04c582cb3b..cc8f7cd83421 100644 --- a/drivers/uio/msm_sharedmem/sharedmem_qmi.c +++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2017, 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 @@ -221,6 +221,7 @@ static int sharedmem_qmi_req_cb(struct qmi_handle *handle, void *conn_h, #define DEBUG_BUF_SIZE (2048) static char *debug_buffer; static u32 debug_data_size; +static struct mutex dbg_buf_lock; /* mutex for debug_buffer */ static ssize_t debug_read(struct file *file, char __user *buf, size_t count, loff_t *file_pos) @@ -276,21 +277,30 @@ static u32 fill_debug_info(char *buffer, u32 buffer_size) static int debug_open(struct inode *inode, struct file *file) { u32 buffer_size; - if (debug_buffer != NULL) + + mutex_lock(&dbg_buf_lock); + if (debug_buffer != NULL) { + mutex_unlock(&dbg_buf_lock); return -EBUSY; + } buffer_size = DEBUG_BUF_SIZE; debug_buffer = kzalloc(buffer_size, GFP_KERNEL); - if (debug_buffer == NULL) + if (debug_buffer == NULL) { + mutex_unlock(&dbg_buf_lock); return -ENOMEM; + } debug_data_size = fill_debug_info(debug_buffer, buffer_size); + mutex_unlock(&dbg_buf_lock); return 0; } static int debug_close(struct inode *inode, struct file *file) { + mutex_lock(&dbg_buf_lock); kfree(debug_buffer); debug_buffer = NULL; debug_data_size = 0; + mutex_unlock(&dbg_buf_lock); return 0; } @@ -321,6 +331,7 @@ static void debugfs_init(void) { struct dentry *f_ent; + mutex_init(&dbg_buf_lock); dir_ent = debugfs_create_dir("rmt_storage", NULL); if (IS_ERR(dir_ent)) { pr_err("Failed to create debug_fs directory\n"); @@ -349,6 +360,7 @@ static void debugfs_init(void) static void debugfs_exit(void) { debugfs_remove_recursive(dir_ent); + mutex_destroy(&dbg_buf_lock); } static void sharedmem_qmi_svc_recv_msg(struct work_struct *work) From 0dba52cf7955306c71fb76d16437d848c953e462 Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Fri, 23 Dec 2016 11:34:32 +0530 Subject: [PATCH 102/210] input: misc: fix heap overflow issue in hbtp_input.c Add the boundary check for ABS code before setting ABS params, to avoid heap overflow. Change-Id: I6aad9916c92d2f775632406374dbb803063148de Signed-off-by: Vevek Venkatesan --- drivers/input/misc/hbtp_input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c index 4c0e9a962668..e80afcf9add8 100644 --- a/drivers/input/misc/hbtp_input.c +++ b/drivers/input/misc/hbtp_input.c @@ -130,9 +130,13 @@ static int hbtp_input_create_input_dev(struct hbtp_input_absinfo *absinfo) input_mt_init_slots(input_dev, HBTP_MAX_FINGER, 0); for (i = 0; i <= ABS_MT_LAST - ABS_MT_FIRST; i++) { abs = absinfo + i; - if (abs->active) - input_set_abs_params(input_dev, abs->code, + if (abs->active) { + if (abs->code >= 0 && abs->code < ABS_CNT) + input_set_abs_params(input_dev, abs->code, abs->minimum, abs->maximum, 0, 0); + else + pr_err("%s: ABS code out of bound\n", __func__); + } } error = input_register_device(input_dev); From d03144e72cea14699b1b5cfa22e6e0b13e4446dd Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Mon, 23 Jan 2017 13:15:58 -0800 Subject: [PATCH 103/210] ASoC: msm: qdsp6v2: completely deallocate on cal block creation failure Completely deallocate the cal block if creation fails to ensure no memory leaks are present. CRs-Fixed: 1112751 Change-Id: I76916c8b3f7e8e9b864dc39dab96f7d330774473 Signed-off-by: Siena Richard --- sound/soc/msm/qdsp6v2/audio_cal_utils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c index 562e9a121d4a..0827a4d7d0cc 100644 --- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c +++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -567,7 +567,6 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, memset(cal_block, 0, sizeof(*cal_block)); INIT_LIST_HEAD(&cal_block->list); - list_add_tail(&cal_block->list, &cal_type->cal_blocks); cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle; if (basic_cal->cal_data.mem_handle > 0) { @@ -599,6 +598,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, goto err; } cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; + list_add_tail(&cal_block->list, &cal_type->cal_blocks); pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", __func__, cal_type->info.reg.cal_type, cal_block->buffer_number, @@ -608,6 +608,8 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, done: return cal_block; err: + kfree(cal_block->cal_info); + kfree(cal_block->client_info); kfree(cal_block); cal_block = NULL; return cal_block; From 01534097044ba2655e84cb8cbb08c0fea17c97da Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Thu, 26 Jan 2017 15:02:42 -0800 Subject: [PATCH 104/210] drivers: soc: add mutex to prevent response being processed twice Add a mutex to prevent two threads from processing the same response at the same time. This ensures responses are processed completely and sequentially. CRs-Fixed: 1116015 Change-Id: Id2ef32edb939f8af2850b54bd6f6f447939c0732 Signed-off-by: Siena Richard --- drivers/soc/qcom/qdsp6v2/voice_svc.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index 50dd9256b270..10f71b85a15b 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -42,6 +42,12 @@ struct voice_svc_prvt { struct list_head response_queue; wait_queue_head_t response_wait; spinlock_t response_lock; + /* + * This mutex ensures responses are processed in sequential order and + * that no two threads access and free the same response at the same + * time. + */ + struct mutex response_mutex_lock; }; struct apr_data { @@ -467,6 +473,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, goto done; } + mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); if (list_empty(&prtd->response_queue)) { @@ -480,7 +487,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_debug("%s: Read timeout\n", __func__); ret = -ETIMEDOUT; - goto done; + goto unlock; } else if (ret > 0 && !list_empty(&prtd->response_queue)) { pr_debug("%s: Interrupt recieved for response\n", __func__); @@ -488,7 +495,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_debug("%s: Interrupted by SIGNAL %d\n", __func__, ret); - goto done; + goto unlock; } spin_lock_irqsave(&prtd->response_lock, spin_flags); @@ -507,7 +514,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, __func__, count, size); ret = -ENOMEM; - goto done; + goto unlock; } if (!access_ok(VERIFY_WRITE, arg, size)) { @@ -515,7 +522,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, __func__); ret = -EPERM; - goto done; + goto unlock; } ret = copy_to_user(arg, &resp->resp, @@ -525,7 +532,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_err("%s: copy_to_user failed %d\n", __func__, ret); ret = -EPERM; - goto done; + goto unlock; } spin_lock_irqsave(&prtd->response_lock, spin_flags); @@ -539,6 +546,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, ret = count; +unlock: + mutex_unlock(&prtd->response_mutex_lock); done: return ret; } @@ -594,6 +603,7 @@ static int voice_svc_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&prtd->response_queue); init_waitqueue_head(&prtd->response_wait); spin_lock_init(&prtd->response_lock); + mutex_init(&prtd->response_mutex_lock); file->private_data = (void *)prtd; /* Current APR implementation doesn't support session based @@ -644,6 +654,7 @@ static int voice_svc_release(struct inode *inode, struct file *file) pr_err("%s: Failed to dereg MVM %d\n", __func__, ret); } + mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); while (!list_empty(&prtd->response_queue)) { @@ -657,6 +668,9 @@ static int voice_svc_release(struct inode *inode, struct file *file) } spin_unlock_irqrestore(&prtd->response_lock, spin_flags); + mutex_unlock(&prtd->response_mutex_lock); + + mutex_destroy(&prtd->response_mutex_lock); kfree(file->private_data); file->private_data = NULL; From d417c3c0ebd798797e6556109f684e05fe604f5d Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Fri, 23 Dec 2016 11:34:32 +0530 Subject: [PATCH 105/210] input: misc: fix heap overflow issue in hbtp_input.c Add the boundary check for ABS code before setting ABS params, to avoid heap overflow. Change-Id: I6aad9916c92d2f775632406374dbb803063148de Signed-off-by: Vevek Venkatesan --- drivers/input/misc/hbtp_input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c index 4c0e9a962668..e80afcf9add8 100644 --- a/drivers/input/misc/hbtp_input.c +++ b/drivers/input/misc/hbtp_input.c @@ -130,9 +130,13 @@ static int hbtp_input_create_input_dev(struct hbtp_input_absinfo *absinfo) input_mt_init_slots(input_dev, HBTP_MAX_FINGER, 0); for (i = 0; i <= ABS_MT_LAST - ABS_MT_FIRST; i++) { abs = absinfo + i; - if (abs->active) - input_set_abs_params(input_dev, abs->code, + if (abs->active) { + if (abs->code >= 0 && abs->code < ABS_CNT) + input_set_abs_params(input_dev, abs->code, abs->minimum, abs->maximum, 0, 0); + else + pr_err("%s: ABS code out of bound\n", __func__); + } } error = input_register_device(input_dev); From 42b0b7e16d098d25999be3cbd4f0c098b7eb43b3 Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 106/210] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; From 05802e312406f6b2b1456a897ec370b39817adf6 Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Mon, 27 Feb 2017 12:27:35 +0530 Subject: [PATCH 107/210] msm: camera: use common macro to check sensor array size sensors ov2685 and ov2685_svc3b4035 uses CCI defined macro which is 8K bytes. Lets use the I2C define which is also 8K size across all the sensor drivers. CRs-Fixed: 779253 Change-Id: I75e333311394375c53ac0821d814c1b37d74e1ba Signed-off-by: VijayaKumar T M --- drivers/media/platform/msm/camera_v2/sensor/ov2685.c | 7 +++---- .../media/platform/msm/camera_v2/sensor/ov2685_scv3b4035.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov2685.c b/drivers/media/platform/msm/camera_v2/sensor/ov2685.c index fa3f36a443f4..f592f6a7434f 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ov2685.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ov2685.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2017 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 @@ -19,7 +19,6 @@ #define OV2685_SENSOR_NAME "ov2685" #define PLATFORM_DRIVER_NAME "msm_camera_ov2685" #define ov2685_obj ov2685_##obj -#define CCI_I2C_MAX_WRITE 8192 #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) @@ -818,7 +817,7 @@ int32_t ov2685_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, } if (!conf_array.size || - conf_array.size > CCI_I2C_MAX_WRITE) { + conf_array.size > I2C_REG_DATA_MAX) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; @@ -1100,7 +1099,7 @@ int32_t ov2685_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl, conf_array.reg_setting = compat_ptr(conf_array32.reg_setting); if (!conf_array.size || - conf_array.size > CCI_I2C_MAX_WRITE) { + conf_array.size > I2C_REG_DATA_MAX) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov2685_scv3b4035.c b/drivers/media/platform/msm/camera_v2/sensor/ov2685_scv3b4035.c index 25a81ad4cbf7..ed99707c9a14 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ov2685_scv3b4035.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ov2685_scv3b4035.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2017 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 @@ -19,7 +19,6 @@ #define OV2685_SCV3B4035_SENSOR_NAME "ov2685_scv3b4035" #define PLATFORM_DRIVER_NAME "msm_camera_ov2685_scv3b4035" #define ov2685_scv3b4035_obj ov2685_scv3b4035_##obj -#define CCI_I2C_MAX_WRITE 8192 #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) @@ -822,7 +821,7 @@ int32_t ov2685_scv3b4035_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, } if (!conf_array.size || - conf_array.size > CCI_I2C_MAX_WRITE) { + conf_array.size > I2C_REG_DATA_MAX) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; @@ -1104,7 +1103,7 @@ int32_t ov2685_scv3b4035_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl, conf_array.reg_setting = compat_ptr(conf_array32.reg_setting); if (!conf_array.size || - conf_array.size > CCI_I2C_MAX_WRITE) { + conf_array.size > I2C_REG_DATA_MAX) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; From 1cc2c28c97fa9367b22bbca302db45780fc87469 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 16 Feb 2017 11:39:44 +0530 Subject: [PATCH 108/210] input: touchscreen: remove msg21xx mstar touch driver Remove msg21xx mstar touch driver from the kernel code as it has never been used in any of the recent platforms. Change-Id: I0ac1f93d9736c402732b6c4a8d22b1bf3500e4c4 Signed-off-by: Vevek Venkatesan Signed-off-by: Shantanu Jain Signed-off-by: Yasir Malik --- .../bindings/input/touchscreen/msg21xx-ts.txt | 71 - drivers/input/touchscreen/Kconfig | 11 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/msg21xx_ts.c | 2162 ----------------- 4 files changed, 2245 deletions(-) delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt delete mode 100644 drivers/input/touchscreen/msg21xx_ts.c diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt deleted file mode 100644 index 0d6289779d8c..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt +++ /dev/null @@ -1,71 +0,0 @@ -Mstar touch controller - -The mstar controller is connected to host processor -via i2c. The controller generates interrupts when the -user touches the panel. The host controller is expected -to read the touch coordinates over i2c and pass the coordinates -to the rest of the system. - -Required properties: - - - compatible : should be "mstar,msg21xx" - - reg : i2c slave address of the device - - interrupt-parent : parent of interrupt - - interrupts : touch sample interrupt to indicate presense or release - of fingers on the panel. - - vdd-supply : Power supply needed to power up the device - - vcc_i2c-supply : Power source required to power up i2c bus - - mstar,irq-gpio : irq gpio which is to provide interrupts to host, - same as "interrupts" node. It will also - contain active low or active high information. - - mstar,reset-gpio : reset gpio to control the reset of chip - - mstar,display-coords : display coords in pixels. It is a four - tuple consisting of min x, min y, max x and - max y values - - pinctrl-names : This should be defined if a target uses pinctrl framework. - See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt. - Specify the names of the configs that pinctrl can install in driver. - Following are the pinctrl configs that can be installed: - "pmx_ts_active" : Active configuration of pins, this should specify active - config defined in pin groups of interrupt and reset gpio. - "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep - config defined in pin groups of interrupt and reset gpio. - "pmx_ts_release" : Release configuration of pins, this should specify - release config defined in pin groups of interrupt and reset gpio. - - mstar,num-max-touches: It defines the maximum number of touch supported by the controller. - - mstar,hard-reset-delay-ms : hard reset delay in ms - - mstar,post-hard-reset-delay-ms : post hard reset delay in ms - -Optional properties: - - - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes. - - mstar,panel-coords : panel coords for the chip in pixels. - It is a four tuple consisting of min x, - min y, max x and max y values - - mstar,ic-type : It defines the ic-type of the controller. Values are as folows: - 1 -> msg2133. - 2 -> msg21xxA. - 3 -> msg26xxM. - -Example: - i2c@78b9000 { /* BLSP1 QUP5 */ - mstar@26 { - compatible = "mstar,msg21xx"; - reg = <0x26>; - interrupt-parent = <&msm_gpio>; - interrupts = <13 0x2008>; - mstar,irq-gpio = <&msm_gpio 13 0x00000001>; - mstar,reset-gpio = <&msm_gpio 12 0x0>; - vdd-supply = <&pm8916_l17>; - vcc_i2c-supply = <&pm8916_l6>; - mstar,display-coords = <0 0 480 854>; - pinctrl-names = "pmx_ts_active","pmx_ts_suspend"; - pinctrl-0 = <&ts_int_active &ts_reset_active>; - pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; - mstar,button-map = <172 139 158>; - mstar,ic-type = <2>; - mstar,num_max_touches = <2>; - mstar,hard-reset-delay-ms = <100>; - mstar,post-hard-reset-delay-ms = <100>; - }; - }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index ad2dd3c53803..b2917ac46935 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -955,17 +955,6 @@ config TOUCHSCREEN_FT5X06_GESTURE If unsure, say N. -config TOUCHSCREEN_MSTAR21XX - tristate "mstar touchscreens" - depends on I2C - help - Say Y here if you have a mstar touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called msg21xx_ts. - config TOUCHSCREEN_GEN_VKEYS tristate "Touchscreen Virtual Keys Driver" help diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index d7603acb2f8a..f3618cc20b3c 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -76,7 +76,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_FT5X06) += ft5x06_ts.o -obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c deleted file mode 100644 index 0b72cac51840..000000000000 --- a/drivers/input/touchscreen/msg21xx_ts.c +++ /dev/null @@ -1,2162 +0,0 @@ -/* - * MStar MSG21XX touchscreen driver - * - * Copyright (c) 2006-2012 MStar Semiconductor, Inc. - * - * Copyright (C) 2012 Bruce Ding - * - * Copyright (c) 2014, 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 as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_FB) -#include -#include -#endif -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR -#include -#endif - -/* Constant Value & Variable Definition*/ - -#define MSTAR_VTG_MIN_UV 2800000 -#define MSTAR_VTG_MAX_UV 3300000 -#define MSTAR_I2C_VTG_MIN_UV 1800000 -#define MSTAR_I2C_VTG_MAX_UV 1800000 - -#define MAX_BUTTONS 4 -#define FT_COORDS_ARR_SIZE 4 -#define MSTAR_FW_NAME_MAX_LEN 50 - -#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E -#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC -#define MSTAR_INIT_SW_ID 0x7FF -#define MSTAR_DEBUG_DIR_NAME "ts_debug" - -#define MSG_FW_FILE_MAJOR_VERSION(x) \ - (((x)->data[0x7f4f] << 8) + ((x)->data[0x7f4e])) - -#define MSG_FW_FILE_MINOR_VERSION(x) \ - (((x)->data[0x7f51] << 8) + ((x)->data[0x7f50])) - -/* - * Note. - * Please do not change the below setting. - */ -#define TPD_WIDTH (2048) -#define TPD_HEIGHT (2048) - -#define PINCTRL_STATE_ACTIVE "pmx_ts_active" -#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" -#define PINCTRL_STATE_RELEASE "pmx_ts_release" - -#define SLAVE_I2C_ID_DBBUS (0xC4>>1) - -#define DEMO_MODE_PACKET_LENGTH (8) - -#define TP_PRINT - -/*store the frimware binary data*/ -static unsigned char fw_bin_data[94][1024]; -static unsigned int crc32_table[256]; - -static unsigned short fw_file_major, fw_file_minor; -static unsigned short main_sw_id = MSTAR_INIT_SW_ID; -static unsigned short info_sw_id = MSTAR_INIT_SW_ID; -static unsigned int bin_conf_crc32; - -struct msg21xx_ts_platform_data { - const char *name; - char fw_name[MSTAR_FW_NAME_MAX_LEN]; - u8 fw_version_major; - u8 fw_version_minor; - u32 irq_gpio; - u32 irq_gpio_flags; - u32 reset_gpio; - u32 reset_gpio_flags; - u32 x_max; - u32 y_max; - u32 x_min; - u32 y_min; - u32 panel_minx; - u32 panel_miny; - u32 panel_maxx; - u32 panel_maxy; - u32 num_max_touches; - u8 ic_type; - u32 button_map[MAX_BUTTONS]; - u32 num_buttons; - u32 hard_reset_delay_ms; - u32 post_hard_reset_delay_ms; - bool updating_fw; -}; - -/* Touch Data Type Definition */ -struct touchPoint_t { - unsigned short x; - unsigned short y; -}; - -struct touchInfo_t { - struct touchPoint_t *point; - unsigned char count; - unsigned char keycode; -}; - -struct msg21xx_ts_data { - struct i2c_client *client; - struct input_dev *input_dev; - struct msg21xx_ts_platform_data *pdata; - struct regulator *vdd; - struct regulator *vcc_i2c; - bool suspended; -#if defined(CONFIG_FB) - struct notifier_block fb_notif; -#endif - struct pinctrl *ts_pinctrl; - struct pinctrl_state *pinctrl_state_active; - struct pinctrl_state *pinctrl_state_suspend; - struct pinctrl_state *pinctrl_state_release; - struct mutex ts_mutex; - struct touchInfo_t info; -}; - -#if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -#endif - -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR -static unsigned char bEnableTpProximity; -static unsigned char bFaceClosingTp; -#endif - -#ifdef TP_PRINT -static int tp_print_proc_read(struct msg21xx_ts_data *ts_data); -static void tp_print_create_entry(struct msg21xx_ts_data *ts_data); -#endif - -static void _ReadBinConfig(struct msg21xx_ts_data *ts_data); -static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data); - -static struct mutex msg21xx_mutex; - -enum EMEM_TYPE_t { - EMEM_ALL = 0, - EMEM_MAIN, - EMEM_INFO, -}; - -/* Function Definition */ - -static unsigned int _CRC_doReflect(unsigned int ref, signed char ch) -{ - unsigned int value = 0; - unsigned int i = 0; - - for (i = 1; i < (ch + 1); i++) { - if (ref & 1) - value |= 1 << (ch - i); - ref >>= 1; - } - - return value; -} - -static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC) -{ - unsigned int ulCRC = prevCRC; - - ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text]; - - return ulCRC; -} - -static void _CRC_initTable(void) -{ - unsigned int magic_number = 0x04c11db7; - unsigned int i, j; - - for (i = 0; i <= 0xFF; i++) { - crc32_table[i] = _CRC_doReflect(i, 8) << 24; - for (j = 0; j < 8; j++) - crc32_table[i] = (crc32_table[i] << 1) ^ - (crc32_table[i] & (0x80000000L) ? - magic_number : 0); - crc32_table[i] = _CRC_doReflect(crc32_table[i], 32); - } -} - -static void msg21xx_reset_hw(struct msg21xx_ts_platform_data *pdata) -{ - gpio_direction_output(pdata->reset_gpio, 1); - gpio_set_value_cansleep(pdata->reset_gpio, 0); - /* Note that the RST must be in LOW 10ms at least */ - usleep(pdata->hard_reset_delay_ms * 1000); - gpio_set_value_cansleep(pdata->reset_gpio, 1); - /* Enable the interrupt service thread/routine for INT after 50ms */ - usleep(pdata->post_hard_reset_delay_ms * 1000); -} - -static int read_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr, - unsigned char *buf, unsigned short size) -{ - int rc = 0; - struct i2c_msg msgs[] = { - { - .addr = addr, - .flags = I2C_M_RD, /* read flag */ - .len = size, - .buf = buf, - }, - }; - - /* If everything went ok (i.e. 1 msg transmitted), return #bytes - transmitted, else error code. */ - if (ts_data->client != NULL) { - rc = i2c_transfer(ts_data->client->adapter, msgs, 1); - if (rc < 0) - dev_err(&ts_data->client->dev, - "%s error %d\n", __func__, rc); - } else { - dev_err(&ts_data->client->dev, "ts_data->client is NULL\n"); - } - - return rc; -} - -static int write_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr, - unsigned char *buf, unsigned short size) -{ - int rc = 0; - struct i2c_msg msgs[] = { - { - .addr = addr, - /* - * if read flag is undefined, - * then it means write flag. - */ - .flags = 0, - .len = size, - .buf = buf, - }, - }; - - /* - * If everything went ok (i.e. 1 msg transmitted), return #bytes - * transmitted, else error code. - */ - if (ts_data->client != NULL) { - rc = i2c_transfer(ts_data->client->adapter, msgs, 1); - if (rc < 0) - dev_err(&ts_data->client->dev, - "%s error %d\n", __func__, rc); - } else { - dev_err(&ts_data->client->dev, "ts_data->client is NULL\n"); - } - - return rc; -} - -static unsigned short read_reg(struct msg21xx_ts_data *ts_data, - unsigned char bank, unsigned char addr) -{ - unsigned char tx_data[3] = {0x10, bank, addr}; - unsigned char rx_data[2] = {0}; - - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data)); - read_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, rx_data, sizeof(rx_data)); - - return rx_data[1] << 8 | rx_data[0]; -} - -static void write_reg(struct msg21xx_ts_data *ts_data, unsigned char bank, - unsigned char addr, - unsigned short data) -{ - unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8}; - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data)); -} - -static void write_reg_8bit(struct msg21xx_ts_data *ts_data, unsigned char bank, - unsigned char addr, - unsigned char data) -{ - unsigned char tx_data[4] = {0x10, bank, addr, data}; - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data)); -} - -static void dbbusDWIICEnterSerialDebugMode(struct msg21xx_ts_data *ts_data) -{ - unsigned char data[5]; - - /* Enter the Serial Debug Mode */ - data[0] = 0x53; - data[1] = 0x45; - data[2] = 0x52; - data[3] = 0x44; - data[4] = 0x42; - - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); -} - -static void dbbusDWIICStopMCU(struct msg21xx_ts_data *ts_data) -{ - unsigned char data[1]; - - /* Stop the MCU */ - data[0] = 0x37; - - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); -} - -static void dbbusDWIICIICUseBus(struct msg21xx_ts_data *ts_data) -{ - unsigned char data[1]; - - /* IIC Use Bus */ - data[0] = 0x35; - - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); -} - -static void dbbusDWIICIICReshape(struct msg21xx_ts_data *ts_data) -{ - unsigned char data[1]; - - /* IIC Re-shape */ - data[0] = 0x71; - - write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); -} - -static unsigned char msg21xx_get_ic_type(struct msg21xx_ts_data *ts_data) -{ - unsigned char ic_type = 0; - unsigned char bank; - unsigned char addr; - - msg21xx_reset_hw(ts_data->pdata); - dbbusDWIICEnterSerialDebugMode(ts_data); - dbbusDWIICStopMCU(ts_data); - dbbusDWIICIICUseBus(ts_data); - dbbusDWIICIICReshape(ts_data); - msleep(300); - - /* stop mcu */ - write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01); - /* disable watch dog */ - write_reg(ts_data, 0x3C, 0x60, 0xAA55); - /* get ic type */ - bank = MSTAR_CHIPTOP_REGISTER_BANK; - addr = MSTAR_CHIPTOP_REGISTER_ICTYPE; - ic_type = (0xff)&(read_reg(ts_data, bank, addr)); - - if (ic_type != ts_data->pdata->ic_type) - ic_type = 0; - - msg21xx_reset_hw(ts_data->pdata); - - return ic_type; -} - -static int msg21xx_read_firmware_id(struct msg21xx_ts_data *ts_data) -{ - unsigned char command[3] = { 0x53, 0x00, 0x2A}; - unsigned char response[4] = { 0 }; - - mutex_lock(&msg21xx_mutex); - write_i2c_seq(ts_data, ts_data->client->addr, command, sizeof(command)); - read_i2c_seq(ts_data, ts_data->client->addr, response, - sizeof(response)); - mutex_unlock(&msg21xx_mutex); - ts_data->pdata->fw_version_major = (response[1]<<8) + response[0]; - ts_data->pdata->fw_version_minor = (response[3]<<8) + response[2]; - - dev_info(&ts_data->client->dev, "major num = %d, minor num = %d\n", - ts_data->pdata->fw_version_major, - ts_data->pdata->fw_version_minor); - - return 0; -} - -static int firmware_erase_c33(struct msg21xx_ts_data *ts_data, - enum EMEM_TYPE_t emem_type) -{ - /* stop mcu */ - write_reg(ts_data, 0x0F, 0xE6, 0x0001); - - /* disable watch dog */ - write_reg_8bit(ts_data, 0x3C, 0x60, 0x55); - write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA); - - /* set PROGRAM password */ - write_reg_8bit(ts_data, 0x16, 0x1A, 0xBA); - write_reg_8bit(ts_data, 0x16, 0x1B, 0xAB); - - write_reg_8bit(ts_data, 0x16, 0x18, 0x80); - - if (emem_type == EMEM_ALL) - write_reg_8bit(ts_data, 0x16, 0x08, 0x10); - - write_reg_8bit(ts_data, 0x16, 0x18, 0x40); - msleep(20); - - /* clear pce */ - write_reg_8bit(ts_data, 0x16, 0x18, 0x80); - - /* erase trigger */ - if (emem_type == EMEM_MAIN) - write_reg_8bit(ts_data, 0x16, 0x0E, 0x04); /* erase main */ - else - write_reg_8bit(ts_data, 0x16, 0x0E, 0x08); /* erase all block */ - - return 0; -} - -static ssize_t firmware_update_c33(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size, - enum EMEM_TYPE_t emem_type, - bool isForce) { - unsigned int i, j; - unsigned int crc_main, crc_main_tp; - unsigned int crc_info, crc_info_tp; - unsigned short reg_data = 0; - int update_pass = 1; - bool fw_upgrade = false; - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - crc_main = 0xffffffff; - crc_info = 0xffffffff; - - msg21xx_reset_hw(ts_data->pdata); - - msg21xx_read_firmware_id(ts_data); - _ReadBinConfig(ts_data); - if ((main_sw_id == info_sw_id) && - (_CalMainCRC32(ts_data) == bin_conf_crc32) && - (fw_file_major == ts_data->pdata->fw_version_major) && - (fw_file_minor > ts_data->pdata->fw_version_minor)) { - fw_upgrade = true; - } - - if (!fw_upgrade && !isForce) { - dev_dbg(dev, "no need to update\n"); - msg21xx_reset_hw(ts_data->pdata); - return size; - } - msg21xx_reset_hw(ts_data->pdata); - msleep(300); - - dbbusDWIICEnterSerialDebugMode(ts_data); - dbbusDWIICStopMCU(ts_data); - dbbusDWIICIICUseBus(ts_data); - dbbusDWIICIICReshape(ts_data); - msleep(300); - - /* erase main */ - firmware_erase_c33(ts_data, EMEM_MAIN); - msleep(1000); - - msg21xx_reset_hw(ts_data->pdata); - dbbusDWIICEnterSerialDebugMode(ts_data); - dbbusDWIICStopMCU(ts_data); - dbbusDWIICIICUseBus(ts_data); - dbbusDWIICIICReshape(ts_data); - msleep(300); - - /* - * Program - */ - - /* polling 0x3CE4 is 0x1C70 */ - if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { - do { - reg_data = read_reg(ts_data, 0x3C, 0xE4); - } while (reg_data != 0x1C70); - } - - switch (emem_type) { - case EMEM_ALL: - write_reg(ts_data, 0x3C, 0xE4, 0xE38F); /* for all-blocks */ - break; - case EMEM_MAIN: - write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for main block */ - break; - case EMEM_INFO: - write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for info block */ - - write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01); - - write_reg_8bit(ts_data, 0x3C, 0xE4, 0xC5); - write_reg_8bit(ts_data, 0x3C, 0xE5, 0x78); - - write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, - 0x04, 0x9F); - write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, - 0x05, 0x82); - - write_reg_8bit(ts_data, 0x0F, 0xE6, 0x00); - msleep(100); - break; - } - - /* polling 0x3CE4 is 0x2F43 */ - do { - reg_data = read_reg(ts_data, 0x3C, 0xE4); - } while (reg_data != 0x2F43); - - /* calculate CRC 32 */ - _CRC_initTable(); - - /* total 32 KB : 2 byte per R/W */ - for (i = 0; i < 32; i++) { - if (i == 31) { - fw_bin_data[i][1014] = 0x5A; - fw_bin_data[i][1015] = 0xA5; - - for (j = 0; j < 1016; j++) - crc_main = _CRC_getValue(fw_bin_data[i][j], - crc_main); - } else { - for (j = 0; j < 1024; j++) - crc_main = _CRC_getValue(fw_bin_data[i][j], - crc_main); - } - - for (j = 0; j < 8; j++) - write_i2c_seq(ts_data, ts_data->client->addr, - &fw_bin_data[i][j * 128], 128); - msleep(100); - - /* polling 0x3CE4 is 0xD0BC */ - do { - reg_data = read_reg(ts_data, 0x3C, 0xE4); - } while (reg_data != 0xD0BC); - - write_reg(ts_data, 0x3C, 0xE4, 0x2F43); - } - - if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { - /* write file done and check crc */ - write_reg(ts_data, 0x3C, 0xE4, 0x1380); - } - msleep(20); - - if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { - /* polling 0x3CE4 is 0x9432 */ - do { - reg_data = read_reg(ts_data, 0x3C, 0xE4); - } while (reg_data != 0x9432); - } - - crc_main = crc_main ^ 0xffffffff; - crc_info = crc_info ^ 0xffffffff; - - if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { - /* CRC Main from TP */ - crc_main_tp = read_reg(ts_data, 0x3C, 0x80); - crc_main_tp = (crc_main_tp << 16) | - read_reg(ts_data, 0x3C, 0x82); - - /* CRC Info from TP */ - crc_info_tp = read_reg(ts_data, 0x3C, 0xA0); - crc_info_tp = (crc_info_tp << 16) | - read_reg(ts_data, 0x3C, 0xA2); - } - - update_pass = 1; - if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { - if (crc_main_tp != crc_main) - update_pass = 0; - } - - if (!update_pass) { - dev_err(dev, "update_C33 failed\n"); - msg21xx_reset_hw(ts_data->pdata); - return 0; - } - - dev_dbg(dev, "update_C33 OK\n"); - msg21xx_reset_hw(ts_data->pdata); - return size; -} - -static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data) -{ - unsigned int ret = 0; - unsigned short reg_data = 0; - - msg21xx_reset_hw(ts_data->pdata); - - dbbusDWIICEnterSerialDebugMode(ts_data); - dbbusDWIICStopMCU(ts_data); - dbbusDWIICIICUseBus(ts_data); - dbbusDWIICIICReshape(ts_data); - msleep(100); - - /* Stop MCU */ - write_reg(ts_data, 0x0F, 0xE6, 0x0001); - - /* Stop Watchdog */ - write_reg_8bit(ts_data, 0x3C, 0x60, 0x55); - write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA); - - /* cmd */ - write_reg(ts_data, 0x3C, 0xE4, 0xDF4C); - write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60); - /* TP SW reset */ - write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F); - - /* MCU run */ - write_reg(ts_data, 0x0F, 0xE6, 0x0000); - - /* polling 0x3CE4 */ - do { - reg_data = read_reg(ts_data, 0x3C, 0xE4); - } while (reg_data != 0x9432); - - /* Cal CRC Main from TP */ - ret = read_reg(ts_data, 0x3C, 0x80); - ret = (ret << 16) | read_reg(ts_data, 0x3C, 0x82); - - dev_dbg(&ts_data->client->dev, - "[21xxA]:Current main crc32=0x%x\n", ret); - return ret; -} - -static void _ReadBinConfig(struct msg21xx_ts_data *ts_data) -{ - unsigned char dbbus_tx_data[5] = {0}; - unsigned char dbbus_rx_data[4] = {0}; - unsigned short reg_data = 0; - - msg21xx_reset_hw(ts_data->pdata); - - dbbusDWIICEnterSerialDebugMode(ts_data); - dbbusDWIICStopMCU(ts_data); - dbbusDWIICIICUseBus(ts_data); - dbbusDWIICIICReshape(ts_data); - msleep(100); - - /* Stop MCU */ - write_reg(ts_data, 0x0F, 0xE6, 0x0001); - - /* Stop Watchdog */ - write_reg_8bit(ts_data, 0x3C, 0x60, 0x55); - write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA); - - /* cmd */ - write_reg(ts_data, 0x3C, 0xE4, 0xA4AB); - write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60); - - /* TP SW reset */ - write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F); - - /* MCU run */ - write_reg(ts_data, 0x0F, 0xE6, 0x0000); - - /* polling 0x3CE4 */ - do { - reg_data = read_reg(ts_data, 0x3C, 0xE4); - } while (reg_data != 0x5B58); - - dbbus_tx_data[0] = 0x72; - dbbus_tx_data[1] = 0x7F; - dbbus_tx_data[2] = 0x55; - dbbus_tx_data[3] = 0x00; - dbbus_tx_data[4] = 0x04; - write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5); - read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); - if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39) - && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39) - && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) { - main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 + - (dbbus_rx_data[1] - 0x30) * 10 + - (dbbus_rx_data[2] - 0x30); - } - - dbbus_tx_data[0] = 0x72; - dbbus_tx_data[1] = 0x7F; - dbbus_tx_data[2] = 0xFC; - dbbus_tx_data[3] = 0x00; - dbbus_tx_data[4] = 0x04; - write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5); - read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); - bin_conf_crc32 = (dbbus_rx_data[0] << 24) | - (dbbus_rx_data[1] << 16) | - (dbbus_rx_data[2] << 8) | - (dbbus_rx_data[3]); - - dbbus_tx_data[0] = 0x72; - dbbus_tx_data[1] = 0x83; - dbbus_tx_data[2] = 0x00; - dbbus_tx_data[3] = 0x00; - dbbus_tx_data[4] = 0x04; - write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5); - read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); - if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39) - && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39) - && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) { - info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 + - (dbbus_rx_data[1] - 0x30) * 10 + - (dbbus_rx_data[2] - 0x30); - } - - dev_dbg(&ts_data->client->dev, - "[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32 = 0x%x\n", - main_sw_id, info_sw_id, bin_conf_crc32); -} - -static ssize_t firmware_update_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - return snprintf(buf, 3, "%d\n", ts_data->pdata->updating_fw); -} - -static ssize_t firmware_update_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size) -{ - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - ts_data->pdata->updating_fw = true; - disable_irq(ts_data->client->irq); - - size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false); - - enable_irq(ts_data->client->irq); - ts_data->pdata->updating_fw = false; - - return size; -} - -static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR), - firmware_update_show, - firmware_update_store); - -static int prepare_fw_data(struct device *dev) -{ - int count; - int i; - int ret; - const struct firmware *fw = NULL; - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - ret = request_firmware(&fw, ts_data->pdata->fw_name, dev); - if (ret < 0) { - dev_err(dev, "Request firmware failed - %s (%d)\n", - ts_data->pdata->fw_name, ret); - return ret; - } - - count = fw->size / 1024; - - for (i = 0; i < count; i++) - memcpy(fw_bin_data[i], fw->data + (i * 1024), 1024); - - fw_file_major = MSG_FW_FILE_MAJOR_VERSION(fw); - fw_file_minor = MSG_FW_FILE_MINOR_VERSION(fw); - dev_dbg(dev, "New firmware: %d.%d", - fw_file_major, fw_file_minor); - - return fw->size; -} - -static ssize_t firmware_update_smart_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size) -{ - int ret; - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - ret = prepare_fw_data(dev); - if (ret < 0) { - dev_err(dev, "Request firmware failed -(%d)\n", ret); - return ret; - } - ts_data->pdata->updating_fw = true; - disable_irq(ts_data->client->irq); - - ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false); - if (ret == 0) - dev_err(dev, "firmware_update_c33 ret = %d\n", ret); - - enable_irq(ts_data->client->irq); - ts_data->pdata->updating_fw = false; - - return ret; -} - -static ssize_t firmware_force_update_smart_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size) -{ - int ret; - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - ret = prepare_fw_data(dev); - if (ret < 0) { - dev_err(dev, "Request firmware failed -(%d)\n", ret); - return ret; - } - ts_data->pdata->updating_fw = true; - disable_irq(ts_data->client->irq); - - ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true); - if (ret == 0) - dev_err(dev, "firmware_update_c33 et = %d\n", ret); - - enable_irq(ts_data->client->irq); - ts_data->pdata->updating_fw = false; - - return ret; -} - -static DEVICE_ATTR(update_fw, (S_IRUGO | S_IWUSR), - firmware_update_show, - firmware_update_smart_store); - -static DEVICE_ATTR(force_update_fw, (S_IRUGO | S_IWUSR), - firmware_update_show, - firmware_force_update_smart_store); - -static ssize_t firmware_version_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - msg21xx_read_firmware_id(ts_data); - return snprintf(buf, sizeof(char) * 8, "%03d%03d\n", - ts_data->pdata->fw_version_major, - ts_data->pdata->fw_version_minor); -} - -static DEVICE_ATTR(version, S_IRUGO, - firmware_version_show, - NULL); - - -static ssize_t msg21xx_fw_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1, - "%s\n", ts_data->pdata->fw_name); -} - -static ssize_t msg21xx_fw_name_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - if (size > MSTAR_FW_NAME_MAX_LEN - 1) - return -EINVAL; - - strlcpy(ts_data->pdata->fw_name, buf, size); - if (ts_data->pdata->fw_name[size - 1] == '\n') - ts_data->pdata->fw_name[size - 1] = 0; - - return size; -} - -static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR), - msg21xx_fw_name_show, msg21xx_fw_name_store); - -static ssize_t firmware_data_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size) -{ - int count = size / 1024; - int i; - - for (i = 0; i < count; i++) - memcpy(fw_bin_data[i], buf + (i * 1024), 1024); - - if (buf != NULL) - dev_dbg(dev, "buf[0] = %c\n", buf[0]); - - return size; -} - -static DEVICE_ATTR(data, S_IWUSR, NULL, firmware_data_store); - -static ssize_t tp_print_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - tp_print_proc_read(ts_data); - - return snprintf(buf, 3, "%d\n", ts_data->suspended); -} - -static ssize_t tp_print_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size) -{ - return size; -} - -static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR), - tp_print_show, tp_print_store); - -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR -static void _msg_enable_proximity(void) -{ - unsigned char tx_data[4] = {0}; - - tx_data[0] = 0x52; - tx_data[1] = 0x00; - tx_data[2] = 0x47; - tx_data[3] = 0xa0; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(ts_data->client->addr, &tx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - - bEnableTpProximity = 1; -} - -static void _msg_disable_proximity(void) -{ - unsigned char tx_data[4] = {0}; - - tx_data[0] = 0x52; - tx_data[1] = 0x00; - tx_data[2] = 0x47; - tx_data[3] = 0xa1; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(ts_data->client->addr, &tx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - - bEnableTpProximity = 0; - bFaceClosingTp = 0; -} - -static void tsps_msg21xx_enable(int en) -{ - if (en) - _msg_enable_proximity(); - else - _msg_disable_proximity(); -} - -static int tsps_msg21xx_data(void) -{ - return bFaceClosingTp; -} -#endif - -static int msg21xx_pinctrl_init(struct msg21xx_ts_data *ts_data) -{ - int retval; - - /* Get pinctrl if target uses pinctrl */ - ts_data->ts_pinctrl = devm_pinctrl_get(&(ts_data->client->dev)); - if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) { - retval = PTR_ERR(ts_data->ts_pinctrl); - dev_dbg(&ts_data->client->dev, - "Target does not use pinctrl %d\n", retval); - goto err_pinctrl_get; - } - - ts_data->pinctrl_state_active = pinctrl_lookup_state( - ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE); - if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) { - retval = PTR_ERR(ts_data->pinctrl_state_active); - dev_dbg(&ts_data->client->dev, - "Can't lookup %s pinstate %d\n", - PINCTRL_STATE_ACTIVE, retval); - goto err_pinctrl_lookup; - } - - ts_data->pinctrl_state_suspend = pinctrl_lookup_state( - ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND); - if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) { - retval = PTR_ERR(ts_data->pinctrl_state_suspend); - dev_dbg(&ts_data->client->dev, - "Can't lookup %s pinstate %d\n", - PINCTRL_STATE_SUSPEND, retval); - goto err_pinctrl_lookup; - } - - ts_data->pinctrl_state_release = pinctrl_lookup_state( - ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE); - if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { - retval = PTR_ERR(ts_data->pinctrl_state_release); - dev_dbg(&ts_data->client->dev, - "Can't lookup %s pinstate %d\n", - PINCTRL_STATE_RELEASE, retval); - } - - return 0; - -err_pinctrl_lookup: - devm_pinctrl_put(ts_data->ts_pinctrl); -err_pinctrl_get: - ts_data->ts_pinctrl = NULL; - return retval; -} - -static unsigned char calculate_checksum(unsigned char *msg, int length) -{ - int checksum = 0, i; - - for (i = 0; i < length; i++) - checksum += msg[i]; - - return (unsigned char)((-checksum) & 0xFF); -} - -static int parse_info(struct msg21xx_ts_data *ts_data) -{ - unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0}; - unsigned char checksum = 0; - unsigned int x = 0, y = 0; - unsigned int x2 = 0, y2 = 0; - unsigned int delta_x = 0, delta_y = 0; - - mutex_lock(&msg21xx_mutex); - read_i2c_seq(ts_data, ts_data->client->addr, &data[0], - DEMO_MODE_PACKET_LENGTH); - mutex_unlock(&msg21xx_mutex); - checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1)); - dev_dbg(&ts_data->client->dev, "check sum: [%x] == [%x]?\n", - data[DEMO_MODE_PACKET_LENGTH-1], checksum); - - if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) { - dev_err(&ts_data->client->dev, "WRONG CHECKSUM\n"); - return -EINVAL; - } - - if (data[0] != 0x52) { - dev_err(&ts_data->client->dev, "WRONG HEADER\n"); - return -EINVAL; - } - - ts_data->info.keycode = 0xFF; - if ((data[1] == 0xFF) && (data[2] == 0xFF) && - (data[3] == 0xFF) && (data[4] == 0xFF) && - (data[6] == 0xFF)) { - if ((data[5] == 0xFF) || (data[5] == 0)) { - ts_data->info.keycode = 0xFF; - } else if ((data[5] == 1) || (data[5] == 2) || - (data[5] == 4) || (data[5] == 8)) { - ts_data->info.keycode = data[5] >> 1; - - dev_dbg(&ts_data->client->dev, - "ts_data->info.keycode index %d\n", - ts_data->info.keycode); - } - #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - else if (bEnableTpProximity && ((data[5] == 0x80) || - (data[5] == 0x40))) { - if (data[5] == 0x80) - bFaceClosingTp = 1; - else if (data[5] == 0x40) - bFaceClosingTp = 0; - - return -EINVAL; - } - #endif - else { - dev_err(&ts_data->client->dev, "WRONG KEY\n"); - return -EINVAL; - } - } else { - x = (((data[1] & 0xF0) << 4) | data[2]); - y = (((data[1] & 0x0F) << 8) | data[3]); - delta_x = (((data[4] & 0xF0) << 4) | data[5]); - delta_y = (((data[4] & 0x0F) << 8) | data[6]); - - if ((delta_x == 0) && (delta_y == 0)) { - ts_data->info.point[0].x = - x * ts_data->pdata->x_max / TPD_WIDTH; - ts_data->info.point[0].y = - y * ts_data->pdata->y_max / TPD_HEIGHT; - ts_data->info.count = 1; - } else { - if (delta_x > 2048) - delta_x -= 4096; - - if (delta_y > 2048) - delta_y -= 4096; - - x2 = (unsigned int)((signed short)x + - (signed short)delta_x); - y2 = (unsigned int)((signed short)y + - (signed short)delta_y); - ts_data->info.point[0].x = - x * ts_data->pdata->x_max / TPD_WIDTH; - ts_data->info.point[0].y = - y * ts_data->pdata->y_max / TPD_HEIGHT; - ts_data->info.point[1].x = - x2 * ts_data->pdata->x_max / TPD_WIDTH; - ts_data->info.point[1].y = - y2 * ts_data->pdata->y_max / TPD_HEIGHT; - ts_data->info.count = ts_data->pdata->num_max_touches; - } - } - - return 0; -} - -static void touch_driver_touch_released(struct msg21xx_ts_data *ts_data) -{ - int i; - - for (i = 0; i < ts_data->pdata->num_max_touches; i++) { - input_mt_slot(ts_data->input_dev, i); - input_mt_report_slot_state(ts_data->input_dev, - MT_TOOL_FINGER, 0); - } - - input_report_key(ts_data->input_dev, BTN_TOUCH, 0); - input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, 0); - input_sync(ts_data->input_dev); -} - -/* read data through I2C then report data to input -sub-system when interrupt occurred */ -static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id) -{ - int i = 0; - static int last_keycode = 0xFF; - static int last_count; - struct msg21xx_ts_data *ts_data = dev_id; - - ts_data->info.count = 0; - if (0 == parse_info(ts_data)) { - if (ts_data->info.keycode != 0xFF) { /* key touch pressed */ - if (ts_data->info.keycode < - ts_data->pdata->num_buttons) { - if (ts_data->info.keycode != last_keycode) { - dev_dbg(&ts_data->client->dev, - "key touch pressed"); - - input_report_key(ts_data->input_dev, - BTN_TOUCH, 1); - input_report_key(ts_data->input_dev, - ts_data->pdata->button_map[ - ts_data->info.keycode], 1); - - last_keycode = ts_data->info.keycode; - } else { - /* pass duplicate key-pressing */ - dev_dbg(&ts_data->client->dev, - "REPEATED KEY\n"); - } - } else { - dev_dbg(&ts_data->client->dev, "WRONG KEY\n"); - } - } else { /* key touch released */ - if (last_keycode != 0xFF) { - dev_dbg(&ts_data->client->dev, "key touch released"); - - input_report_key(ts_data->input_dev, - BTN_TOUCH, 0); - input_report_key(ts_data->input_dev, - ts_data->pdata->button_map[last_keycode], - 0); - - last_keycode = 0xFF; - } - } - - if (ts_data->info.count > 0) { /* point touch pressed */ - for (i = 0; i < ts_data->info.count; i++) { - input_mt_slot(ts_data->input_dev, i); - input_mt_report_slot_state(ts_data->input_dev, - MT_TOOL_FINGER, 1); - input_report_abs(ts_data->input_dev, - ABS_MT_TOUCH_MAJOR, 1); - input_report_abs(ts_data->input_dev, - ABS_MT_POSITION_X, - ts_data->info.point[i].x); - input_report_abs(ts_data->input_dev, - ABS_MT_POSITION_Y, - ts_data->info.point[i].y); - } - } - - if (last_count > ts_data->info.count) { - for (i = ts_data->info.count; - i < ts_data->pdata->num_max_touches; - i++) { - input_mt_slot(ts_data->input_dev, i); - input_mt_report_slot_state(ts_data->input_dev, - MT_TOOL_FINGER, 0); - } - } - last_count = ts_data->info.count; - - input_report_key(ts_data->input_dev, BTN_TOUCH, - ts_data->info.count > 0); - input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, - ts_data->info.count > 0); - - input_sync(ts_data->input_dev); - } - - return IRQ_HANDLED; -} - -static int msg21xx_ts_power_init(struct msg21xx_ts_data *ts_data, bool init) -{ - int rc; - - if (init) { - ts_data->vdd = regulator_get(&ts_data->client->dev, - "vdd"); - if (IS_ERR(ts_data->vdd)) { - rc = PTR_ERR(ts_data->vdd); - dev_err(&ts_data->client->dev, - "Regulator get failed vdd rc=%d\n", rc); - return rc; - } - - if (regulator_count_voltages(ts_data->vdd) > 0) { - rc = regulator_set_voltage(ts_data->vdd, - MSTAR_VTG_MIN_UV, - MSTAR_VTG_MAX_UV); - if (rc) { - dev_err(&ts_data->client->dev, - "Regulator set_vtg failed vdd rc=%d\n", - rc); - goto reg_vdd_put; - } - } - - ts_data->vcc_i2c = regulator_get(&ts_data->client->dev, - "vcc_i2c"); - if (IS_ERR(ts_data->vcc_i2c)) { - rc = PTR_ERR(ts_data->vcc_i2c); - dev_err(&ts_data->client->dev, - "Regulator get failed vcc_i2c rc=%d\n", rc); - goto reg_vdd_set_vtg; - } - - if (regulator_count_voltages(ts_data->vcc_i2c) > 0) { - rc = regulator_set_voltage(ts_data->vcc_i2c, - MSTAR_I2C_VTG_MIN_UV, - MSTAR_I2C_VTG_MAX_UV); - if (rc) { - dev_err(&ts_data->client->dev, - "Regulator set_vtg failed vcc_i2c rc=%d\n", rc); - goto reg_vcc_i2c_put; - } - } - } else { - if (regulator_count_voltages(ts_data->vdd) > 0) - regulator_set_voltage(ts_data->vdd, 0, - MSTAR_VTG_MAX_UV); - - regulator_put(ts_data->vdd); - - if (regulator_count_voltages(ts_data->vcc_i2c) > 0) - regulator_set_voltage(ts_data->vcc_i2c, 0, - MSTAR_I2C_VTG_MAX_UV); - - regulator_put(ts_data->vcc_i2c); - } - - return 0; - -reg_vcc_i2c_put: - regulator_put(ts_data->vcc_i2c); -reg_vdd_set_vtg: - if (regulator_count_voltages(ts_data->vdd) > 0) - regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV); -reg_vdd_put: - regulator_put(ts_data->vdd); - return rc; -} - -static int msg21xx_ts_power_on(struct msg21xx_ts_data *ts_data, bool on) -{ - int rc; - - if (!on) - goto power_off; - - rc = regulator_enable(ts_data->vdd); - if (rc) { - dev_err(&ts_data->client->dev, - "Regulator vdd enable failed rc=%d\n", rc); - return rc; - } - - rc = regulator_enable(ts_data->vcc_i2c); - if (rc) { - dev_err(&ts_data->client->dev, - "Regulator vcc_i2c enable failed rc=%d\n", rc); - regulator_disable(ts_data->vdd); - } - - return rc; - -power_off: - rc = regulator_disable(ts_data->vdd); - if (rc) { - dev_err(&ts_data->client->dev, - "Regulator vdd disable failed rc=%d\n", rc); - return rc; - } - - rc = regulator_disable(ts_data->vcc_i2c); - if (rc) { - dev_err(&ts_data->client->dev, - "Regulator vcc_i2c disable failed rc=%d\n", rc); - rc = regulator_enable(ts_data->vdd); - } - - return rc; -} - -static int msg21xx_ts_gpio_configure(struct msg21xx_ts_data *ts_data, bool on) -{ - int ret = 0; - - if (!on) - goto pwr_deinit; - - if (gpio_is_valid(ts_data->pdata->irq_gpio)) { - ret = gpio_request(ts_data->pdata->irq_gpio, - "msg21xx_irq_gpio"); - if (ret) { - dev_err(&ts_data->client->dev, - "Failed to request GPIO[%d], %d\n", - ts_data->pdata->irq_gpio, ret); - goto err_irq_gpio_req; - } - ret = gpio_direction_input(ts_data->pdata->irq_gpio); - if (ret) { - dev_err(&ts_data->client->dev, - "Failed to set direction for gpio[%d], %d\n", - ts_data->pdata->irq_gpio, ret); - goto err_irq_gpio_dir; - } - gpio_set_value_cansleep(ts_data->pdata->irq_gpio, 1); - } else { - dev_err(&ts_data->client->dev, "irq gpio not provided\n"); - goto err_irq_gpio_req; - } - - if (gpio_is_valid(ts_data->pdata->reset_gpio)) { - ret = gpio_request(ts_data->pdata->reset_gpio, - "msg21xx_reset_gpio"); - if (ret) { - dev_err(&ts_data->client->dev, - "Failed to request GPIO[%d], %d\n", - ts_data->pdata->reset_gpio, ret); - goto err_reset_gpio_req; - } - - /* power on TP */ - ret = gpio_direction_output( - ts_data->pdata->reset_gpio, 1); - if (ret) { - dev_err(&ts_data->client->dev, - "Failed to set direction for GPIO[%d], %d\n", - ts_data->pdata->reset_gpio, ret); - goto err_reset_gpio_dir; - } - msleep(100); - gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0); - msleep(20); - gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 1); - msleep(200); - } else { - dev_err(&ts_data->client->dev, "reset gpio not provided\n"); - goto err_reset_gpio_req; - } - - return 0; - -err_reset_gpio_dir: - if (gpio_is_valid(ts_data->pdata->reset_gpio)) - gpio_free(ts_data->pdata->irq_gpio); -err_reset_gpio_req: -err_irq_gpio_dir: - if (gpio_is_valid(ts_data->pdata->irq_gpio)) - gpio_free(ts_data->pdata->irq_gpio); -err_irq_gpio_req: - return ret; - -pwr_deinit: - if (gpio_is_valid(ts_data->pdata->irq_gpio)) - gpio_free(ts_data->pdata->irq_gpio); - if (gpio_is_valid(ts_data->pdata->reset_gpio)) { - gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0); - ret = gpio_direction_input(ts_data->pdata->reset_gpio); - if (ret) - dev_err(&ts_data->client->dev, - "Unable to set direction for gpio [%d]\n", - ts_data->pdata->reset_gpio); - gpio_free(ts_data->pdata->reset_gpio); - } - return 0; -} - -#ifdef CONFIG_PM -static int msg21xx_ts_resume(struct device *dev) -{ - int retval; - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - if (!ts_data->suspended) { - dev_info(dev, "msg21xx_ts already in resume\n"); - return 0; - } - - mutex_lock(&ts_data->ts_mutex); - - retval = msg21xx_ts_power_on(ts_data, true); - if (retval) { - dev_err(dev, "msg21xx_ts power on failed"); - mutex_unlock(&ts_data->ts_mutex); - return retval; - } - - if (ts_data->ts_pinctrl) { - retval = pinctrl_select_state(ts_data->ts_pinctrl, - ts_data->pinctrl_state_active); - if (retval < 0) { - dev_err(dev, "Cannot get active pinctrl state\n"); - mutex_unlock(&ts_data->ts_mutex); - return retval; - } - } - - retval = msg21xx_ts_gpio_configure(ts_data, true); - if (retval) { - dev_err(dev, "Failed to put gpios in active state %d", - retval); - mutex_unlock(&ts_data->ts_mutex); - return retval; - } - - enable_irq(ts_data->client->irq); - ts_data->suspended = false; - - mutex_unlock(&ts_data->ts_mutex); - - return 0; -} - -static int msg21xx_ts_suspend(struct device *dev) -{ - int retval; - struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); - - if (ts_data->pdata->updating_fw) { - dev_info(dev, "Firmware loading in progress\n"); - return 0; - } - - if (ts_data->suspended) { - dev_info(dev, "msg21xx_ts already in suspend\n"); - return 0; - } - -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - if (bEnableTpProximity) { - dev_dbg(dev, "suspend bEnableTpProximity=%d\n", - bEnableTpProximity); - return 0; - } -#endif - - mutex_lock(&ts_data->ts_mutex); - - disable_irq(ts_data->client->irq); - - touch_driver_touch_released(ts_data); - - if (ts_data->ts_pinctrl) { - retval = pinctrl_select_state(ts_data->ts_pinctrl, - ts_data->pinctrl_state_suspend); - if (retval < 0) { - dev_err(dev, "Cannot get idle pinctrl state %d\n", - retval); - mutex_unlock(&ts_data->ts_mutex); - return retval; - } - } - - retval = msg21xx_ts_gpio_configure(ts_data, false); - if (retval) { - dev_err(dev, "Failed to put gpios in idle state %d", - retval); - mutex_unlock(&ts_data->ts_mutex); - return retval; - } - - retval = msg21xx_ts_power_on(ts_data, false); - if (retval) { - dev_err(dev, "msg21xx_ts power off failed"); - mutex_unlock(&ts_data->ts_mutex); - return retval; - } - - ts_data->suspended = true; - - mutex_unlock(&ts_data->ts_mutex); - - return 0; -} -#else -static int msg21xx_ts_resume(struct device *dev) -{ - return 0; -} -static int msg21xx_ts_suspend(struct device *dev) -{ - return 0; -} -#endif - -static int msg21xx_debug_suspend_set(void *_data, u64 val) -{ - struct msg21xx_ts_data *data = _data; - - mutex_lock(&data->input_dev->mutex); - - if (val) - msg21xx_ts_suspend(&data->client->dev); - else - msg21xx_ts_resume(&data->client->dev); - - mutex_unlock(&data->input_dev->mutex); - - return 0; -} - -static int msg21xx_debug_suspend_get(void *_data, u64 *val) -{ - struct msg21xx_ts_data *data = _data; - - mutex_lock(&data->input_dev->mutex); - *val = data->suspended; - mutex_unlock(&data->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, msg21xx_debug_suspend_get, - msg21xx_debug_suspend_set, "%lld\n"); - - -#if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct fb_event *evdata = data; - int *blank; - struct msg21xx_ts_data *ts_data = - container_of(self, struct msg21xx_ts_data, fb_notif); - - if (evdata && evdata->data && event == FB_EVENT_BLANK) { - blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - msg21xx_ts_resume(&ts_data->client->dev); - else if (*blank == FB_BLANK_POWERDOWN) - msg21xx_ts_suspend(&ts_data->client->dev); - } - - return 0; -} -#endif - -static int msg21xx_get_dt_coords(struct device *dev, char *name, - struct msg21xx_ts_platform_data *pdata) -{ - u32 coords[FT_COORDS_ARR_SIZE]; - struct property *prop; - struct device_node *np = dev->of_node; - int coords_size, rc; - - prop = of_find_property(np, name, NULL); - if (!prop) - return -EINVAL; - if (!prop->value) - return -ENODATA; - - coords_size = prop->length / sizeof(u32); - if (coords_size != FT_COORDS_ARR_SIZE) { - dev_err(dev, "invalid %s\n", name); - return -EINVAL; - } - - rc = of_property_read_u32_array(np, name, coords, coords_size); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Unable to read %s\n", name); - return rc; - } - - if (!strcmp(name, "mstar,panel-coords")) { - pdata->panel_minx = coords[0]; - pdata->panel_miny = coords[1]; - pdata->panel_maxx = coords[2]; - pdata->panel_maxy = coords[3]; - } else if (!strcmp(name, "mstar,display-coords")) { - pdata->x_min = coords[0]; - pdata->y_min = coords[1]; - pdata->x_max = coords[2]; - pdata->y_max = coords[3]; - } else { - dev_err(dev, "unsupported property %s\n", name); - return -EINVAL; - } - - return 0; -} - -static int msg21xx_parse_dt(struct device *dev, - struct msg21xx_ts_platform_data *pdata) -{ - int rc; - struct device_node *np = dev->of_node; - struct property *prop; - u32 temp_val; - - rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata); - if (rc && (rc != -EINVAL)) - return rc; - - rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata); - if (rc) - return rc; - - rc = of_property_read_u32(np, "mstar,hard-reset-delay-ms", - &temp_val); - if (!rc) - pdata->hard_reset_delay_ms = temp_val; - else - return rc; - - rc = of_property_read_u32(np, "mstar,post-hard-reset-delay-ms", - &temp_val); - if (!rc) - pdata->post_hard_reset_delay_ms = temp_val; - else - return rc; - - /* reset, irq gpio info */ - pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio", - 0, &pdata->reset_gpio_flags); - if (pdata->reset_gpio < 0) - return pdata->reset_gpio; - - pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio", - 0, &pdata->irq_gpio_flags); - if (pdata->irq_gpio < 0) - return pdata->irq_gpio; - - rc = of_property_read_u32(np, "mstar,ic-type", &temp_val); - if (rc && (rc != -EINVAL)) - return rc; - - pdata->ic_type = temp_val; - - rc = of_property_read_u32(np, "mstar,num-max-touches", &temp_val); - if (!rc) - pdata->num_max_touches = temp_val; - else - return rc; - - prop = of_find_property(np, "mstar,button-map", NULL); - if (prop) { - pdata->num_buttons = prop->length / sizeof(temp_val); - if (pdata->num_buttons > MAX_BUTTONS) - return -EINVAL; - - rc = of_property_read_u32_array(np, - "mstar,button-map", pdata->button_map, - pdata->num_buttons); - if (rc) { - dev_err(dev, "Unable to read key codes\n"); - return rc; - } - } - - return 0; -} - -/* probe function is used for matching and initializing input device */ -static int msg21xx_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) { - - int ret = 0, i; - struct dentry *temp, *dir; - struct input_dev *input_dev; - struct msg21xx_ts_data *ts_data; - struct msg21xx_ts_platform_data *pdata; - - if (client->dev.of_node) { - pdata = devm_kzalloc(&client->dev, - sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL); - if (!pdata) { - dev_err(&client->dev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - ret = msg21xx_parse_dt(&client->dev, pdata); - if (ret) { - dev_err(&client->dev, "DT parsing failed\n"); - return ret; - } - } else - pdata = client->dev.platform_data; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "I2C not supported\n"); - return -ENODEV; - } - - ts_data = devm_kzalloc(&client->dev, - sizeof(struct msg21xx_ts_data), GFP_KERNEL); - if (!ts_data) { - dev_err(&client->dev, "Not enough memory\n"); - return -ENOMEM; - } - - ts_data->client = client; - ts_data->info.point = devm_kzalloc(&client->dev, - sizeof(struct touchPoint_t) * pdata->num_max_touches, - GFP_KERNEL); - if (!ts_data->info.point) { - dev_err(&client->dev, "Not enough memory\n"); - return -ENOMEM; - } - - /* allocate an input device */ - input_dev = input_allocate_device(); - if (!input_dev) { - ret = -ENOMEM; - dev_err(&client->dev, "input device allocation failed\n"); - goto err_input_allocate_dev; - } - - input_dev->name = client->name; - input_dev->phys = "I2C"; - input_dev->dev.parent = &client->dev; - input_dev->id.bustype = BUS_I2C; - - ts_data->input_dev = input_dev; - ts_data->client = client; - ts_data->pdata = pdata; - - input_set_drvdata(input_dev, ts_data); - i2c_set_clientdata(client, ts_data); - - ret = msg21xx_ts_power_init(ts_data, true); - if (ret) { - dev_err(&client->dev, "Mstar power init failed\n"); - return ret; - } - - ret = msg21xx_ts_power_on(ts_data, true); - if (ret) { - dev_err(&client->dev, "Mstar power on failed\n"); - goto exit_deinit_power; - } - - ret = msg21xx_pinctrl_init(ts_data); - if (!ret && ts_data->ts_pinctrl) { - /* - * Pinctrl handle is optional. If pinctrl handle is found - * let pins to be configured in active state. If not - * found continue further without error. - */ - ret = pinctrl_select_state(ts_data->ts_pinctrl, - ts_data->pinctrl_state_active); - if (ret < 0) - dev_err(&client->dev, - "Failed to select %s pinatate %d\n", - PINCTRL_STATE_ACTIVE, ret); - } - - ret = msg21xx_ts_gpio_configure(ts_data, true); - if (ret) { - dev_err(&client->dev, "Failed to configure gpio %d\n", ret); - goto exit_gpio_config; - } - - if (msg21xx_get_ic_type(ts_data) == 0) { - dev_err(&client->dev, "The current IC is not Mstar\n"); - ret = -1; - goto err_wrong_ic_type; - } - - mutex_init(&msg21xx_mutex); - mutex_init(&ts_data->ts_mutex); - - /* set the supported event type for input device */ - set_bit(EV_ABS, input_dev->evbit); - set_bit(EV_SYN, input_dev->evbit); - set_bit(EV_KEY, input_dev->evbit); - set_bit(BTN_TOUCH, input_dev->keybit); - set_bit(BTN_TOOL_FINGER, input_dev->keybit); - set_bit(INPUT_PROP_DIRECT, input_dev->propbit); - - for (i = 0; i < pdata->num_buttons; i++) - input_set_capability(input_dev, EV_KEY, pdata->button_map[i]); - - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, pdata->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, pdata->y_max, 0, 0); - ret = input_mt_init_slots(input_dev, pdata->num_max_touches, 0); - if (ret) { - dev_err(&client->dev, - "Error %d initialising slots\n", ret); - goto err_free_mem; - } - - /* register the input device to input sub-system */ - ret = input_register_device(input_dev); - if (ret < 0) { - dev_err(&client->dev, - "Unable to register ms-touchscreen input device\n"); - goto err_input_reg_dev; - } - - /* version */ - if (device_create_file(&client->dev, &dev_attr_version) < 0) { - dev_err(&client->dev, - "Failed to create device file(%s)!\n", - dev_attr_version.attr.name); - goto err_create_fw_ver_file; - } - /* update */ - if (device_create_file(&client->dev, &dev_attr_update) < 0) { - dev_err(&client->dev, - "Failed to create device file(%s)!\n", - dev_attr_update.attr.name); - goto err_create_fw_update_file; - } - /* data */ - if (device_create_file(&client->dev, &dev_attr_data) < 0) { - dev_err(&client->dev, - "Failed to create device file(%s)!\n", - dev_attr_data.attr.name); - goto err_create_fw_data_file; - } - /* fw name */ - if (device_create_file(&client->dev, &dev_attr_fw_name) < 0) { - dev_err(&client->dev, - "Failed to create device file(%s)!\n", - dev_attr_fw_name.attr.name); - goto err_create_fw_name_file; - } - /* smart fw update */ - if (device_create_file(&client->dev, &dev_attr_update_fw) < 0) { - dev_err(&client->dev, - "Failed to create device file(%s)!\n", - dev_attr_update_fw.attr.name); - goto err_create_update_fw_file; - } - /* smart fw force update */ - if (device_create_file(&client->dev, - &dev_attr_force_update_fw) < 0) { - dev_err(&client->dev, - "Failed to create device file(%s)!\n", - dev_attr_force_update_fw.attr.name); - goto err_create_force_update_fw_file; - } - dir = debugfs_create_dir(MSTAR_DEBUG_DIR_NAME, NULL); - temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir, - ts_data, &debug_suspend_fops); - if (temp == NULL || IS_ERR(temp)) { - dev_err(&client->dev, - "debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); - goto free_debug_dir; - } - -#ifdef TP_PRINT - tp_print_create_entry(ts_data); -#endif - - ret = request_threaded_irq(client->irq, NULL, - msg21xx_ts_interrupt, - pdata->irq_gpio_flags | IRQF_ONESHOT, - "msg21xx", ts_data); - if (ret) - goto err_req_irq; - - disable_irq(client->irq); - -#if defined(CONFIG_FB) - ts_data->fb_notif.notifier_call = fb_notifier_callback; - ret = fb_register_client(&ts_data->fb_notif); -#endif - -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, - &tsps_msg21xx_data); -#endif - - dev_dbg(&client->dev, "mstar touch screen registered\n"); - enable_irq(client->irq); - return 0; - -err_req_irq: - free_irq(client->irq, ts_data); - device_remove_file(&client->dev, &dev_attr_data); -free_debug_dir: - debugfs_remove_recursive(dir); -err_create_fw_data_file: - device_remove_file(&client->dev, &dev_attr_update); -err_create_fw_update_file: - device_remove_file(&client->dev, &dev_attr_version); -err_create_fw_name_file: - device_remove_file(&client->dev, &dev_attr_fw_name); -err_create_update_fw_file: - device_remove_file(&client->dev, &dev_attr_update_fw); -err_create_force_update_fw_file: - device_remove_file(&client->dev, &dev_attr_force_update_fw); -err_create_fw_ver_file: - input_unregister_device(input_dev); - -err_input_reg_dev: - input_free_device(input_dev); - input_dev = NULL; -err_input_allocate_dev: - mutex_destroy(&msg21xx_mutex); - mutex_destroy(&ts_data->ts_mutex); - -err_wrong_ic_type: - msg21xx_ts_gpio_configure(ts_data, false); -exit_gpio_config: - if (ts_data->ts_pinctrl) { - if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { - devm_pinctrl_put(ts_data->ts_pinctrl); - ts_data->ts_pinctrl = NULL; - } else { - ret = pinctrl_select_state(ts_data->ts_pinctrl, - ts_data->pinctrl_state_release); - if (ret < 0) - dev_err(&ts_data->client->dev, - "Cannot get release pinctrl state\n"); - } - } - msg21xx_ts_power_on(ts_data, false); -exit_deinit_power: - msg21xx_ts_power_init(ts_data, false); -err_free_mem: - input_free_device(input_dev); - - return ret; -} - -/* remove function is triggered when the input device is removed -from input sub-system */ -static int touch_driver_remove(struct i2c_client *client) -{ - int retval = 0; - struct msg21xx_ts_data *ts_data = i2c_get_clientdata(client); - - free_irq(ts_data->client->irq, ts_data); - gpio_free(ts_data->pdata->irq_gpio); - gpio_free(ts_data->pdata->reset_gpio); - - if (ts_data->ts_pinctrl) { - if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { - devm_pinctrl_put(ts_data->ts_pinctrl); - ts_data->ts_pinctrl = NULL; - } else { - retval = pinctrl_select_state(ts_data->ts_pinctrl, - ts_data->pinctrl_state_release); - if (retval < 0) - dev_err(&ts_data->client->dev, - "Cannot get release pinctrl state\n"); - } - } - - input_unregister_device(ts_data->input_dev); - mutex_destroy(&msg21xx_mutex); - mutex_destroy(&ts_data->ts_mutex); - - return retval; -} - -/* The I2C device list is used for matching I2C device -and I2C device driver. */ -static const struct i2c_device_id touch_device_id[] = { - {"msg21xx", 0}, - {}, /* should not omitted */ -}; - -static struct of_device_id msg21xx_match_table[] = { - { .compatible = "mstar,msg21xx", }, - { }, -}; - -MODULE_DEVICE_TABLE(i2c, touch_device_id); - -static struct i2c_driver touch_device_driver = { - .driver = { - .name = "ms-msg21xx", - .owner = THIS_MODULE, - .of_match_table = msg21xx_match_table, - }, - .probe = msg21xx_ts_probe, - .remove = touch_driver_remove, - .id_table = touch_device_id, -}; - -module_i2c_driver(touch_device_driver); - -#ifdef TP_PRINT -#include - -static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256; -static unsigned char row, units, cnt; - -static int tp_print_proc_read(struct msg21xx_ts_data *ts_data) -{ - unsigned short i, j; - unsigned short left, offset = 0; - unsigned char dbbus_tx_data[3] = {0}; - unsigned char u8Data; - signed short s16Data; - int s32Data; - char *buf = NULL; - - left = cnt*row*units; - if ((ts_data->suspended == 0) && - (InfoAddr != 0x0F) && - (PoolAddr != 0x10) && - (left > 0)) { - buf = kmalloc(left, GFP_KERNEL); - if (buf != NULL) { - - while (left > 0) { - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) - & 0xFF; - dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(ts_data, ts_data->client->addr, - &dbbus_tx_data[0], 3); - read_i2c_seq(ts_data, ts_data->client->addr, - &buf[offset], - left > TransLen ? TransLen : left); - mutex_unlock(&msg21xx_mutex); - - if (left > TransLen) { - left -= TransLen; - offset += TransLen; - } else { - left = 0; - } - } - - for (i = 0; i < cnt; i++) { - for (j = 0; j < row; j++) { - if (units == 1) { - u8Data = buf[i * row * units + - j * units]; - } else if (units == 2) { - s16Data = buf[i * row * units + - j * units] + - (buf[i * row * units + - j * units + 1] << 8); - } else if (units == 4) { - s32Data = buf[i * row * units + - j * units] + - (buf[i * row * units + - j * units + 1] << 8) + - (buf[i * row * units + - j * units + 2] << 16) + - (buf[i * row * units + - j * units + 3] << 24); - } - } - } - - kfree(buf); - } - } - - return 0; -} - -static void tp_print_create_entry(struct msg21xx_ts_data *ts_data) -{ - unsigned char dbbus_tx_data[3] = {0}; - unsigned char dbbus_rx_data[8] = {0}; - - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = 0x00; - dbbus_tx_data[2] = 0x58; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 3); - read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0]; - PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2]; - - if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) { - msleep(20); - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF; - dbbus_tx_data[2] = InfoAddr & 0xFF; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(ts_data, ts_data->client->addr, - &dbbus_tx_data[0], 3); - read_i2c_seq(ts_data, ts_data->client->addr, - &dbbus_rx_data[0], 8); - mutex_unlock(&msg21xx_mutex); - - units = dbbus_rx_data[0]; - row = dbbus_rx_data[1]; - cnt = dbbus_rx_data[2]; - TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6]; - - if (device_create_file(&ts_data->client->dev, - &dev_attr_tpp) < 0) - dev_err(&ts_data->client->dev, "Failed to create device file(%s)!\n", - dev_attr_tpp.attr.name); - } -} -#endif - -MODULE_AUTHOR("MStar Semiconductor, Inc."); -MODULE_LICENSE("GPL v2"); From 5c76204e642c377e8d13bb266279d793fabd2b40 Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Wed, 25 Jan 2017 16:38:48 +0530 Subject: [PATCH 109/210] msm: mdss: handle synchronization issues during DSI debugfs read/write Handle race condition during read/write operations to DSI debugfs nodes related to DSI panel ON/OFF commands. Change-Id: I29c4ad74bf21d4cb5362565e902a682fe7263147 Signed-off-by: Padmanabhan Komanduru --- drivers/video/msm/mdss/mdss_dsi.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index 3de9eea98c1f..1de41eeb7d16 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -614,6 +614,7 @@ struct buf_data { char *string_buf; /* cmd buf as string, 3 bytes per number */ int sblen; /* string buffer length */ int sync_flag; + struct mutex dbg_mutex; /* mutex to synchronize read/write/flush */ }; struct mdss_dsi_debugfs_info { @@ -703,6 +704,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, char *bp; ssize_t ret = 0; + mutex_lock(&pcmds->dbg_mutex); if (*ppos == 0) { kfree(pcmds->string_buf); pcmds->string_buf = NULL; @@ -721,6 +723,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, buffer = kmalloc(bsize, GFP_KERNEL); if (!buffer) { pr_err("%s: Failed to allocate memory\n", __func__); + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -756,10 +759,12 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, kfree(pcmds->string_buf); pcmds->string_buf = NULL; pcmds->sblen = 0; + mutex_unlock(&pcmds->dbg_mutex); return 0; /* the end */ } ret = simple_read_from_buffer(buf, count, ppos, pcmds->string_buf, pcmds->sblen); + mutex_unlock(&pcmds->dbg_mutex); return ret; } @@ -771,6 +776,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, int blen = 0; char *string_buf; + mutex_lock(&pcmds->dbg_mutex); if (*ppos == 0) { kfree(pcmds->string_buf); pcmds->string_buf = NULL; @@ -782,6 +788,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, string_buf = krealloc(pcmds->string_buf, blen + 1, GFP_KERNEL); if (!string_buf) { pr_err("%s: Failed to allocate memory\n", __func__); + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -791,6 +798,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, string_buf[blen] = '\0'; pcmds->string_buf = string_buf; pcmds->sblen = blen; + mutex_unlock(&pcmds->dbg_mutex); return ret; } @@ -801,8 +809,12 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) char *buf, *bufp, *bp; struct dsi_ctrl_hdr *dchdr; - if (!pcmds->string_buf) + mutex_lock(&pcmds->dbg_mutex); + + if (!pcmds->string_buf) { + mutex_unlock(&pcmds->dbg_mutex); return 0; + } /* * Allocate memory for command buffer @@ -815,6 +827,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) kfree(pcmds->string_buf); pcmds->string_buf = NULL; pcmds->sblen = 0; + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -839,6 +852,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pr_err("%s: dtsi cmd=%x error, len=%d\n", __func__, dchdr->dtype, dchdr->dlen); kfree(buf); + mutex_unlock(&pcmds->dbg_mutex); return -EINVAL; } bp += sizeof(*dchdr); @@ -850,6 +864,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pr_err("%s: dcs_cmd=%x len=%d error!\n", __func__, bp[0], len); kfree(buf); + mutex_unlock(&pcmds->dbg_mutex); return -EINVAL; } @@ -862,6 +877,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pcmds->buf = buf; pcmds->blen = blen; } + mutex_unlock(&pcmds->dbg_mutex); return 0; } @@ -876,6 +892,7 @@ struct dentry *dsi_debugfs_create_dcs_cmd(const char *name, umode_t mode, struct dentry *parent, struct buf_data *cmd, struct dsi_panel_cmds ctrl_cmds) { + mutex_init(&cmd->dbg_mutex); cmd->buf = ctrl_cmds.buf; cmd->blen = ctrl_cmds.blen; cmd->string_buf = NULL; From 777ea081d6be2990bfe9aebc6c58f339e9da3194 Mon Sep 17 00:00:00 2001 From: Ankit Sharma Date: Thu, 9 Feb 2017 16:23:09 +0530 Subject: [PATCH 110/210] leds : qpnp-flash: Fix Use-after-free(UAF) for debugfs Fix UAF where two threads can open and close the same file. Second open will cause the private data for the first file to be overwritten. When the first file is closed and the private data is freed, this makes the now-shared private data OOB for the second thread. CRs-Fixed: 1109763 Change-Id: I1c4618d5be99e140abf0f3ea0d7f485897db5ab2 Signed-off-by: Ankit Sharma --- drivers/leds/leds-qpnp-flash.c | 83 ++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 6cc8e0986b91..bb837d65f4d5 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -218,11 +218,13 @@ struct flash_led_platform_data { }; struct qpnp_flash_led_buffer { - struct mutex debugfs_lock; /* Prevent thread concurrency */ - size_t rpos; - size_t wpos; - size_t len; - char data[0]; + struct mutex debugfs_lock; /* Prevent thread concurrency */ + size_t rpos; + size_t wpos; + size_t len; + struct qpnp_flash_led *led; + u32 buffer_cnt; + char data[0]; }; /* @@ -239,10 +241,8 @@ struct qpnp_flash_led { struct workqueue_struct *ordered_workq; struct qpnp_vadc_chip *vadc_dev; struct mutex flash_led_lock; - struct qpnp_flash_led_buffer *log; struct dentry *dbgfs_root; int num_leds; - u32 buffer_cnt; u16 base; u16 current_addr; u16 current2_addr; @@ -273,10 +273,10 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, log->wpos = 0; log->len = logbufsize - sizeof(*log); mutex_init(&log->debugfs_lock); - led->log = log; + log->led = led; - led->buffer_cnt = 1; - file->private_data = led; + log->buffer_cnt = 1; + file->private_data = log; return 0; } @@ -289,12 +289,12 @@ static int flash_led_dfs_open(struct inode *inode, struct file *file) static int flash_led_dfs_close(struct inode *inode, struct file *file) { - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; - if (led && led->log) { + if (log) { file->private_data = NULL; - mutex_destroy(&led->log->debugfs_lock); - kfree(led->log); + mutex_destroy(&log->debugfs_lock); + kfree(log); } return 0; @@ -323,15 +323,21 @@ static int print_to_log(struct qpnp_flash_led_buffer *log, static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { - struct qpnp_flash_led *led = fp->private_data; - struct qpnp_flash_led_buffer *log = led->log; + struct qpnp_flash_led_buffer *log = fp->private_data; + struct qpnp_flash_led *led; u8 val; int rc = 0; size_t len; size_t ret; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + mutex_lock(&log->debugfs_lock); - if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || + if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) goto unlock_mutex; @@ -343,7 +349,7 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, INT_LATCHED_STS(led->base), rc); goto unlock_mutex; } - led->buffer_cnt--; + log->buffer_cnt--; rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); if (rc == 0) @@ -378,18 +384,24 @@ unlock_mutex: static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { - struct qpnp_flash_led *led = fp->private_data; - struct qpnp_flash_led_buffer *log = led->log; + struct qpnp_flash_led_buffer *log = fp->private_data; + struct qpnp_flash_led *led; int rc = 0; size_t len; size_t ret; + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + mutex_lock(&log->debugfs_lock); - if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || + if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) goto unlock_mutex; - led->buffer_cnt--; + log->buffer_cnt--; rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); if (rc == 0) @@ -431,10 +443,17 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, int data; size_t ret = 0; - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; + struct qpnp_flash_led *led; char *kbuf; - mutex_lock(&led->log->debugfs_lock); + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); kbuf = kmalloc(count + 1, GFP_KERNEL); if (!kbuf) { ret = -ENOMEM; @@ -469,7 +488,7 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, free_buf: kfree(kbuf); unlock_mutex: - mutex_unlock(&led->log->debugfs_lock); + mutex_unlock(&log->debugfs_lock); return ret; } @@ -481,11 +500,17 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, int cnt = 0; int data; size_t ret = 0; - - struct qpnp_flash_led *led = file->private_data; + struct qpnp_flash_led_buffer *log = file->private_data; + struct qpnp_flash_led *led; char *kbuf; - mutex_lock(&led->log->debugfs_lock); + if (!log) { + pr_err("error: file private data is NULL\n"); + return -EFAULT; + } + led = log->led; + + mutex_lock(&log->debugfs_lock); kbuf = kmalloc(count + 1, GFP_KERNEL); if (!kbuf) { ret = -ENOMEM; @@ -519,7 +544,7 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, free_buf: kfree(kbuf); unlock_mutex: - mutex_unlock(&led->log->debugfs_lock); + mutex_unlock(&log->debugfs_lock); return ret; } From 78d70861fd683b35e00c91a1a25414e58fb950fc Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Mon, 23 Jan 2017 18:04:53 +0530 Subject: [PATCH 111/210] input: touchscreen: gt9xx: fix memory corruption in Goodix driver Fix memory corruption in Goodix touchscreen driver, by resetting the global structure cmd_head to zero (except *data and wr flag) in goodix_tool_write handler on error case. Change-Id: I4f7f8f464b93571627b922b10c10a65826228e42 Signed-off-by: Vevek Venkatesan --- drivers/input/touchscreen/gt9xx/goodix_tool.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c index 8e202fc00dcd..905e74792bee 100644 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c @@ -1,7 +1,7 @@ /* drivers/input/touchscreen/goodix_tool.c * * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 as published by @@ -311,6 +311,7 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, size_t count, loff_t *ppos) { s32 ret = 0; + u8 *dataptr = NULL; mutex_lock(&lock); ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); @@ -463,6 +464,11 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, ret = CMD_HEAD_LENGTH; exit: + dataptr = cmd_head.data; + memset(&cmd_head, 0, sizeof(cmd_head)); + cmd_head.wr = 0xFF; + cmd_head.data = dataptr; + mutex_unlock(&lock); return ret; } From f7cf0eede3170d00d2050dabec1946a4e193eb7b Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Wed, 25 Jan 2017 10:51:55 -0800 Subject: [PATCH 112/210] msm: ADSPRPC: Check for buffer overflow condition The buffer length that is being passed could result in overflow condition causing invalid memory to be accessed. Change-Id: I3e23f31b8cb61f8e77d09a39fab4a2d4c222cf25 Signed-off-by: Sathish Ambley --- drivers/char/adsprpc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index b2ce58e10834..391bfe6bd510 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 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 @@ -456,9 +456,9 @@ static int overlap_ptr_cmp(const void *a, const void *b) return st == 0 ? ed : st; } -static void context_build_overlap(struct smq_invoke_ctx *ctx) +static int context_build_overlap(struct smq_invoke_ctx *ctx) { - int i; + int err = 0, i; remote_arg_t *lpra = ctx->lpra; int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); @@ -467,6 +467,11 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) for (i = 0; i < nbufs; ++i) { ctx->overs[i].start = (uintptr_t)lpra[i].buf.pv; ctx->overs[i].end = ctx->overs[i].start + lpra[i].buf.len; + if (lpra[i].buf.len) { + VERIFY(err, ctx->overs[i].end > ctx->overs[i].start); + if (err) + goto bail; + } ctx->overs[i].raix = i; ctx->overps[i] = &ctx->overs[i]; } @@ -492,6 +497,8 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) max = *ctx->overps[i]; } } +bail: + return err; } #define K_COPY_FROM_USER(err, kernel, dst, src, size) \ From 375e2a578f8f2c23aa08b1361df649176a0ba372 Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Mon, 6 Mar 2017 11:39:35 +0530 Subject: [PATCH 113/210] msm: camera: cpp: Avoid exposing kernel information to user space Avoid copy_to_user for the cases that are not required. CRs-Fixed: 1099731 Change-Id: Id7d94d26fc662f406f55fbe2f8703b3632809802 Signed-off-by: Pratap Nirujogi Signed-off-by: VijayaKumar T M --- .../msm/camera_v2/pproc/cpp/msm_cpp.c | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 63751c45d204..5b09cd230d20 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -3349,6 +3349,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, struct msm_cpp_frame_info32_t k32_frame_info; struct msm_cpp_frame_info_t k64_frame_info; void __user *up = (void __user *)arg; + bool is_copytouser_req = true; if (sd == NULL) { pr_err("%s: Subdevice is NULL\n", __func__); @@ -3505,6 +3506,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, k64_cpp_buff_info.buffer_info = compat_ptr(k32_cpp_buff_info.buffer_info); kp_ioctl.ioctl_ptr = (void *)&k64_cpp_buff_info; + is_copytouser_req = false; if (cmd == VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO32) cmd = VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO; else if (cmd == VIDIOC_MSM_CPP_DELETE_STREAM_BUFF32) @@ -3570,6 +3572,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, kp_ioctl.len = sizeof(struct msm_cpp_clock_settings_t); } + is_copytouser_req = false; cmd = VIDIOC_MSM_CPP_SET_CLOCK; break; } @@ -3600,6 +3603,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, kp_ioctl.ioctl_ptr = (void *)&k_queue_buf; kp_ioctl.len = sizeof(struct msm_pproc_queue_buf_info); + is_copytouser_req = false; cmd = VIDIOC_MSM_CPP_QUEUE_BUF; break; } @@ -3620,6 +3624,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, k64_frame_info.frame_id = k32_frame_info.frame_id; kp_ioctl.ioctl_ptr = (void *)&k64_frame_info; + is_copytouser_req = false; cmd = VIDIOC_MSM_CPP_POP_STREAM_BUFFER; break; } @@ -3668,14 +3673,15 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, break; } - up32_ioctl.id = kp_ioctl.id; - up32_ioctl.len = kp_ioctl.len; - up32_ioctl.trans_code = kp_ioctl.trans_code; - up32_ioctl.ioctl_ptr = ptr_to_compat(kp_ioctl.ioctl_ptr); - - if (copy_to_user((void __user *)up, &up32_ioctl, sizeof(up32_ioctl))) - return -EFAULT; + if (is_copytouser_req) { + up32_ioctl.id = kp_ioctl.id; + up32_ioctl.len = kp_ioctl.len; + up32_ioctl.trans_code = kp_ioctl.trans_code; + up32_ioctl.ioctl_ptr = ptr_to_compat(kp_ioctl.ioctl_ptr); + if (copy_to_user((void __user *)up, &up32_ioctl, sizeof(up32_ioctl))) + return -EFAULT; + } return rc; } #endif From c736ef51e34f1c6333de6e32a5728431bb3a2eba Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Fri, 24 Feb 2017 15:22:40 +0530 Subject: [PATCH 114/210] usb: replace %p with %pK Format specifier %p can leak kernel addresses while not valuing the kptr_restrict system settings. When kptr_restrict is set to (1), kernel pointers printed using the %pK format specifier will be replaced with 0's. Debugging Note : &pK prints only Zeros as address. If you need actual address information, write 0 to kptr_restrict. echo 0 > /proc/sys/kernel/kptr_restrict CRs-fixed: 1052849 Change-Id: I0e98145730380ea983fa8f46a28d15dd6c2c31df Signed-off-by: Manu Gautam --- drivers/net/usb/cdc_ether.c | 4 +- drivers/net/usb/cdc_mbim.c | 2 +- drivers/net/usb/rmnet_usb_ctrl.c | 2 +- drivers/platform/msm/usb_bam.c | 14 ++--- drivers/usb/core/devio.c | 4 +- drivers/usb/core/hcd.c | 4 +- drivers/usb/core/urb.c | 2 +- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/debugfs.c | 6 +-- drivers/usb/dwc3/dwc3-msm.c | 10 ++-- drivers/usb/dwc3/ep0.c | 4 +- drivers/usb/dwc3/gadget.c | 16 +++--- drivers/usb/early/ehci-dbgp.c | 2 +- drivers/usb/gadget/android.c | 4 +- drivers/usb/gadget/ci13xxx_msm_hsic.c | 2 +- drivers/usb/gadget/ci13xxx_udc.c | 76 +++++++++++++------------- drivers/usb/gadget/composite.c | 18 +++---- drivers/usb/gadget/configfs.c | 2 +- drivers/usb/gadget/dummy_hcd.c | 12 ++--- drivers/usb/gadget/f_accessory.c | 10 ++-- drivers/usb/gadget/f_acm.c | 6 +-- drivers/usb/gadget/f_fs.c | 4 +- drivers/usb/gadget/f_gps.c | 20 +++---- drivers/usb/gadget/f_mtp.c | 10 ++-- drivers/usb/gadget/f_qdss.c | 4 +- drivers/usb/gadget/f_rmnet.c | 30 +++++------ drivers/usb/gadget/f_serial.c | 5 +- drivers/usb/gadget/inode.c | 4 +- drivers/usb/gadget/u_bam.c | 24 ++++----- drivers/usb/gadget/u_bam_data.c | 24 ++++----- drivers/usb/gadget/u_ctrl_hsuart.c | 6 +-- drivers/usb/gadget/u_ctrl_qti.c | 10 ++-- drivers/usb/gadget/u_data_hsic.c | 22 ++++---- drivers/usb/gadget/u_data_hsuart.c | 18 +++---- drivers/usb/gadget/u_data_ipa.c | 16 +++--- drivers/usb/gadget/u_rmnet_ctrl_smd.c | 10 ++-- drivers/usb/gadget/u_serial.c | 18 +++---- drivers/usb/gadget/u_smd.c | 40 +++++++------- drivers/usb/host/ehci-dbg.c | 22 ++++---- drivers/usb/host/ehci-fsl.c | 2 +- drivers/usb/host/ehci-hcd.c | 2 +- drivers/usb/host/ehci-msm-hsic.c | 10 ++-- drivers/usb/host/ehci-mv.c | 2 +- drivers/usb/host/ehci-ps3.c | 2 +- drivers/usb/host/ehci-q.c | 8 +-- drivers/usb/host/ehci-sched.c | 22 ++++---- drivers/usb/host/xhci-dbg.c | 78 +++++++++++++-------------- drivers/usb/host/xhci-mem.c | 32 +++++------ drivers/usb/host/xhci-ring.c | 20 +++---- drivers/usb/host/xhci.c | 22 ++++---- drivers/usb/mon/mon_text.c | 2 +- drivers/usb/phy/phy-msm-usb.c | 2 +- drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/uas.c | 2 +- sound/usb/endpoint.c | 4 +- sound/usb/pcm.c | 12 ++--- 56 files changed, 357 insertions(+), 356 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index b1897c7afdd8..ea0a686a09eb 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -191,7 +191,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) info->u->bSlaveInterface0); if (!info->control || !info->data) { dev_dbg(&intf->dev, - "master #%u/%p slave #%u/%p\n", + "master #%u/%pK slave #%u/%pK\n", info->u->bMasterInterface0, info->control, info->u->bSlaveInterface0, @@ -287,7 +287,7 @@ next_desc: info->data = usb_ifnum_to_if(dev->udev, 1); if (!info->control || !info->data || info->control != intf) { dev_dbg(&intf->dev, - "rndis: master #0/%p slave #1/%p\n", + "rndis: master #0/%pK slave #1/%pK\n", info->control, info->data); goto bad_desc; diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 7cabe4583904..5b04430bfac3 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -305,7 +305,7 @@ next_ndp: /* sanity checking */ if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) { netif_dbg(dev, rx_err, dev->net, - "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n", + "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%pK\n", x, offset, len, skb_in); if (!x) goto err_ndp; diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c index f44d4dcb9075..58fd1f68636c 100644 --- a/drivers/net/usb/rmnet_usb_ctrl.c +++ b/drivers/net/usb/rmnet_usb_ctrl.c @@ -982,7 +982,7 @@ static ssize_t rmnet_usb_ctrl_read_stats(struct file *file, char __user *ubuf, cdev = &ctrl_devs[i][n]; dev = cdev->cudev; temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp, - "\n#ctrl_dev: %p Name: %s#\n" + "\n#ctrl_dev: %pK Name: %s#\n" "snd encap cmd cnt %u\n" "resp avail cnt: %u\n" "get encap resp cnt: %u\n" diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c index 431dcb220b32..bee49c853c4f 100644 --- a/drivers/platform/msm/usb_bam.c +++ b/drivers/platform/msm/usb_bam.c @@ -259,10 +259,10 @@ void msm_bam_set_hsic_host_dev(struct device *dev) if (dev) { /* Hold the device until allowing lpm */ info[HSIC_CTRL].in_lpm = false; - log_event(1, "%s: Getting hsic device %p\n", __func__, dev); + log_event(1, "%s: Getting hsic device %pK\n", __func__, dev); pm_runtime_get(dev); } else if (host_info[HSIC_CTRL].dev) { - log_event(1, "%s: Try Putting hsic device %p, lpm:%d\n", + log_event(1, "%s: Try Putting hsic device %pK, lpm:%d\n", __func__, host_info[HSIC_CTRL].dev, info[HSIC_CTRL].in_lpm); /* Just release previous device if not already done */ @@ -889,7 +889,7 @@ static bool _hsic_host_bam_resume_core(void) /* Exit from "full suspend" in case of hsic host */ if (host_info[HSIC_CTRL].dev && info[HSIC_CTRL].in_lpm) { - log_event(1, "%s: Getting hsic device %p\n", __func__, + log_event(1, "%s: Getting hsic device %pK\n", __func__, host_info[HSIC_CTRL].dev); pm_runtime_get(host_info[HSIC_CTRL].dev); info[HSIC_CTRL].in_lpm = false; @@ -941,7 +941,7 @@ static void _hsic_host_bam_suspend_core(void) log_event(1, "%s: enter\n", __func__); if (host_info[HSIC_CTRL].dev && !info[HSIC_CTRL].in_lpm) { - log_event(1, "%s: Putting hsic host device %p\n", __func__, + log_event(1, "%s: Putting hsic host device %pK\n", __func__, host_info[HSIC_CTRL].dev); pm_runtime_put(host_info[HSIC_CTRL].dev); info[HSIC_CTRL].in_lpm = true; @@ -1836,7 +1836,7 @@ static bool check_pipes_empty(u8 src_idx, u8 dst_idx) /* If we have any remaints in the pipes we don't go to sleep */ prod_pipe = ctx.usb_bam_sps.sps_pipes[src_idx]; cons_pipe = ctx.usb_bam_sps.sps_pipes[dst_idx]; - log_event(1, "prod_pipe=%p, cons_pipe=%p", prod_pipe, cons_pipe); + log_event(1, "prod_pipe=%pK, cons_pipe=%pK", prod_pipe, cons_pipe); if (!cons_pipe || (!prod_pipe && prod_pipe_connect->pipe_type == USB_BAM_PIPE_BAM2BAM)) { @@ -2187,7 +2187,7 @@ bool msm_bam_host_lpm_ok(enum usb_ctrl bam_type) } /* HSIC host will go now to lpm */ - log_event(1, "%s: vote for suspend hsic %p\n", + log_event(1, "%s: vote for suspend hsic %pK\n", __func__, host_info[bam_type].dev); for (i = 0; i < ctx.max_connections; i++) { @@ -2555,7 +2555,7 @@ static void usb_bam_work(struct work_struct *w) pipe_iter->dir == PEER_PERIPHERAL_TO_USB && pipe_iter->enabled) { - log_event(1, "%s: Register wakeup on pipe %p\n", + log_event(1, "%s: Register wakeup on pipe %pK\n", __func__, pipe_iter); __usb_bam_register_wake_cb(i, pipe_iter->activity_notify, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4ccdd01fd0b7..dc8f384b6850 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -373,11 +373,11 @@ static void snoop_urb(struct usb_device *udev, if (userurb) { /* Async */ if (when == SUBMIT) - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "length %u\n", userurb, ep, t, d, length); else - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "actual_length %u status %d\n", userurb, ep, t, d, length, timeout_or_status); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d350a4e3e821..704fe9aa02c8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1626,7 +1626,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) if (retval == 0) retval = -EINPROGRESS; else if (retval != -EIDRM && retval != -EBUSY) - dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", + dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n", urb, retval); usb_put_dev(udev); } @@ -1710,7 +1710,7 @@ rescan: /* kick hcd */ unlink1(hcd, urb, -ESHUTDOWN); dev_dbg (hcd->self.controller, - "shutdown urb %p ep%d%s%s\n", + "shutdown urb %pK ep%d%s%s\n", urb, usb_endpoint_num(&ep->desc), is_in ? "in" : "out", ({ char *s; diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 16927fa88fbd..6c7a59560fa3 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -324,7 +324,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || !urb->complete) return -EINVAL; if (urb->hcpriv) { - WARN_ONCE(1, "URB %p submitted while active\n", urb); + WARN_ONCE(1, "URB %pK submitted while active\n", urb); return -EBUSY; } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7314687b37eb..13ea8afecd59 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -333,7 +333,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc) for (n = 0; n < dwc->num_event_buffers; n++) { evt = dwc->ev_buffs[n]; - dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", + dev_dbg(dwc->dev, "Event buf %pK dma %08llx length %d\n", evt->buf, (unsigned long long) evt->dma, evt->length); diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 29cdc99e486d..b5317548e92f 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -692,7 +692,7 @@ static int dwc3_ep_req_list_show(struct seq_file *s, void *unused) req = list_entry(ptr, struct dwc3_request, list); seq_printf(s, - "req:0x%p len: %d sts: %d dma:0x%pa num_sgs: %d\n", + "req:0x%pK len: %d sts: %d dma:0x%pKa num_sgs: %d\n", req, req->request.length, req->request.status, &req->request.dma, req->request.num_sgs); } @@ -731,7 +731,7 @@ static int dwc3_ep_queued_req_show(struct seq_file *s, void *unused) req = list_entry(ptr, struct dwc3_request, list); seq_printf(s, - "req:0x%p len:%d sts:%d dma:%pa nsg:%d trb:0x%p\n", + "req:0x%pK len:%d sts:%d dma:%pKa nsg:%d trb:0x%pK\n", req, req->request.length, req->request.status, &req->request.dma, req->request.num_sgs, req->trb); } @@ -773,7 +773,7 @@ static int dwc3_ep_trbs_show(struct seq_file *s, void *unused) dep->name, dep->flags, dep->free_slot, dep->busy_slot); for (j = 0; j < DWC3_TRB_NUM; j++) { trb = &dep->trb_pool[j]; - seq_printf(s, "trb:0x%p bph:0x%x bpl:0x%x size:0x%x ctrl: %x\n", + seq_printf(s, "trb:0x%pK bph:0x%x bpl:0x%x size:0x%x ctrl: %x\n", trb, trb->bph, trb->bpl, trb->size, trb->ctrl); } spin_unlock_irqrestore(&dwc->lock, flags); diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 8501f2ec2de4..41af462263b4 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -708,14 +708,14 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, if (!dep->endpoint.desc) { dev_err(mdwc->dev, - "%s: trying to queue request %p to disabled ep %s\n", + "%s: trying to queue request %pK to disabled ep %s\n", __func__, request, ep->name); return -EPERM; } if (dep->number == 0 || dep->number == 1) { dev_err(mdwc->dev, - "%s: trying to queue dbm request %p to control ep %s\n", + "%s: trying to queue dbm request %pK to control ep %s\n", __func__, request, ep->name); return -EPERM; } @@ -724,7 +724,7 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list) || !list_empty(&dep->req_queued)) { dev_err(mdwc->dev, - "%s: trying to queue dbm request %p tp ep %s\n", + "%s: trying to queue dbm request %pK tp ep %s\n", __func__, request, ep->name); return -EPERM; } else { @@ -769,7 +769,7 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, return ret; } - dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n", + dev_vdbg(dwc->dev, "%s: queing request %pK to ep %s length %d\n", __func__, request, ep->name, request->length); size = dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)); dbm_event_buffer_config(mdwc->dbm, @@ -986,7 +986,7 @@ EXPORT_SYMBOL(msm_dwc3_restart_usb_session); */ int msm_register_usb_ext_notification(struct usb_ext_notification *info) { - pr_debug("%s usb_ext: %p\n", __func__, info); + pr_debug("%s usb_ext: %pK\n", __func__, info); if (info) { if (usb_ext) { diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index fed1aa12c394..b8d4b6256e36 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -243,7 +243,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, spin_lock_irqsave(&dwc->lock, flags); if (!dep->endpoint.desc) { - dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", + dev_dbg(dwc->dev, "trying to queue request %pK to disabled %s\n", request, dep->name); ret = -ESHUTDOWN; goto out; @@ -255,7 +255,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, goto out; } - dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n", + dev_vdbg(dwc->dev, "queueing request %pK to %s length %d, state '%s'\n", request, dep->name, request->length, dwc3_ep0_state_string(dwc->ep0state)); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index aa7412ec3a4b..4d8a0240588c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -332,7 +332,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, usb_gadget_unmap_request(&dwc->gadget, &req->request, req->direction); - dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", + dev_dbg(dwc->dev, "request %pK from %s completed %d/%d ===> %d\n", req, dep->name, req->request.actual, req->request.length, status); @@ -746,7 +746,7 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, int ret; if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { - pr_debug("dwc3: invalid parameters. ep=%p, desc=%p, DT=%d\n", + pr_debug("dwc3: invalid parameters. ep=%pK, desc=%pK, DT=%d\n", ep, desc, desc ? desc->bDescriptorType : 0); return -EINVAL; } @@ -874,7 +874,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, bool zlp_appended = false; unsigned rlen; - dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n", + dev_vdbg(dwc->dev, "%s: req %pK dma %08llx length %d%s%s\n", dep->name, req, (unsigned long long) dma, length, last ? " last" : "", chain ? " chain" : ""); @@ -1355,7 +1355,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (req->request.status == -EINPROGRESS) { ret = -EBUSY; - dev_err(dwc->dev, "%s: %p request already in queue", + dev_err(dwc->dev, "%s: %pK request already in queue", dep->name, req); return ret; } @@ -1485,7 +1485,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, if (!dep->endpoint.desc) { spin_unlock_irqrestore(&dwc->lock, flags); - dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", + dev_dbg(dwc->dev, "trying to queue request %pK to disabled %s\n", request, ep->name); return -ESHUTDOWN; } @@ -1497,7 +1497,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, return dwc->gadget.remote_wakeup ? -EAGAIN : -ENOTSUPP; } - dev_vdbg(dwc->dev, "queing request %p to %s length %d\n", + dev_vdbg(dwc->dev, "queing request %pK to %s length %d\n", request, ep->name, request->length); WARN(!dep->direction && (request->length % ep->desc->wMaxPacketSize), @@ -1544,7 +1544,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, dwc3_stop_active_transfer(dwc, dep->number); goto out1; } - dev_err(dwc->dev, "request %p was not queued to %s\n", + dev_err(dwc->dev, "request %pK was not queued to %s\n", request, ep->name); ret = -EINVAL; goto out0; @@ -2495,7 +2495,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, * would help. Lets hope that if this occurs, someone * fixes the root cause instead of looking away :) */ - dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n", + dev_err(dwc->dev, "%s's TRB (%pK) still owned by HW\n", dep->name, trb); count = trb->size & DWC3_TRB_SIZE_MASK; diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 5e29ddeb4d33..318db26f0296 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -892,7 +892,7 @@ int __init early_dbgp_init(char *s) set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); ehci_bar += bar_val & ~PAGE_MASK; - dbgp_printk("ehci_bar: %p\n", ehci_bar); + dbgp_printk("ehci_bar: %pK\n", ehci_bar); ehci_caps = ehci_bar; ehci_regs = ehci_bar + EARLY_HC_LENGTH(readl(&ehci_caps->hc_capbase)); diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index dd070ec952cb..9868f3a48136 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -475,7 +475,7 @@ static void android_work(struct work_struct *data) } pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]); } else { - pr_info("%s: did not send uevent (%d %d %p)\n", __func__, + pr_info("%s: did not send uevent (%d %d %pK)\n", __func__, dev->connected, dev->sw_connected, cdev->config); } } @@ -3870,7 +3870,7 @@ static int usb_diag_update_pid_and_serial_num(u32 pid, const char *snum) return -ENODEV; } - pr_debug("%s: dload:%p pid:%x serial_num:%s\n", + pr_debug("%s: dload:%pK pid:%x serial_num:%s\n", __func__, diag_dload, pid, snum); /* update pid */ diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c index 4148531f385c..4353e84d8a03 100644 --- a/drivers/usb/gadget/ci13xxx_msm_hsic.c +++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c @@ -814,7 +814,7 @@ static int msm_hsic_probe(struct platform_device *pdev) ret = -ENOMEM; goto error; } - dev_info(&pdev->dev, "HSIC Peripheral regs = %p\n", mhsic->regs); + dev_info(&pdev->dev, "HSIC Peripheral regs = %pK\n", mhsic->regs); ret = msm_hsic_config_gdsc(pdev, mhsic, true); if (ret) { diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 8dcae289040c..d4ed50e0b2c7 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -912,7 +912,7 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr, struct usb_gadget *gadget = &udc->gadget; int n = 0; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -954,7 +954,7 @@ static ssize_t show_driver(struct device *dev, struct device_attribute *attr, struct usb_gadget_driver *driver = udc->driver; int n = 0; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1169,7 +1169,7 @@ static void dbg_usb_op_fail(u8 addr, const char *name, list_for_each(ptr, &mep->qh.queue) { req = list_entry(ptr, struct ci13xxx_req, queue); scnprintf(msg, sizeof(msg), - "%pa:%08X:%08X\n", + "%pKa:%08X:%08X\n", &req->dma, req->ptr->next, req->ptr->token); dbg_print(addr, "REQ", 0, msg); @@ -1192,7 +1192,7 @@ static ssize_t show_events(struct device *dev, struct device_attribute *attr, unsigned long flags; unsigned i, j, n = 0; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1227,7 +1227,7 @@ static ssize_t store_events(struct device *dev, struct device_attribute *attr, { unsigned tty; - dbg_trace("[%s] %p, %d\n", __func__, buf, count); + dbg_trace("[%s] %pK, %d\n", __func__, buf, count); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); goto done; @@ -1259,7 +1259,7 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr, u32 intr; unsigned i, j, n = 0; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1332,7 +1332,7 @@ static ssize_t store_inters(struct device *dev, struct device_attribute *attr, unsigned long flags; unsigned en, bit; - dbg_trace("[%s] %p, %d\n", __func__, buf, count); + dbg_trace("[%s] %pK, %d\n", __func__, buf, count); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); goto done; @@ -1372,7 +1372,7 @@ static ssize_t show_port_test(struct device *dev, unsigned long flags; unsigned mode; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1398,7 +1398,7 @@ static ssize_t store_port_test(struct device *dev, unsigned long flags; unsigned mode; - dbg_trace("[%s] %p, %d\n", __func__, buf, count); + dbg_trace("[%s] %pK, %d\n", __func__, buf, count); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); goto done; @@ -1432,7 +1432,7 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, unsigned long flags; unsigned i, j, n = 0; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1472,7 +1472,7 @@ static ssize_t show_registers(struct device *dev, u32 *dump; unsigned i, k, n = 0; - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1514,7 +1514,7 @@ static ssize_t store_registers(struct device *dev, struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); unsigned long addr, data, flags; - dbg_trace("[%s] %p, %d\n", __func__, buf, count); + dbg_trace("[%s] %pK, %d\n", __func__, buf, count); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); goto done; @@ -1550,7 +1550,7 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr, struct ci13xxx_req *req = NULL; unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); - dbg_trace("[%s] %p\n", __func__, buf); + dbg_trace("[%s] %pK\n", __func__, buf); if (attr == NULL || buf == NULL) { dev_err(dev, "[%s] EINVAL\n", __func__); return 0; @@ -1661,7 +1661,7 @@ static ssize_t print_dtds(struct device *dev, list_for_each(ptr, &mEp->qh.queue) { req = list_entry(ptr, struct ci13xxx_req, queue); - pr_info("\treq:%pa next:%08x token:%08x page0:%08x status:%d\n", + pr_info("\treq:%pKa next:%08x token:%08x page0:%08x status:%d\n", &req->dma, req->ptr->next, req->ptr->token, req->ptr->page[0], req->req.status); } @@ -1965,7 +1965,7 @@ static void ep_prime_timer_func(unsigned long data) mep->qh.ptr->td.next, mep->qh.ptr->td.token); list_for_each(ptr, &mep->qh.queue) { req = list_entry(ptr, struct ci13xxx_req, queue); - pr_info("\treq:%pa:%08xtkn:%08xpage0:%08xsts:%d\n", + pr_info("\treq:%pKa:%08xtkn:%08xpage0:%08xsts:%d\n", &req->dma, req->ptr->next, req->ptr->token, req->ptr->page[0], req->req.status); @@ -2003,7 +2003,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) unsigned length = mReq->req.length; struct ci13xxx *udc = _udc; - trace("%p, %p", mEp, mReq); + trace("%pK, %pK", mEp, mReq); /* don't queue twice */ if (mReq->req.status == -EALREADY) @@ -2203,7 +2203,7 @@ done: */ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) { - trace("%p, %p", mEp, mReq); + trace("%pK, %pK", mEp, mReq); if (mReq->req.status != -EALREADY) return -EINVAL; @@ -2405,7 +2405,7 @@ static int _ep_nuke(struct ci13xxx_ep *mEp) __releases(mEp->lock) __acquires(mEp->lock) { - trace("%p", mEp); + trace("%pK", mEp); if (mEp == NULL) return -EINVAL; @@ -2452,7 +2452,7 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); unsigned long flags; - trace("%p", gadget); + trace("%pK", gadget); if (gadget == NULL) return -EINVAL; @@ -2501,7 +2501,7 @@ __acquires(udc->lock) { int retval; - trace("%p", udc); + trace("%pK", udc); if (udc == NULL) { err("EINVAL"); @@ -2600,7 +2600,7 @@ static void isr_suspend_handler(struct ci13xxx *udc) */ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) { - trace("%p, %p", ep, req); + trace("%pK, %pK", ep, req); if (ep == NULL || req == NULL) { err("EINVAL"); @@ -2627,7 +2627,7 @@ __acquires(mEp->lock) struct usb_request *req = udc->status; int dir, num, retval; - trace("%p, %p", mEp, setup); + trace("%pK, %pK", mEp, setup); if (mEp == NULL || setup == NULL) return -EINVAL; @@ -2676,7 +2676,7 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) struct ci13xxx *udc = req->context; unsigned long flags; - trace("%p, %p", ep, req); + trace("%pK, %pK", ep, req); spin_lock_irqsave(udc->lock, flags); if (udc->test_mode) @@ -2697,7 +2697,7 @@ __acquires(mEp->lock) int retval; struct ci13xxx_ep *mEp; - trace("%p", udc); + trace("%pK", udc); mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in; udc->status->context = udc; @@ -2728,7 +2728,7 @@ __acquires(mEp->lock) int req_dequeue = 1; struct ci13xxx *udc = _udc; - trace("%p", mEp); + trace("%pK", mEp); if (list_empty(&mEp->qh.queue)) return 0; @@ -2826,7 +2826,7 @@ __acquires(udc->lock) unsigned i; u8 tmode = 0; - trace("%p", udc); + trace("%pK", udc); if (udc == NULL) { err("EINVAL"); @@ -3112,7 +3112,7 @@ static int ep_enable(struct usb_ep *ep, unsigned long flags; unsigned mult = 0; - trace("ep = %p, desc = %p", ep, desc); + trace("ep = %pK, desc = %pK", ep, desc); if (ep == NULL || desc == NULL) return -EINVAL; @@ -3175,7 +3175,7 @@ static int ep_disable(struct usb_ep *ep) int direction, retval = 0; unsigned long flags; - trace("%p", ep); + trace("%pK", ep); if (ep == NULL) return -EINVAL; @@ -3222,7 +3222,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); struct ci13xxx_req *mReq = NULL; - trace("%p, %i", ep, gfp_flags); + trace("%pK, %i", ep, gfp_flags); if (ep == NULL) { err("EINVAL"); @@ -3258,7 +3258,7 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); unsigned long flags; - trace("%p, %p", ep, req); + trace("%pK, %pK", ep, req); if (ep == NULL || req == NULL) { err("EINVAL"); @@ -3293,7 +3293,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, unsigned long flags; struct ci13xxx *udc = _udc; - trace("%p, %p, %X", ep, req, gfp_flags); + trace("%pK, %pK, %X", ep, req, gfp_flags); spin_lock_irqsave(mEp->lock, flags); if (ep == NULL || req == NULL || mEp->desc == NULL) { @@ -3426,7 +3426,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) struct ci13xxx *udc = _udc; unsigned long flags; - trace("%p, %p", ep, req); + trace("%pK, %pK", ep, req); if (udc->udc_driver->in_lpm && udc->udc_driver->in_lpm(udc)) { dev_err(udc->transceiver->dev, @@ -3503,7 +3503,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) int direction, retval = 0; unsigned long flags; - trace("%p, %i", ep, value); + trace("%pK, %i", ep, value); if (ep == NULL || mEp->desc == NULL) return -EINVAL; @@ -3548,7 +3548,7 @@ static int ep_set_wedge(struct usb_ep *ep) struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); unsigned long flags; - trace("%p", ep); + trace("%pK", ep); if (ep == NULL || mEp->desc == NULL) return -EINVAL; @@ -3573,7 +3573,7 @@ static void ep_fifo_flush(struct usb_ep *ep) struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); unsigned long flags; - trace("%p", ep); + trace("%pK", ep); if (ep == NULL) { err("%02X: -EINVAL", _usb_addr(mEp)); @@ -3750,7 +3750,7 @@ static int ci13xxx_start(struct usb_gadget *gadget, int retval = -ENOMEM; bool put = false; - trace("%p", driver); + trace("%pK", driver); if (driver == NULL || driver->setup == NULL || @@ -3843,7 +3843,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, struct ci13xxx *udc = _udc; unsigned long flags; - trace("%p", driver); + trace("%pK", driver); if (driver == NULL || driver->unbind == NULL || @@ -3974,7 +3974,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, struct ci13xxx_platform_data *pdata; int retval = 0, i, j; - trace("%p, %p, %p", dev, regs, driver->name); + trace("%pK, %pK, %pK", dev, regs, driver->name); if (dev == NULL || regs == NULL || driver == NULL || driver->name == NULL) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index e3672923d54c..d9a35fee6370 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -181,7 +181,7 @@ int usb_add_function(struct usb_configuration *config, { int value = -EINVAL; - DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n", + DBG(config->cdev, "adding '%s'/%pK to config '%s'/%pK\n", function->name, function, config->label, config); @@ -216,7 +216,7 @@ int usb_add_function(struct usb_configuration *config, done: if (value) - DBG(config->cdev, "adding '%s'/%p --> %d\n", + DBG(config->cdev, "adding '%s'/%pK --> %d\n", function->name, function, value); return value; } @@ -764,7 +764,7 @@ static int set_config(struct usb_composite_dev *cdev, result = f->set_alt(f, tmp, 0); if (result < 0) { - DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", + DBG(cdev, "interface %d (%s/%pK) alt 0 --> %d\n", tmp, f->name, f, result); reset_config(cdev); @@ -839,7 +839,7 @@ int usb_add_config(struct usb_composite_dev *cdev, if (!bind) goto done; - DBG(cdev, "adding config #%u '%s'/%p\n", + DBG(cdev, "adding config #%u '%s'/%pK\n", config->bConfigurationValue, config->label, config); @@ -856,7 +856,7 @@ int usb_add_config(struct usb_composite_dev *cdev, struct usb_function, list); list_del(&f->list); if (f->unbind) { - DBG(cdev, "unbind function '%s'/%p\n", + DBG(cdev, "unbind function '%s'/%pK\n", f->name, f); f->unbind(config, f); /* may free memory for "f" */ @@ -867,7 +867,7 @@ int usb_add_config(struct usb_composite_dev *cdev, } else { unsigned i; - DBG(cdev, "cfg %d/%p speeds:%s%s%s\n", + DBG(cdev, "cfg %d/%pK speeds:%s%s%s\n", config->bConfigurationValue, config, config->superspeed ? " super" : "", config->highspeed ? " high" : "", @@ -882,7 +882,7 @@ int usb_add_config(struct usb_composite_dev *cdev, if (!f) continue; - DBG(cdev, " interface %d = %s/%p\n", + DBG(cdev, " interface %d = %s/%pK\n", i, f->name, f); } } @@ -910,13 +910,13 @@ static void unbind_config(struct usb_composite_dev *cdev, struct usb_function, list); list_del(&f->list); if (f->unbind) { - DBG(cdev, "unbind function '%s'/%p\n", f->name, f); + DBG(cdev, "unbind function '%s'/%pK\n", f->name, f); f->unbind(config, f); /* may free memory for "f" */ } } if (config->unbind) { - DBG(cdev, "unbind config '%s'/%p\n", config->label, config); + DBG(cdev, "unbind config '%s'/%pK\n", config->label, config); config->unbind(config); /* may free memory for "c" */ } diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 3dab424515ef..c1d2f8f30b12 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -752,7 +752,7 @@ static void purge_configs_funcs(struct gadget_info *gi) list_move_tail(&f->list, &cfg->func_list); if (f->unbind) { dev_err(&gi->cdev.gadget->dev, "unbind function" - " '%s'/%p\n", f->name, f); + " '%s'/%pK\n", f->name, f); f->unbind(c, f); } } diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index ac0e79e2c2e9..00457123eca1 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -637,7 +637,7 @@ static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req, return -ESHUTDOWN; #if 0 - dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", + dev_dbg(udc_dev(dum), "ep %pK queue req %pK to %s, len %d buf %pK\n", ep, _req, _ep->name, _req->length, _req->buf); #endif _req->status = -EINPROGRESS; @@ -702,7 +702,7 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req) if (retval == 0) { dev_dbg(udc_dev(dum), - "dequeued req %p from %s, len %d buf %p\n", + "dequeued req %pK from %s, len %d buf %pK\n", req, _ep->name, _req->length, _req->buf); _req->complete(_ep, _req); } @@ -1727,7 +1727,7 @@ restart: if (!ep) { /* set_configuration() disagreement */ dev_dbg(dummy_dev(dum_hcd), - "no ep configured for urb %p\n", + "no ep configured for urb %pK\n", urb); status = -EPROTO; goto return_urb; @@ -1742,7 +1742,7 @@ restart: } if (ep->halted && !ep->setup_stage) { /* NOTE: must not be iso! */ - dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n", + dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %pK\n", ep->ep.name, urb); status = -EPIPE; goto return_urb; @@ -1759,7 +1759,7 @@ restart: list_for_each_entry(req, &ep->queue, queue) { list_del_init(&req->queue); req->req.status = -EOVERFLOW; - dev_dbg(udc_dev(dum), "stale req = %p\n", + dev_dbg(udc_dev(dum), "stale req = %pK\n", req); spin_unlock(&dum->lock); @@ -2252,7 +2252,7 @@ static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb) int ep = usb_pipeendpoint(urb->pipe); return snprintf(buf, size, - "urb/%p %s ep%d%s%s len %d/%d\n", + "urb/%pK %s ep%d%s%s len %d/%d\n", urb, ({ char *s; switch (urb->dev->speed) { diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index 3b194b6ec863..2210b6befc9e 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -539,7 +539,7 @@ static int create_bulk_endpoints(struct acc_dev *dev, struct usb_ep *ep; int i; - DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); + DBG(cdev, "create_bulk_endpoints dev: %pK\n", dev); ep = usb_ep_autoconfig(cdev->gadget, in_desc); if (!ep) { @@ -642,7 +642,7 @@ requeue_req: r = -EIO; goto done; } else { - pr_debug("rx %p queue\n", req); + pr_debug("rx %pK queue\n", req); } /* wait for a request to complete */ @@ -665,7 +665,7 @@ copy_data: if (req->actual == 0) goto requeue_req; - pr_debug("rx %p %u\n", req, req->actual); + pr_debug("rx %pK %u\n", req, req->actual); xfer = (req->actual < count) ? req->actual : count; r = xfer; if (copy_to_user(buf, req->buf, xfer)) @@ -963,7 +963,7 @@ acc_function_bind(struct usb_configuration *c, struct usb_function *f) int id; int ret; - DBG(cdev, "acc_function_bind dev: %p\n", dev); + DBG(cdev, "acc_function_bind dev: %pK\n", dev); ret = hid_register_driver(&acc_hid_driver); if (ret) @@ -1129,7 +1129,7 @@ static void acc_hid_work(struct work_struct *data) list_for_each_safe(entry, temp, &new_list) { hid = list_entry(entry, struct acc_hid_dev, list); if (acc_hid_init(hid)) { - pr_err("can't add HID device %p\n", hid); + pr_err("can't add HID device %pK\n", hid); acc_hid_delete(hid); } else { spin_lock_irqsave(&dev->lock, flags); diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 32bdc1c54fec..30a22dcdbb49 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -137,7 +137,7 @@ static int acm_port_connect(struct f_acm *acm) port_num = gacm_ports[acm->port_num].client_port_num; - pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_port_no:%d\n", + pr_debug("%s: transport:%s f_acm:%pK gserial:%pK port_num:%d cl_port_no:%d\n", __func__, xport_to_str(acm->transport), acm, &acm->port, acm->port_num, port_num); @@ -163,7 +163,7 @@ static int acm_port_disconnect(struct f_acm *acm) port_num = gacm_ports[acm->port_num].client_port_num; - pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_pno:%d\n", + pr_debug("%s: transport:%s f_acm:%pK gserial:%pK port_num:%d cl_pno:%d\n", __func__, xport_to_str(acm->transport), acm, &acm->port, acm->port_num, port_num); @@ -827,7 +827,7 @@ fail: if (acm->port.in) acm->port.in->driver_data = NULL; - ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); + ERROR(cdev, "%s/%pK: can't bind, err %d\n", f->name, f, status); return status; } diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 6fac2ecc5f4c..7f7acc4c41ad 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1444,14 +1444,14 @@ static void ffs_data_clear(struct ffs_data *ffs) { ENTER(); - pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n", __func__, + pr_debug("%s: ffs->gadget= %pK, ffs->flags= %lu\n", __func__, ffs->gadget, ffs->flags); if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags)) functionfs_closed_callback(ffs); /* Dump ffs->gadget and ffs->flags */ if (ffs->gadget) - pr_err("%s: ffs:%p ffs->gadget= %p, ffs->flags= %lu\n", + pr_err("%s: ffs:%pK ffs->gadget= %pK, ffs->flags= %lu\n", __func__, ffs, ffs->gadget, ffs->flags); BUG_ON(ffs->gadget); diff --git a/drivers/usb/gadget/f_gps.c b/drivers/usb/gadget/f_gps.c index ae34229ac356..350bd1bf5bb9 100644 --- a/drivers/usb/gadget/f_gps.c +++ b/drivers/usb/gadget/f_gps.c @@ -293,7 +293,7 @@ gps_set_alt(struct usb_function *f, unsigned intf, unsigned alt) int ret; struct list_head *cpkt; - pr_debug("%s:dev:%p\n", __func__, dev); + pr_debug("%s:dev:%pK\n", __func__, dev); if (dev->notify->driver_data) usb_ep_disable(dev->notify); @@ -334,7 +334,7 @@ static void gps_ctrl_response_available(struct f_gps *dev) int ret; struct rmnet_ctrl_pkt *cpkt; - pr_debug("%s:dev:%p\n", __func__, dev); + pr_debug("%s:dev:%pK\n", __func__, dev); spin_lock_irqsave(&dev->lock, flags); if (!atomic_read(&dev->online) || !req || !req->buf) { @@ -376,7 +376,7 @@ static void gps_connect(struct grmnet *gr) struct f_gps *dev; if (!gr) { - pr_err("%s: Invalid grmnet:%p\n", __func__, gr); + pr_err("%s: Invalid grmnet:%pK\n", __func__, gr); return; } @@ -392,7 +392,7 @@ static void gps_disconnect(struct grmnet *gr) int status; if (!gr) { - pr_err("%s: Invalid grmnet:%p\n", __func__, gr); + pr_err("%s: Invalid grmnet:%pK\n", __func__, gr); return; } @@ -434,7 +434,7 @@ gps_send_cpkt_response(void *gr, void *buf, size_t len) unsigned long flags; if (!gr || !buf) { - pr_err("%s: Invalid grmnet/buf, grmnet:%p buf:%p\n", + pr_err("%s: Invalid grmnet/buf, grmnet:%pK buf:%pK\n", __func__, gr, buf); return -ENODEV; } @@ -448,7 +448,7 @@ gps_send_cpkt_response(void *gr, void *buf, size_t len) dev = port_to_gps(gr); - pr_debug("%s: dev:%p\n", __func__, dev); + pr_debug("%s: dev:%pK\n", __func__, dev); if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) { gps_free_ctrl_pkt(cpkt); @@ -475,7 +475,7 @@ gps_cmd_complete(struct usb_ep *ep, struct usb_request *req) return; } - pr_debug("%s: dev:%p\n", __func__, dev); + pr_debug("%s: dev:%pK\n", __func__, dev); cdev = dev->cdev; @@ -490,7 +490,7 @@ static void gps_notify_complete(struct usb_ep *ep, struct usb_request *req) unsigned long flags; struct rmnet_ctrl_pkt *cpkt; - pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num); + pr_debug("%s: dev:%pK port#%d\n", __func__, dev, dev->port_num); switch (status) { case -ECONNRESET: @@ -536,7 +536,7 @@ gps_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) u16 w_length = le16_to_cpu(ctrl->wLength); int ret = -EOPNOTSUPP; - pr_debug("%s:dev:%p\n", __func__, dev); + pr_debug("%s:dev:%pK\n", __func__, dev); if (!atomic_read(&dev->online)) { pr_debug("%s: usb cable is not connected\n", __func__); @@ -706,7 +706,7 @@ static int gps_bind_config(struct usb_configuration *c) struct usb_function *f; unsigned long flags; - pr_debug("%s: usb config:%p\n", __func__, c); + pr_debug("%s: usb config:%pK\n", __func__, c); if (gps_string_defs[0].id == 0) { status = usb_string_id(c->cdev); diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c index f74abece2196..b7f125f2bd52 100644 --- a/drivers/usb/gadget/f_mtp.c +++ b/drivers/usb/gadget/f_mtp.c @@ -490,7 +490,7 @@ static int mtp_create_bulk_endpoints(struct mtp_dev *dev, size_t extra_buf_alloc = cdev->gadget->extra_buf_alloc; int i; - DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); + DBG(cdev, "create_bulk_endpoints dev: %pK\n", dev); ep = usb_ep_autoconfig(cdev->gadget, in_desc); if (!ep) { @@ -625,7 +625,7 @@ requeue_req: r = -EIO; goto done; } else { - DBG(cdev, "rx %p queue\n", req); + DBG(cdev, "rx %pK queue\n", req); } /* wait for a request to complete */ @@ -650,7 +650,7 @@ requeue_req: if (req->actual == 0) goto requeue_req; - DBG(cdev, "rx %p %d\n", req, req->actual); + DBG(cdev, "rx %pK %d\n", req, req->actual); xfer = (req->actual < count) ? req->actual : count; r = xfer; if (copy_to_user(buf, req->buf, xfer)) @@ -925,7 +925,7 @@ static void receive_file_work(struct work_struct *data) } if (write_req) { - DBG(cdev, "rx %p %d\n", write_req, write_req->actual); + DBG(cdev, "rx %pK %d\n", write_req, write_req->actual); start_time = ktime_get(); ret = vfs_write(filp, write_req->buf, write_req->actual, &offset); @@ -1343,7 +1343,7 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f) int ret; dev->cdev = cdev; - DBG(cdev, "mtp_function_bind dev: %p\n", dev); + DBG(cdev, "mtp_function_bind dev: %pK\n", dev); /* allocate interface ID(s) */ id = usb_interface_id(c, f); diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c index 8448d576611d..ea06482da8e1 100644 --- a/drivers/usb/gadget/f_qdss.c +++ b/drivers/usb/gadget/f_qdss.c @@ -674,7 +674,7 @@ static void usb_qdss_connect_work(struct work_struct *work) dxport = qdss_ports[qdss->port_num].data_xport; ctrl_xport = qdss_ports[qdss->port_num].ctrl_xport; port_num = qdss_ports[qdss->port_num].data_xport_num; - pr_debug("%s: data xport: %s dev: %p portno: %d\n", + pr_debug("%s: data xport: %s dev: %pK portno: %d\n", __func__, xport_to_str(dxport), qdss, qdss->port_num); if (qdss->port_num >= nr_qdss_ports) { @@ -779,7 +779,7 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt) dxport = qdss_ports[qdss->port_num].data_xport; - pr_debug("qdss_set_alt qdss pointer = %p\n", qdss); + pr_debug("qdss_set_alt qdss pointer = %pK\n", qdss); qdss->gadget = gadget; diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c index 239729874ee6..baaf15f385de 100644 --- a/drivers/usb/gadget/f_rmnet.c +++ b/drivers/usb/gadget/f_rmnet.c @@ -409,7 +409,7 @@ static int gport_rmnet_connect(struct f_rmnet *dev, unsigned intf) struct usb_gadget *gadget = dev->cdev->gadget; void *net; - pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n", + pr_debug("%s: ctrl xport: %s data xport: %s dev: %pK portno: %d\n", __func__, xport_to_str(cxport), xport_to_str(dxport), dev, dev->port_num); @@ -559,7 +559,7 @@ static int gport_rmnet_disconnect(struct f_rmnet *dev) enum transport_type cxport = rmnet_ports[dev->port_num].ctrl_xport; enum transport_type dxport = rmnet_ports[dev->port_num].data_xport; - pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n", + pr_debug("%s: ctrl xport: %s data xport: %s dev: %pK portno: %d\n", __func__, xport_to_str(cxport), xport_to_str(dxport), dev, dev->port_num); @@ -659,7 +659,7 @@ static void frmnet_suspend(struct usb_function *f) else remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup; - pr_debug("%s: data xport: %s dev: %p portno: %d remote_wakeup: %d\n", + pr_debug("%s: data xport: %s dev: %pK portno: %d remote_wakeup: %d\n", __func__, xport_to_str(dxport), dev, dev->port_num, remote_wakeup_allowed); @@ -684,7 +684,7 @@ static void frmnet_suspend(struct usb_function *f) */ dev->in_ep_desc_backup = dev->port.in->desc; dev->out_ep_desc_backup = dev->port.out->desc; - pr_debug("in_ep_desc_bkup = %p, out_ep_desc_bkup = %p", + pr_debug("in_ep_desc_bkup = %pK, out_ep_desc_bkup = %pK", dev->in_ep_desc_backup, dev->out_ep_desc_backup); pr_debug("%s(): Disconnecting\n", __func__); gport_rmnet_disconnect(dev); @@ -717,7 +717,7 @@ static void frmnet_resume(struct usb_function *f) else remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup; - pr_debug("%s: data xport: %s dev: %p portno: %d remote_wakeup: %d\n", + pr_debug("%s: data xport: %s dev: %pK portno: %d remote_wakeup: %d\n", __func__, xport_to_str(dxport), dev, dev->port_num, remote_wakeup_allowed); @@ -786,7 +786,7 @@ frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt) int ret; struct list_head *cpkt; - pr_debug("%s:dev:%p port#%d\n", __func__, dev, dev->port_num); + pr_debug("%s:dev:%pK port#%d\n", __func__, dev, dev->port_num); if (dev->notify->driver_data) { pr_debug("%s: reset port:%d\n", __func__, dev->port_num); @@ -849,7 +849,7 @@ static void frmnet_ctrl_response_available(struct f_rmnet *dev) int ret; struct rmnet_ctrl_pkt *cpkt; - pr_debug("%s:dev:%p portno#%d\n", __func__, dev, dev->port_num); + pr_debug("%s:dev:%pK portno#%d\n", __func__, dev, dev->port_num); spin_lock_irqsave(&dev->lock, flags); if (!atomic_read(&dev->online) || !req || !req->buf) { @@ -898,7 +898,7 @@ static void frmnet_connect(struct grmnet *gr) struct f_rmnet *dev; if (!gr) { - pr_err("%s: Invalid grmnet:%p\n", __func__, gr); + pr_err("%s: Invalid grmnet:%pK\n", __func__, gr); return; } @@ -914,7 +914,7 @@ static void frmnet_disconnect(struct grmnet *gr) int status; if (!gr) { - pr_err("%s: Invalid grmnet:%p\n", __func__, gr); + pr_err("%s: Invalid grmnet:%pK\n", __func__, gr); return; } @@ -956,7 +956,7 @@ frmnet_send_cpkt_response(void *gr, void *buf, size_t len) unsigned long flags; if (!gr || !buf) { - pr_err("%s: Invalid grmnet/buf, grmnet:%p buf:%p\n", + pr_err("%s: Invalid grmnet/buf, grmnet:%pK buf:%pK\n", __func__, gr, buf); return -ENODEV; } @@ -970,7 +970,7 @@ frmnet_send_cpkt_response(void *gr, void *buf, size_t len) dev = port_to_rmnet(gr); - pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num); + pr_debug("%s: dev:%pK port#%d\n", __func__, dev, dev->port_num); if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) { rmnet_free_ctrl_pkt(cpkt); @@ -998,7 +998,7 @@ frmnet_cmd_complete(struct usb_ep *ep, struct usb_request *req) return; } - pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num); + pr_debug("%s: dev:%pK port#%d\n", __func__, dev, dev->port_num); cdev = dev->cdev; @@ -1015,7 +1015,7 @@ static void frmnet_notify_complete(struct usb_ep *ep, struct usb_request *req) unsigned long flags; struct rmnet_ctrl_pkt *cpkt; - pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num); + pr_debug("%s: dev:%pK port#%d\n", __func__, dev, dev->port_num); switch (status) { case -ECONNRESET: @@ -1084,7 +1084,7 @@ frmnet_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) u16 w_length = le16_to_cpu(ctrl->wLength); int ret = -EOPNOTSUPP; - pr_debug("%s:dev:%p port#%d\n", __func__, dev, dev->port_num); + pr_debug("%s:dev:%pK port#%d\n", __func__, dev, dev->port_num); if (!atomic_read(&dev->online)) { pr_warning("%s: usb cable is not connected\n", __func__); @@ -1310,7 +1310,7 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno) struct usb_function *f; unsigned long flags; - pr_debug("%s: usb config:%p\n", __func__, c); + pr_debug("%s: usb config:%pK\n", __func__, c); if (portno >= nr_rmnet_ports) { pr_err("%s: supporting ports#%u port_id:%u\n", __func__, diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 9c270ad4a359..f37b36e2dea4 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -413,7 +413,7 @@ static int gport_connect(struct f_gser *gser) unsigned port_num; int ret; - pr_debug("%s: transport: %s f_gser: %p gserial: %p port_num: %d\n", + pr_debug("%s: transport: %s f_gser: %pK gserial: %pK port_num: %d\n", __func__, xport_to_str(gser->transport), gser, &gser->port, gser->port_num); @@ -464,7 +464,7 @@ static int gport_disconnect(struct f_gser *gser) port_num = gserial_ports[gser->port_num].client_port_num; - pr_debug("%s: transport: %s f_gser: %p gserial: %p port_num: %d\n", + pr_debug("%s: transport: %s f_gser: %pK gserial: %pK port_num: %d\n", __func__, xport_to_str(gser->transport), gser, &gser->port, gser->port_num); @@ -656,6 +656,7 @@ static void gser_disable(struct usb_function *f) #endif gser->online = 0; } + #ifdef CONFIG_MODEM_SUPPORT static int gser_notify(struct f_gser *gser, u8 type, u16 value, void *data, unsigned length) diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 42a30903d4fd..6909702c4c63 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -310,7 +310,7 @@ nonblock: // case STATE_EP_DISABLED: /* "can't happen" */ // case STATE_EP_READY: /* "can't happen" */ default: /* error! */ - pr_debug ("%s: ep %p not available, state %d\n", + pr_debug ("%s: ep %pK not available, state %d\n", shortname, epdata, epdata->state); // FALLTHROUGH case STATE_EP_UNBOUND: /* clean disconnect */ @@ -1934,7 +1934,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) fail: spin_unlock_irq (&dev->lock); - pr_debug ("%s: %s fail %Zd, %p\n", shortname, __func__, value, dev); + pr_debug ("%s: %s fail %Zd, %pK\n", shortname, __func__, value, dev); kfree (dev->buf); dev->buf = NULL; return value; diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c index 4ab6d0a99ebd..eb20bcb7d98e 100644 --- a/drivers/usb/gadget/u_bam.c +++ b/drivers/usb/gadget/u_bam.c @@ -226,7 +226,7 @@ static int gbam_alloc_requests(struct usb_ep *ep, struct list_head *head, { int i; struct usb_request *req; - pr_debug("%s: ep:%p head:%p num:%d cb:%p", __func__, + pr_debug("%s: ep:%pK head:%pK num:%d cb:%pK", __func__, ep, head, num, cb); for (i = 0; i < num; i++) { @@ -465,7 +465,7 @@ void gbam_data_recv_cb(void *p, struct sk_buff *skb) if (!skb) return; - pr_debug("%s: p:%p#%d d:%p skb_len:%d\n", __func__, + pr_debug("%s: p:%pK#%d d:%pK skb_len:%d\n", __func__, port, port->port_num, d, skb->len); spin_lock_irqsave(&port->port_lock_dl, flags); @@ -506,7 +506,7 @@ void gbam_data_write_done(void *p, struct sk_buff *skb) d->pending_bytes_with_bam -= skb->len; gbam_free_skb_to_pool(port, skb); - pr_debug("%s:port:%p d:%p tom:%lu ppkt:%u pbytes:%u pno:%d\n", __func__, + pr_debug("%s:port:%pK d:%pK tom:%lu ppkt:%u pbytes:%u pno:%d\n", __func__, port, d, d->to_modem, d->pending_pkts_with_bam, d->pending_bytes_with_bam, port->port_num); @@ -581,7 +581,7 @@ static void gbam_data_write_tobam(struct work_struct *w) d->pending_bytes_with_bam += skb->len; d->to_modem++; - pr_debug("%s: port:%p d:%p tom:%lu ppkts:%u pbytes:%u pno:%d\n", + pr_debug("%s: port:%pK d:%pK tom:%lu ppkts:%u pbytes:%u pno:%d\n", __func__, port, d, d->to_modem, d->pending_pkts_with_bam, d->pending_bytes_with_bam, port->port_num); @@ -1074,7 +1074,7 @@ static void gbam_start_io(struct gbam_port *port) { unsigned long flags; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (_gbam_start_io(port, true)) return; @@ -1785,7 +1785,7 @@ static int gbam_port_alloc(int portno) pdrv->driver.owner = THIS_MODULE; platform_driver_register(pdrv); - pr_debug("%s: port:%p portno:%d\n", __func__, port, portno); + pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno); return 0; } @@ -1825,7 +1825,7 @@ static int gbam2bam_port_alloc(int portno) INIT_LIST_HEAD(&d->rx_idle); INIT_WORK(&d->write_tobam_w, gbam_data_write_tobam); - pr_debug("%s: port:%p portno:%d\n", __func__, port, portno); + pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno); return 0; } @@ -1857,7 +1857,7 @@ static ssize_t gbam_read_stats(struct file *file, char __user *ubuf, d = &port->data_ch; temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp, - "#PORT:%d port:%p data_ch:%p#\n" + "#PORT:%d port:%pK data_ch:%pK#\n" "dpkts_to_usbhost: %lu\n" "dpkts_to_modem: %lu\n" "dpkts_pwith_bam: %u\n" @@ -1980,7 +1980,7 @@ void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans) unsigned long flags, flags_ul, flags_dl; struct bam_ch_info *d; - pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num); + pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, port_num); if (trans == USB_GADGET_XPORT_BAM && port_num >= n_bam_ports) { @@ -2112,7 +2112,7 @@ int gbam_connect(struct grmnet *gr, u8 port_num, int ret; unsigned long flags, flags_ul; - pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num); + pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, port_num); if (!gr) { pr_err("%s: grmnet port is null\n", __func__); @@ -2257,7 +2257,7 @@ int gbam_connect(struct grmnet *gr, u8 port_num, ret = usb_ep_enable(gr->in); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:IN ep:%p", + pr_err("%s: usb_ep_enable failed eptype:IN ep:%pK", __func__, gr->in); goto exit; } @@ -2271,7 +2271,7 @@ int gbam_connect(struct grmnet *gr, u8 port_num, if (gr->out) { ret = usb_ep_enable(gr->out); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p", + pr_err("%s: usb_ep_enable failed eptype:OUT ep:%pK", __func__, gr->out); gr->in->driver_data = 0; goto exit; diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c index 81f186b5f7df..d7b3e84646c0 100644 --- a/drivers/usb/gadget/u_bam_data.c +++ b/drivers/usb/gadget/u_bam_data.c @@ -168,7 +168,7 @@ static int bam_data_alloc_requests(struct usb_ep *ep, struct list_head *head, struct bam_data_ch_info *d = &port->data_ch; struct usb_request *req; - pr_debug("%s: ep:%p head:%p num:%d cb:%p", __func__, + pr_debug("%s: ep:%pK head:%pK num:%d cb:%pK", __func__, ep, head, num, cb); if (d->alloc_rx_reqs) { @@ -294,7 +294,7 @@ static void bam_data_write_done(void *p, struct sk_buff *skb) d->pending_with_bam--; - pr_debug("%s: port:%p d:%p pbam:%u, pno:%d\n", __func__, + pr_debug("%s: port:%pK d:%pK pbam:%u, pno:%d\n", __func__, port, d, d->pending_with_bam, port->port_num); spin_unlock_irqrestore(&port->port_lock, flags); @@ -528,7 +528,7 @@ static void bam_data_write_toipa(struct work_struct *w) d->pending_with_bam++; - pr_debug("%s: port:%p d:%p pbam:%u pno:%d\n", __func__, + pr_debug("%s: port:%pK d:%pK pbam:%u pno:%d\n", __func__, port, d, d->pending_with_bam, port->port_num); spin_unlock_irqrestore(&port->port_lock, flags); @@ -804,7 +804,7 @@ static void bam2bam_data_disconnect_work(struct work_struct *w) usb_gadget_autopm_put_async(port->gadget); spin_unlock_irqrestore(&port->port_lock, flags); - pr_debug("Disconnect workqueue done (port %p)\n", port); + pr_debug("Disconnect workqueue done (port %pK)\n", port); } /* * This function configured data fifo based on index passed to get bam2bam @@ -1171,7 +1171,7 @@ static void bam2bam_data_connect_work(struct work_struct *w) bam_data_start_rx_transfers(d, port); bam_data_start_endless_tx(port); - pr_debug("Connect workqueue done (port %p)", port); + pr_debug("Connect workqueue done (port %pK)", port); return; disconnect_ipa: @@ -1210,7 +1210,7 @@ void bam_data_start_rx_tx(u8 port_num) } if (!d->rx_req || !d->tx_req) { - pr_err("%s: No request d->rx_req=%p, d->tx_req=%p", __func__, + pr_err("%s: No request d->rx_req=%pK, d->tx_req=%pK", __func__, d->rx_req, d->tx_req); goto out; } @@ -1364,7 +1364,7 @@ void bam_data_disconnect(struct data_port *gr, enum function_type func, return; } - pr_debug("dev:%p port number:%d\n", gr, port_num); + pr_debug("dev:%pK port number:%d\n", gr, port_num); if (!gr) { pr_err("data port is null\n"); @@ -1516,7 +1516,7 @@ int bam_data_connect(struct data_port *gr, enum transport_type trans, return -EINVAL; } - pr_debug("dev:%p port#%d\n", gr, port_num); + pr_debug("dev:%pK port#%d\n", gr, port_num); bam_name = (trans == USB_GADGET_XPORT_BAM2BAM_IPA) ? IPA_P_BAM : A2_P_BAM; @@ -1604,7 +1604,7 @@ int bam_data_connect(struct data_port *gr, enum transport_type trans, ret = usb_ep_enable(gr->in); if (ret) { - pr_err("usb_ep_enable failed eptype:IN ep:%p", gr->in); + pr_err("usb_ep_enable failed eptype:IN ep:%pK", gr->in); goto exit; } @@ -1612,7 +1612,7 @@ int bam_data_connect(struct data_port *gr, enum transport_type trans, ret = usb_ep_enable(gr->out); if (ret) { - pr_err("usb_ep_enable failed eptype:OUT ep:%p", gr->out); + pr_err("usb_ep_enable failed eptype:OUT ep:%pK", gr->out); goto disable_in_ep; } @@ -1894,7 +1894,7 @@ void bam_data_suspend(struct data_port *port_usb, u8 dev_port_num, port_usb->in_ep_desc_backup = port_usb->in->desc; port_usb->out_ep_desc_backup = port_usb->out->desc; - pr_debug("in_ep_desc_backup = %p, out_ep_desc_backup = %p", + pr_debug("in_ep_desc_backup = %pK, out_ep_desc_backup = %pK", port_usb->in_ep_desc_backup, port_usb->out_ep_desc_backup); @@ -1935,7 +1935,7 @@ void bam_data_resume(struct data_port *port_usb, u8 dev_port_num, port_usb->in->desc = port_usb->in_ep_desc_backup; port_usb->out->desc = port_usb->out_ep_desc_backup; - pr_debug("in_ep_desc_backup = %p, out_ep_desc_backup = %p", + pr_debug("in_ep_desc_backup = %pK, out_ep_desc_backup = %pK", port_usb->in_ep_desc_backup, port_usb->out_ep_desc_backup); diff --git a/drivers/usb/gadget/u_ctrl_hsuart.c b/drivers/usb/gadget/u_ctrl_hsuart.c index c998a2d77e6b..f8722be9a255 100644 --- a/drivers/usb/gadget/u_ctrl_hsuart.c +++ b/drivers/usb/gadget/u_ctrl_hsuart.c @@ -233,7 +233,7 @@ static void ghsuart_ctrl_connect_w(struct work_struct *w) if (!port || !test_bit(CH_READY, &port->channel_sts)) return; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (test_bit(CH_OPENED, &port->channel_sts)) { retval = wait_for_completion_timeout( @@ -439,7 +439,7 @@ static int ghsuart_ctrl_port_alloc(int portno, enum gadget_type gtype) err = platform_driver_register(pdrv); if (unlikely(err < 0)) return err; - pr_debug("%s: port:%p portno:%d\n", __func__, port, portno); + pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno); return 0; } @@ -502,7 +502,7 @@ static ssize_t ghsuart_ctrl_read_stats(struct file *file, char __user *ubuf, spin_lock_irqsave(&port->port_lock, flags); temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp, - "#PORT:%d port: %p\n" + "#PORT:%d port: %pK\n" "to_usbhost: %lu\n" "to_modem: %lu\n" "cpkt_drp_cnt: %lu\n" diff --git a/drivers/usb/gadget/u_ctrl_qti.c b/drivers/usb/gadget/u_ctrl_qti.c index 0fc2adcd62f6..c719ad730752 100644 --- a/drivers/usb/gadget/u_ctrl_qti.c +++ b/drivers/usb/gadget/u_ctrl_qti.c @@ -88,7 +88,7 @@ static void qti_ctrl_queue_notify(struct qti_ctrl_port *port) spin_lock_irqsave(&port->lock, flags); if (!port->is_open) { - pr_err("%s: rmnet ctrl file handler %p is not open", + pr_err("%s: rmnet ctrl file handler %pK is not open", __func__, port); spin_unlock_irqrestore(&port->lock, flags); return; @@ -141,7 +141,7 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len) /* drop cpkt if port is not open */ if (!port->is_open) { - pr_debug("rmnet file handler %p(index=%d) is not open", + pr_debug("rmnet file handler %pK(index=%d) is not open", port, port->index); port->drp_cpkt_cnt++; spin_unlock_irqrestore(&port->lock, flags); @@ -185,7 +185,7 @@ int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf, struct gqdss *g_dpl = NULL; unsigned long flags; - pr_debug("%s: gtype:%d gadget:%p\n", __func__, gtype, gr); + pr_debug("%s: gtype:%d gadget:%pK\n", __func__, gtype, gr); if (port_num >= NR_QTI_PORTS) { pr_err("%s: Invalid QTI port %d\n", __func__, port_num); return -ENODEV; @@ -261,7 +261,7 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num) struct grmnet *g_rmnet = NULL; struct gqdss *g_dpl = NULL; - pr_debug("%s: gadget:%p\n", __func__, gr); + pr_debug("%s: gadget:%pK\n", __func__, gr); if (port_num >= NR_QTI_PORTS) { pr_err("%s: Invalid QTI port %d\n", __func__, port_num); @@ -659,7 +659,7 @@ static int qti_ctrl_read_stats(struct seq_file *s, void *unused) continue; spin_lock_irqsave(&port->lock, flags); - seq_printf(s, "\n#PORT:%d port: %p\n", i, port); + seq_printf(s, "\n#PORT:%d port: %pK\n", i, port); seq_printf(s, "name: %s\n", port->name); seq_printf(s, "host_to_modem: %d\n", port->host_to_modem); diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c index 07bb5a8fac5f..c02c798a82ae 100644 --- a/drivers/usb/gadget/u_data_hsic.c +++ b/drivers/usb/gadget/u_data_hsic.c @@ -156,7 +156,7 @@ static int ghsic_data_alloc_requests(struct usb_ep *ep, struct list_head *head, struct usb_request *req; unsigned long flags; - pr_debug("%s: ep:%s head:%p num:%d cb:%p", __func__, + pr_debug("%s: ep:%s head:%pK num:%d cb:%pK", __func__, ep->name, head, num, cb); for (i = 0; i < num; i++) { @@ -272,7 +272,7 @@ static int ghsic_data_receive(void *p, void *data, size_t len) return -ENOTCONN; } - pr_debug("%s: p:%p#%d skb_len:%d\n", __func__, + pr_debug("%s: p:%pK#%d skb_len:%d\n", __func__, port, port->port_num, skb->len); spin_lock_irqsave(&port->tx_lock, flags); @@ -316,7 +316,7 @@ static void ghsic_data_write_tomdm(struct work_struct *w) } while ((skb = __skb_dequeue(&port->rx_skb_q))) { - pr_debug("%s: port:%p tom:%lu pno:%d\n", __func__, + pr_debug("%s: port:%pK tom:%lu pno:%d\n", __func__, port, port->to_modem, port->port_num); info = (struct timestamp_info *)skb->cb; @@ -424,7 +424,7 @@ static void ghsic_data_start_rx(struct gdata_port *port) struct timestamp_info *info; unsigned int created; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (!port) return; @@ -481,7 +481,7 @@ static void ghsic_data_start_io(struct gdata_port *port) struct usb_ep *ep_out, *ep_in; int ret; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (!port) return; @@ -508,7 +508,7 @@ static void ghsic_data_start_io(struct gdata_port *port) spin_lock_irqsave(&port->tx_lock, flags); ep_in = port->in; spin_unlock_irqrestore(&port->tx_lock, flags); - pr_debug("%s: ep_in:%p\n", __func__, ep_in); + pr_debug("%s: ep_in:%pK\n", __func__, ep_in); if (!ep_in) { spin_lock_irqsave(&port->rx_lock, flags); @@ -543,7 +543,7 @@ static void ghsic_data_connect_w(struct work_struct *w) !test_bit(CH_READY, &port->bridge_sts)) return; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); ret = data_bridge_open(&port->brdg); if (ret) { @@ -855,14 +855,14 @@ int ghsic_data_connect(void *gptr, int port_num) ret = usb_ep_enable(port->in); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:IN ep:%p", + pr_err("%s: usb_ep_enable failed eptype:IN ep:%pK", __func__, port->in); goto fail; } if (port->out) { ret = usb_ep_enable(port->out); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p", + pr_err("%s: usb_ep_enable failed eptype:OUT ep:%pK", __func__, port->out); usb_ep_disable(port->in); goto fail; @@ -939,7 +939,7 @@ static void dbg_timestamp(char *event, struct sk_buff * skb) write_lock_irqsave(&dbg_data.lck, flags); scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG, - "%p %u[%s] %u %u %u %u %u %u\n", + "%pK %u[%s] %u %u %u %u %u %u\n", skb, skb->len, event, info->created, info->rx_queued, info->rx_done, info->rx_done_sent, info->tx_queued, get_timestamp()); @@ -1013,7 +1013,7 @@ static ssize_t ghsic_data_read_stats(struct file *file, spin_lock_irqsave(&port->rx_lock, flags); temp += scnprintf(buf + temp, DEBUG_DATA_BUF_SIZE - temp, "\nName: %s\n" - "#PORT:%d port#: %p\n" + "#PORT:%d port#: %pK\n" "data_ch_open: %d\n" "data_ch_ready: %d\n" "\n******UL INFO*****\n\n" diff --git a/drivers/usb/gadget/u_data_hsuart.c b/drivers/usb/gadget/u_data_hsuart.c index a5c918281f25..f79978951577 100644 --- a/drivers/usb/gadget/u_data_hsuart.c +++ b/drivers/usb/gadget/u_data_hsuart.c @@ -153,7 +153,7 @@ static int ghsuart_data_alloc_requests(struct usb_ep *ep, int i; struct usb_request *req; - pr_debug("%s: ep:%s head:%p num:%d cb:%p", __func__, + pr_debug("%s: ep:%s head:%pK num:%d cb:%pK", __func__, ep->name, head, num, cb); for (i = 0; i < num; i++) { @@ -244,7 +244,7 @@ static void ghsuart_data_write_tomdm(struct work_struct *w) } while ((skb = __skb_dequeue(&port->rx_skb_q))) { - pr_debug("%s: port:%p tom:%lu pno:%d\n", __func__, + pr_debug("%s: port:%pK tom:%lu pno:%d\n", __func__, port, port->to_modem, port->port_num); ret = msm_smux_write(port->ch_id, skb, skb->data, skb->len); @@ -345,7 +345,7 @@ static void ghsuart_data_start_rx(struct ghsuart_data_port *port) int ret; struct sk_buff *skb; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (!port) return; @@ -398,7 +398,7 @@ static void ghsuart_data_start_io(struct ghsuart_data_port *port) struct usb_ep *ep; int ret; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (!port) return; @@ -594,7 +594,7 @@ static void ghsuart_data_connect_w(struct work_struct *w) !test_bit(CH_READY, &port->channel_sts)) return; - pr_debug("%s: port:%p\n", __func__, port); + pr_debug("%s: port:%pK\n", __func__, port); if (test_bit(CH_OPENED, &port->channel_sts)) { ret = wait_for_completion_timeout( @@ -832,7 +832,7 @@ static int ghsuart_data_port_alloc(unsigned port_num, enum gadget_type gtype) platform_driver_register(pdrv); - pr_debug("%s: port:%p portno:%d\n", __func__, port, port_num); + pr_debug("%s: port:%pK portno:%d\n", __func__, port, port_num); return 0; } @@ -956,14 +956,14 @@ int ghsuart_data_connect(void *gptr, int port_num) ret = usb_ep_enable(port->in); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:IN ep:%p", + pr_err("%s: usb_ep_enable failed eptype:IN ep:%pK", __func__, port->in); goto fail; } ret = usb_ep_enable(port->out); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p", + pr_err("%s: usb_ep_enable failed eptype:OUT ep:%pK", __func__, port->out); usb_ep_disable(port->in); goto fail; @@ -1010,7 +1010,7 @@ static ssize_t ghsuart_data_read_stats(struct file *file, spin_lock_irqsave(&port->rx_lock, flags); temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp, "\nName: %s\n" - "#PORT:%d port#: %p\n" + "#PORT:%d port#: %pK\n" "data_ch_open: %d\n" "data_ch_ready: %d\n" "data_ch_connected: %d\n" diff --git a/drivers/usb/gadget/u_data_ipa.c b/drivers/usb/gadget/u_data_ipa.c index 9e3b01f4df22..fe2914d5a949 100644 --- a/drivers/usb/gadget/u_data_ipa.c +++ b/drivers/usb/gadget/u_data_ipa.c @@ -186,7 +186,7 @@ void ipa_data_disconnect(struct gadget_ipa_port *gp, u8 port_num) unsigned long flags; struct usb_gadget *gadget = NULL; - pr_debug("dev:%p port number:%d\n", gp, port_num); + pr_debug("dev:%pK port number:%d\n", gp, port_num); if (port_num >= n_ipa_ports) { pr_err("invalid ipa portno#%d\n", port_num); return; @@ -449,7 +449,7 @@ static void ipa_data_connect_work(struct work_struct *w) if (gport->in) ipa_data_start_endless_xfer(port, true); - pr_debug("Connect workqueue done (port %p)", port); + pr_debug("Connect workqueue done (port %pK)", port); return; disconnect_usb_bam_ipa_in: @@ -494,7 +494,7 @@ int ipa_data_connect(struct gadget_ipa_port *gp, u8 port_num, unsigned long flags; int ret; - pr_debug("dev:%p port#%d src_connection_idx:%d dst_connection_idx:%d\n", + pr_debug("dev:%pK port#%d src_connection_idx:%d dst_connection_idx:%d\n", gp, port_num, src_connection_idx, dst_connection_idx); if (port_num >= n_ipa_ports) { @@ -531,7 +531,7 @@ int ipa_data_connect(struct gadget_ipa_port *gp, u8 port_num, port->port_usb->in->endless = true; ret = usb_ep_enable(port->port_usb->in); if (ret) { - pr_err("usb_ep_enable failed eptype:IN ep:%p", + pr_err("usb_ep_enable failed eptype:IN ep:%pK", port->port_usb->in); port->port_usb->in->endless = false; goto err_usb_in; @@ -542,7 +542,7 @@ int ipa_data_connect(struct gadget_ipa_port *gp, u8 port_num, port->port_usb->out->endless = true; ret = usb_ep_enable(port->port_usb->out); if (ret) { - pr_err("usb_ep_enable failed eptype:OUT ep:%p", + pr_err("usb_ep_enable failed eptype:OUT ep:%pK", port->port_usb->out); port->port_usb->out->endless = false; goto err_usb_out; @@ -655,7 +655,7 @@ void ipa_data_suspend(struct gadget_ipa_port *gp, u8 port_num) struct ipa_data_ch_info *port; int ret; - pr_debug("dev:%p port number:%d\n", gp, port_num); + pr_debug("dev:%pK port number:%d\n", gp, port_num); if (port_num >= n_ipa_ports) { pr_err("invalid ipa portno#%d\n", port_num); @@ -702,7 +702,7 @@ void ipa_data_resume(struct gadget_ipa_port *gp, u8 port_num) struct usb_gadget *gadget = NULL; int ret; - pr_debug("dev:%p port number:%d\n", gp, port_num); + pr_debug("dev:%pK port number:%d\n", gp, port_num); if (port_num >= n_ipa_ports) { pr_err("invalid ipa portno#%d\n", port_num); @@ -775,7 +775,7 @@ static int ipa_data_port_alloc(int portno) ipa_data_ports[portno] = port; - pr_debug("port:%p with portno:%d allocated\n", port, portno); + pr_debug("port:%pK with portno:%d allocated\n", port, portno); return 0; } diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c index 1fa27b0ed522..b667eb416a2b 100644 --- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c +++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c @@ -142,7 +142,7 @@ static void grmnet_ctrl_smd_read_w(struct work_struct *w) (c->ch == 0))); if (read_avail < 0 || c->ch == 0) { - pr_err("%s:smd read_avail failure:%d or channel closed ch=%p", + pr_err("%s:smd read_avail failure:%d or channel closed ch=%pK", __func__, read_avail, c->ch); kfree(buf); return; @@ -435,7 +435,7 @@ int gsmd_ctrl_connect(struct grmnet *gr, int port_num) struct smd_ch_info *c; unsigned long flags; - pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num); + pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, port_num); if (!is_legal_port_num(port_num)) { pr_err("%s: Invalid port_num#%d\n", __func__, port_num); @@ -491,7 +491,7 @@ void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num) struct rmnet_ctrl_pkt *cpkt; int clear_bits; - pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num); + pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, port_num); if (!is_legal_port_num(port_num)) { pr_err("%s: Invalid port_num#%d\n", __func__, port_num); @@ -646,7 +646,7 @@ static int grmnet_ctrl_smd_port_alloc(int portno) pdrv->driver.name = c->name; pdrv->driver.owner = THIS_MODULE; - pr_debug("%s: port:%p portno:%d\n", __func__, port, portno); + pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno); return 0; } @@ -735,7 +735,7 @@ static ssize_t gsmd_ctrl_read_stats(struct file *file, char __user *ubuf, c = &port->ctrl_ch; temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp, - "#PORT:%d port:%p ctrl_ch:%p#\n" + "#PORT:%d port:%pK ctrl_ch:%pK#\n" "to_usbhost: %lu\n" "to_modem: %lu\n" "DTR: %s\n" diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 9a120401cd95..f30cf31c7251 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -873,7 +873,7 @@ static int gs_open(struct tty_struct *tty, struct file *file) spin_lock_irq(&port->port_lock); if (status) { - pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n", + pr_debug("gs_open: ttyGS%d (%pK,%pK) no buffer\n", port->port_num, tty, file); port->openclose = false; goto exit_unlock_port; @@ -908,7 +908,7 @@ static int gs_open(struct tty_struct *tty, struct file *file) gser->connect(gser); } - pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); + pr_debug("gs_open: ttyGS%d (%pK,%pK)\n", port->port_num, tty, file); status = 0; @@ -944,7 +944,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) goto exit; } - pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file); + pr_debug("gs_close: ttyGS%d (%pK,%pK) ...\n", port->port_num, tty, file); /* mark port as closing but in use; we can drop port lock * and sleep if necessary @@ -982,7 +982,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) port->openclose = false; - pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", + pr_debug("gs_close: ttyGS%d (%pK,%pK) done!\n", port->port_num, tty, file); wake_up(&port->port.close_wait); @@ -998,7 +998,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) if (!port) return 0; - pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n", + pr_vdebug("gs_write: ttyGS%d (%pK) writing %d bytes\n", port->port_num, tty, count); spin_lock_irqsave(&port->port_lock, flags); @@ -1020,7 +1020,7 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch) if (!port) return 0; - pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %pf\n", + pr_vdebug("gs_put_char: (%d,%pK) char=0x%x, called from %pKf\n", port->port_num, tty, ch, __builtin_return_address(0)); spin_lock_irqsave(&port->port_lock, flags); @@ -1037,7 +1037,7 @@ static void gs_flush_chars(struct tty_struct *tty) if (!port) return; - pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty); + pr_vdebug("gs_flush_chars: (%d,%pK)\n", port->port_num, tty); spin_lock_irqsave(&port->port_lock, flags); if (port->port_usb) @@ -1058,7 +1058,7 @@ static int gs_write_room(struct tty_struct *tty) room = gs_buf_space_avail(&port->port_write_buf); spin_unlock_irqrestore(&port->port_lock, flags); - pr_vdebug("gs_write_room: (%d,%p) room=%d\n", + pr_vdebug("gs_write_room: (%d,%pK) room=%d\n", port->port_num, tty, room); return room; @@ -1076,7 +1076,7 @@ static int gs_chars_in_buffer(struct tty_struct *tty) chars = gs_buf_data_avail(&port->port_write_buf); spin_unlock_irqrestore(&port->port_lock, flags); - pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n", + pr_vdebug("gs_chars_in_buffer: (%d,%pK) chars=%d\n", port->port_num, tty, chars); return chars; diff --git a/drivers/usb/gadget/u_smd.c b/drivers/usb/gadget/u_smd.c index 04fd57cf81bc..712311cf29b7 100644 --- a/drivers/usb/gadget/u_smd.c +++ b/drivers/usb/gadget/u_smd.c @@ -148,7 +148,7 @@ static int gsmd_alloc_requests(struct usb_ep *ep, struct list_head *head, int i; struct usb_request *req; - pr_debug("%s: ep:%p head:%p num:%d size:%d cb:%p", __func__, + pr_debug("%s: ep:%pK head:%pK num:%d size:%d cb:%pK", __func__, ep, head, num, size, cb); for (i = 0; i < num; i++) { @@ -198,7 +198,7 @@ static void gsmd_start_rx(struct gsmd_port *port) spin_lock_irqsave(&port->port_lock, flags); if (ret) { pr_err("%s: usb ep out queue failed" - "port:%p, port#%d\n", + "port:%pK, port#%d\n", __func__, port, port->port_num); list_add_tail(&req->list, pool); break; @@ -214,7 +214,7 @@ static void gsmd_rx_push(struct work_struct *w) struct smd_port_info *pi = port->pi; struct list_head *q; - pr_debug("%s: port:%p port#%d", __func__, port, port->port_num); + pr_debug("%s: port:%pK port#%d", __func__, port, port->port_num); spin_lock_irq(&port->port_lock); @@ -227,11 +227,11 @@ static void gsmd_rx_push(struct work_struct *w) switch (req->status) { case -ESHUTDOWN: - pr_debug("%s: req status shutdown portno#%d port:%p\n", + pr_debug("%s: req status shutdown portno#%d port:%pK\n", __func__, port->port_num, port); goto rx_push_end; default: - pr_warning("%s: port:%p port#%d" + pr_warning("%s: port:%pK port#%d" " Unexpected Rx Status:%d\n", __func__, port, port->port_num, req->status); case 0: @@ -301,7 +301,7 @@ static void gsmd_tx_pull(struct work_struct *w) struct smd_port_info *pi = port->pi; struct usb_ep *in; - pr_debug("%s: port:%p port#%d pool:%p\n", __func__, + pr_debug("%s: port:%pK port#%d pool:%pK\n", __func__, port, port->port_num, pool); spin_lock_irq(&port->port_lock); @@ -335,7 +335,7 @@ static void gsmd_tx_pull(struct work_struct *w) spin_lock_irq(&port->port_lock); if (ret) { pr_err("%s: usb ep in queue failed" - "port:%p, port#%d err:%d\n", + "port:%pK, port#%d err:%d\n", __func__, port, port->port_num, ret); /* could be usb disconnected */ if (!port->port_usb) @@ -362,7 +362,7 @@ static void gsmd_read_complete(struct usb_ep *ep, struct usb_request *req) { struct gsmd_port *port = ep->driver_data; - pr_debug("%s: ep:%p port:%p\n", __func__, ep, port); + pr_debug("%s: ep:%pK port:%pK\n", __func__, ep, port); if (!port) { pr_err("%s: port is null\n", __func__); @@ -388,7 +388,7 @@ static void gsmd_write_complete(struct usb_ep *ep, struct usb_request *req) { struct gsmd_port *port = ep->driver_data; - pr_debug("%s: ep:%p port:%p\n", __func__, ep, port); + pr_debug("%s: ep:%pK port:%pK\n", __func__, ep, port); if (!port) { pr_err("%s: port is null\n", __func__); @@ -404,7 +404,7 @@ static void gsmd_write_complete(struct usb_ep *ep, struct usb_request *req) } if (req->status) - pr_warning("%s: port:%p port#%d unexpected %s status %d\n", + pr_warning("%s: port:%pK port#%d unexpected %s status %d\n", __func__, port, port->port_num, ep->name, req->status); @@ -419,7 +419,7 @@ static void gsmd_start_io(struct gsmd_port *port) { int ret = -ENODEV; - pr_debug("%s: port: %p\n", __func__, port); + pr_debug("%s: port: %pK\n", __func__, port); spin_lock(&port->port_lock); @@ -571,7 +571,7 @@ static void gsmd_connect_work(struct work_struct *w) port = container_of(w, struct gsmd_port, connect_work.work); pi = port->pi; - pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num); + pr_debug("%s: port:%pK port#%d\n", __func__, port, port->port_num); if (!test_bit(CH_READY, &pi->flags)) return; @@ -600,7 +600,7 @@ static void gsmd_disconnect_work(struct work_struct *w) port = container_of(w, struct gsmd_port, disconnect_work); pi = port->pi; - pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num); + pr_debug("%s: port:%pK port#%d\n", __func__, port, port->port_num); smd_close(port->pi->ch); port->pi->ch = NULL; @@ -668,7 +668,7 @@ int gsmd_connect(struct gserial *gser, u8 portno) int ret; struct gsmd_port *port; - pr_debug("%s: gserial:%p portno:%u\n", __func__, gser, portno); + pr_debug("%s: gserial:%pK portno:%u\n", __func__, gser, portno); if (portno >= n_smd_ports) { pr_err("%s: Invalid port no#%d", __func__, portno); @@ -691,7 +691,7 @@ int gsmd_connect(struct gserial *gser, u8 portno) ret = usb_ep_enable(gser->in); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:IN ep:%p, err:%d", + pr_err("%s: usb_ep_enable failed eptype:IN ep:%pK, err:%d", __func__, gser->in, ret); port->port_usb = 0; return ret; @@ -700,7 +700,7 @@ int gsmd_connect(struct gserial *gser, u8 portno) ret = usb_ep_enable(gser->out); if (ret) { - pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p, err: %d", + pr_err("%s: usb_ep_enable failed eptype:OUT ep:%pK, err: %d", __func__, gser->out, ret); port->port_usb = 0; gser->in->driver_data = 0; @@ -718,7 +718,7 @@ void gsmd_disconnect(struct gserial *gser, u8 portno) unsigned long flags; struct gsmd_port *port; - pr_debug("%s: gserial:%p portno:%u\n", __func__, gser, portno); + pr_debug("%s: gserial:%pK portno:%u\n", __func__, gser, portno); if (portno >= n_smd_ports) { pr_err("%s: invalid portno#%d\n", __func__, portno); @@ -855,7 +855,7 @@ static int gsmd_port_alloc(int portno, struct usb_cdc_line_coding *coding) pdrv->driver.owner = THIS_MODULE; platform_driver_register(pdrv); - pr_debug("%s: port:%p portno:%d\n", __func__, port, portno); + pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno); return 0; } @@ -959,10 +959,10 @@ int gsmd_setup(struct usb_gadget *g, unsigned count) int ret; int i; - pr_debug("%s: g:%p count: %d\n", __func__, g, count); + pr_debug("%s: g:%pK count: %d\n", __func__, g, count); if (!count || count > SMD_N_PORTS) { - pr_err("%s: Invalid num of ports count:%d gadget:%p\n", + pr_err("%s: Invalid num of ports count:%d gadget:%pK\n", __func__, count, g); return -EINVAL; } diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 5429d2645bbc..dc1c35b5a4f7 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -106,7 +106,7 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} static void __maybe_unused dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) { - ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, + ehci_dbg(ehci, "%s td %pK n%08x %08x t%08x p0=%08x\n", label, qtd, hc32_to_cpup(ehci, &qtd->hw_next), hc32_to_cpup(ehci, &qtd->hw_alt_next), hc32_to_cpup(ehci, &qtd->hw_token), @@ -124,7 +124,7 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) { struct ehci_qh_hw *hw = qh->hw; - ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, + ehci_dbg (ehci, "%s qh %pK n%08x info %x %x qtd %x\n", label, qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next); } @@ -132,7 +132,7 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) static void __maybe_unused dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) { - ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", + ehci_dbg (ehci, "%s [%d] itd %pK, next %08x, urb %pK\n", label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), itd->urb); ehci_dbg (ehci, @@ -163,7 +163,7 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) static void __maybe_unused dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) { - ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", + ehci_dbg (ehci, "%s [%d] sitd %pK, next %08x, urb %pK\n", label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), sitd->urb); ehci_dbg (ehci, @@ -429,7 +429,7 @@ static void qh_lines ( scratch = hc32_to_cpup(ehci, &hw->hw_info1); hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0; temp = scnprintf (next, size, - "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", + "qh/%pK dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", qh, scratch & 0x007f, speed_char (scratch), (scratch >> 8) & 0x000f, @@ -457,7 +457,7 @@ static void qh_lines ( mark = '/'; } temp = snprintf (next, size, - "\n\t%p%c%s len=%d %08x urb %p", + "\n\t%pK%c%s len=%d %08x urb %pK", td, mark, ({ char *tmp; switch ((scratch>>8)&0x03) { case 0: tmp = "out"; break; @@ -571,7 +571,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) switch (hc32_to_cpu(ehci, tag)) { case Q_TYPE_QH: hw = p.qh->hw; - temp = scnprintf (next, size, " qh%d-%04x/%p", + temp = scnprintf (next, size, " qh%d-%04x/%pK", p.qh->period, hc32_to_cpup(ehci, &hw->hw_info2) @@ -632,20 +632,20 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) break; case Q_TYPE_FSTN: temp = scnprintf (next, size, - " fstn-%8x/%p", p.fstn->hw_prev, + " fstn-%8x/%pK", p.fstn->hw_prev, p.fstn); tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next); p = p.fstn->fstn_next; break; case Q_TYPE_ITD: temp = scnprintf (next, size, - " itd/%p", p.itd); + " itd/%pK", p.itd); tag = Q_NEXT_TYPE(ehci, p.itd->hw_next); p = p.itd->itd_next; break; case Q_TYPE_SITD: temp = scnprintf (next, size, - " sitd%d-%04x/%p", + " sitd%d-%04x/%pK", p.sitd->stream->interval, hc32_to_cpup(ehci, &p.sitd->hw_uframe) & 0x0000ffff, @@ -817,7 +817,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) } if (!list_empty(&ehci->async_unlink)) { - temp = scnprintf(next, size, "async unlink qh %p\n", + temp = scnprintf(next, size, "async unlink qh %pK\n", list_first_entry(&ehci->async_unlink, struct ehci_qh, unlink_node)); size -= temp; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index bfcf38383f74..b68f3662894b 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -144,7 +144,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, struct ehci_hcd *ehci = hcd_to_ehci(hcd); hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2); - dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n", + dev_dbg(&pdev->dev, "hcd=0x%pK ehci=0x%pK, phy=0x%pK\n", hcd, ehci, hcd->phy); if (!IS_ERR_OR_NULL(hcd->phy)) { diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8db0e169543b..58adbed2d3ed 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1015,7 +1015,7 @@ idle_timeout: /* caller was supposed to have unlinked any requests; * that's not our job. just leak this memory. */ - ehci_err (ehci, "qh %p (#%02x) state %d%s\n", + ehci_err (ehci, "qh %pK (#%02x) state %d%s\n", qh, ep->desc.bEndpointAddress, qh->qh_state, list_empty (&qh->qtd_list) ? "" : "(has tds)"); break; diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c index 26a91431d7f3..9f8127200f97 100644 --- a/drivers/usb/host/ehci-msm-hsic.c +++ b/drivers/usb/host/ehci-msm-hsic.c @@ -274,7 +274,7 @@ static void dbg_log_event(struct urb *urb, char * event, unsigned extra) if (!str_to_event(event)) { write_lock_irqsave(&dbg_hsic_ctrl.lck, flags); scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], - DBG_MSG_LEN, "%s: [%s : %p]:[%s] " + DBG_MSG_LEN, "%s: [%s : %pK]:[%s] " "%02x %02x %04x %04x %04x %u %d %s", get_timestamp(tbuf), event, urb, usb_urb_dir_in(urb) ? "in" : "out", @@ -294,7 +294,7 @@ static void dbg_log_event(struct urb *urb, char * event, unsigned extra) } else { write_lock_irqsave(&dbg_hsic_ctrl.lck, flags); scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], - DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d %s", + DBG_MSG_LEN, "%s: [%s : %pK]:[%s] %u %d %s", get_timestamp(tbuf), event, urb, usb_urb_dir_in(urb) ? "in" : "out", urb->actual_length, extra, @@ -307,7 +307,7 @@ static void dbg_log_event(struct urb *urb, char * event, unsigned extra) } else { write_lock_irqsave(&dbg_hsic_data.lck, flags); scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN, - "%s: [%s : %p]:ep%d[%s] %u %d %s", + "%s: [%s : %pK]:ep%d[%s] %u %d %s", get_timestamp(tbuf), event, urb, ep_addr & 0x0f, usb_urb_dir_in(urb) ? "in" : "out", str_to_event(event) ? urb->actual_length : @@ -339,7 +339,7 @@ static void dump_hsic_regs(struct usb_hcd *hcd) return; for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10) - pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i, + pr_info("%pK: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i, readl_relaxed(hcd->regs + i), readl_relaxed(hcd->regs + i + 4), readl_relaxed(hcd->regs + i + 8), @@ -1721,7 +1721,7 @@ static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id) { struct msm_hsic_hcd *mehci = dev_id; - pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id); + pr_debug("%s: mehci:%pK dev_id:%pK\n", __func__, mehci, dev_id); if (mehci) msm_hsic_config_gpios(mehci, 0); diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 402062973f03..52e7113759ef 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -263,7 +263,7 @@ static int mv_ehci_probe(struct platform_device *pdev) pdata->private_init(ehci_mv->op_regs, ehci_mv->phy_regs); dev_info(&pdev->dev, - "successful find EHCI device with regs 0x%p irq %d" + "successful find EHCI device with regs 0x%pK irq %d" " working in %s mode\n", hcd->regs, hcd->irq, ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host"); diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index fd983771b025..ffb3c15f9b85 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -216,7 +216,7 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev) BUG_ON(!hcd); - dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs); + dev_dbg(&dev->core, "%s:%d: regs %pK\n", __func__, __LINE__, hcd->regs); dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq); tmp = hcd->irq; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index ecf0a4c87569..a523915a00d2 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -273,7 +273,7 @@ __acquires(ehci->lock) #ifdef EHCI_URB_TRACE ehci_dbg (ehci, - "%s %s urb %p ep%d%s status %d len %d/%d\n", + "%s %s urb %pK ep%d%s status %d len %d/%d\n", __func__, urb->dev->devpath, urb, usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", @@ -362,7 +362,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) /* Report Data Buffer Error: non-fatal but useful */ if (token & QTD_STS_DBE) ehci_dbg(ehci, - "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", + "detected DataBufferErr for urb %pK ep%d%s len %d, qtd %pK [qh %pK]\n", urb, usb_endpoint_num(&urb->ep->desc), usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out", @@ -920,7 +920,7 @@ qh_make ( } break; default: - ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev, + ehci_dbg(ehci, "bogus dev %pK speed %d\n", urb->dev, urb->dev->speed); done: qh_destroy(ehci, qh); @@ -1108,7 +1108,7 @@ submit_async ( struct ehci_qtd *qtd; qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list); ehci_dbg(ehci, - "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", + "%s %s urb %pK ep%d%s len %d, qtd %pK [qh %pK]\n", __func__, urb->dev->devpath, urb, epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", urb->transfer_buffer_length, diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 738d9ada620b..32cea68fa71b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -492,7 +492,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) unsigned period = qh->period; dev_dbg (&qh->dev->dev, - "link qh%d-%04x/%p start %d [%d/%d us]\n", + "link qh%d-%04x/%pK start %d [%d/%d us]\n", period, hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); @@ -586,7 +586,7 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) : (qh->usecs * 8); dev_dbg (&qh->dev->dev, - "unlink qh%d-%04x/%p start %d [%d/%d us]\n", + "unlink qh%d-%04x/%pK start %d [%d/%d us]\n", qh->period, hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); @@ -658,7 +658,7 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) * FIXME kill the now-dysfunctional queued urbs */ else { - ehci_err(ehci, "can't reschedule qh %p, err %d\n", + ehci_err(ehci, "can't reschedule qh %pK, err %d\n", qh, rc); } } @@ -838,7 +838,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) : cpu_to_hc32(ehci, QH_SMASK); hw->hw_info2 |= c_mask; } else - ehci_dbg (ehci, "reused qh %p schedule\n", qh); + ehci_dbg (ehci, "reused qh %pK schedule\n", qh); done: return status; @@ -1385,7 +1385,7 @@ iso_stream_schedule ( /* Is the schedule already full? */ if (unlikely(start < period)) { - ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", + ehci_dbg(ehci, "iso sched full %pK (%u-%u < %u mod %u)\n", urb, stream->next_uframe, base, period, mod); status = -ENOSPC; @@ -1405,7 +1405,7 @@ iso_stream_schedule ( * no matter what. */ else if (start + span - period < now2) { - ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", + ehci_dbg(ehci, "iso underrun %pK (%u+%u < %u)\n", urb, start + base, span - period, now2 + base); } @@ -1451,7 +1451,7 @@ iso_stream_schedule ( /* no room in the schedule */ if (!done) { - ehci_dbg(ehci, "iso sched full %p", urb); + ehci_dbg(ehci, "iso sched full %pK", urb); status = -ENOSPC; goto fail; } @@ -1459,7 +1459,7 @@ iso_stream_schedule ( /* Tried to schedule too far into the future? */ if (unlikely(start - base + span - period >= mod)) { - ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", + ehci_dbg(ehci, "request %pK would overflow (%u+%u >= %u)\n", urb, start - base, span - period, mod); status = -EFBIG; goto fail; @@ -1768,7 +1768,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, #ifdef EHCI_URB_TRACE ehci_dbg (ehci, - "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", + "%s %s urb %pK ep%d%s len %d, %d pkts %d uframes [%pK]\n", __func__, urb->dev->devpath, urb, usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", @@ -2156,7 +2156,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, #ifdef EHCI_URB_TRACE ehci_dbg (ehci, - "submit %p dev%s ep%d%s-iso len %d\n", + "submit %pK dev%s ep%d%s-iso len %d\n", urb, urb->dev->devpath, usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", @@ -2303,7 +2303,7 @@ restart: q = *q_p; break; default: - ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", + ehci_dbg(ehci, "corrupt type %d frame %d shadow %pK\n", type, frame, q.ptr); // BUG (); /* FALL THROUGH */ diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 2f8c5362a77e..74a332891f3d 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -31,10 +31,10 @@ void xhci_dbg_regs(struct xhci_hcd *xhci) { u32 temp; - xhci_dbg(xhci, "// xHCI capability registers at %p:\n", + xhci_dbg(xhci, "// xHCI capability registers at %pK:\n", xhci->cap_regs); temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); - xhci_dbg(xhci, "// @%p = 0x%x (CAPLENGTH AND HCIVERSION)\n", + xhci_dbg(xhci, "// @%pK = 0x%x (CAPLENGTH AND HCIVERSION)\n", &xhci->cap_regs->hc_capbase, temp); xhci_dbg(xhci, "// CAPLENGTH: 0x%x\n", (unsigned int) HC_LENGTH(temp)); @@ -43,24 +43,24 @@ void xhci_dbg_regs(struct xhci_hcd *xhci) (unsigned int) HC_VERSION(temp)); #endif - xhci_dbg(xhci, "// xHCI operational registers at %p:\n", xhci->op_regs); + xhci_dbg(xhci, "// xHCI operational registers at %pK:\n", xhci->op_regs); temp = xhci_readl(xhci, &xhci->cap_regs->run_regs_off); - xhci_dbg(xhci, "// @%p = 0x%x RTSOFF\n", + xhci_dbg(xhci, "// @%pK = 0x%x RTSOFF\n", &xhci->cap_regs->run_regs_off, (unsigned int) temp & RTSOFF_MASK); - xhci_dbg(xhci, "// xHCI runtime registers at %p:\n", xhci->run_regs); + xhci_dbg(xhci, "// xHCI runtime registers at %pK:\n", xhci->run_regs); temp = xhci_readl(xhci, &xhci->cap_regs->db_off); - xhci_dbg(xhci, "// @%p = 0x%x DBOFF\n", &xhci->cap_regs->db_off, temp); - xhci_dbg(xhci, "// Doorbell array at %p:\n", xhci->dba); + xhci_dbg(xhci, "// @%pK = 0x%x DBOFF\n", &xhci->cap_regs->db_off, temp); + xhci_dbg(xhci, "// Doorbell array at %pK:\n", xhci->dba); } static void xhci_print_cap_regs(struct xhci_hcd *xhci) { u32 temp; - xhci_dbg(xhci, "xHCI capability registers at %p:\n", xhci->cap_regs); + xhci_dbg(xhci, "xHCI capability registers at %pK:\n", xhci->cap_regs); temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); xhci_dbg(xhci, "CAPLENGTH AND HCIVERSION 0x%x:\n", @@ -141,7 +141,7 @@ static void xhci_print_status(struct xhci_hcd *xhci) static void xhci_print_op_regs(struct xhci_hcd *xhci) { - xhci_dbg(xhci, "xHCI operational registers at %p:\n", xhci->op_regs); + xhci_dbg(xhci, "xHCI operational registers at %pK:\n", xhci->op_regs); xhci_print_command_reg(xhci); xhci_print_status(xhci); } @@ -162,7 +162,7 @@ static void xhci_print_ports(struct xhci_hcd *xhci) addr = &xhci->op_regs->port_status_base; for (i = 0; i < ports; i++) { for (j = 0; j < NUM_PORT_REGS; ++j) { - xhci_dbg(xhci, "%p port %s reg = 0x%x\n", + xhci_dbg(xhci, "%pK port %s reg = 0x%x\n", addr, names[j], (unsigned int) xhci_readl(xhci, addr)); addr++; @@ -182,35 +182,35 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num) if (temp == XHCI_INIT_VALUE) return; - xhci_dbg(xhci, " %p: ir_set[%i]\n", ir_set, set_num); + xhci_dbg(xhci, " %pK: ir_set[%i]\n", ir_set, set_num); - xhci_dbg(xhci, " %p: ir_set.pending = 0x%x\n", addr, + xhci_dbg(xhci, " %pK: ir_set.pending = 0x%x\n", addr, (unsigned int)temp); addr = &ir_set->irq_control; temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.control = 0x%x\n", addr, + xhci_dbg(xhci, " %pK: ir_set.control = 0x%x\n", addr, (unsigned int)temp); addr = &ir_set->erst_size; temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_size = 0x%x\n", addr, + xhci_dbg(xhci, " %pK: ir_set.erst_size = 0x%x\n", addr, (unsigned int)temp); addr = &ir_set->rsvd; temp = xhci_readl(xhci, addr); if (temp != XHCI_INIT_VALUE) - xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n", + xhci_dbg(xhci, " WARN: %pK: ir_set.rsvd = 0x%x\n", addr, (unsigned int)temp); addr = &ir_set->erst_base; temp_64 = xhci_read_64(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n", + xhci_dbg(xhci, " %pK: ir_set.erst_base = @%08llx\n", addr, temp_64); addr = &ir_set->erst_dequeue; temp_64 = xhci_read_64(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n", + xhci_dbg(xhci, " %pK: ir_set.erst_dequeue = @%08llx\n", addr, temp_64); } @@ -219,15 +219,15 @@ void xhci_print_run_regs(struct xhci_hcd *xhci) u32 temp; int i; - xhci_dbg(xhci, "xHCI runtime registers at %p:\n", xhci->run_regs); + xhci_dbg(xhci, "xHCI runtime registers at %pK:\n", xhci->run_regs); temp = xhci_readl(xhci, &xhci->run_regs->microframe_index); - xhci_dbg(xhci, " %p: Microframe index = 0x%x\n", + xhci_dbg(xhci, " %pK: Microframe index = 0x%x\n", &xhci->run_regs->microframe_index, (unsigned int) temp); for (i = 0; i < 7; ++i) { temp = xhci_readl(xhci, &xhci->run_regs->rsvd[i]); if (temp != XHCI_INIT_VALUE) - xhci_dbg(xhci, " WARN: %p: Rsvd[%i] = 0x%x\n", + xhci_dbg(xhci, " WARN: %pK: Rsvd[%i] = 0x%x\n", &xhci->run_regs->rsvd[i], i, (unsigned int) temp); } @@ -329,13 +329,13 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg) void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring) { - xhci_dbg(xhci, "Ring deq = %p (virt), 0x%llx (dma)\n", + xhci_dbg(xhci, "Ring deq = %pK (virt), 0x%llx (dma)\n", ring->dequeue, (unsigned long long)xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue)); xhci_dbg(xhci, "Ring deq updated %u times\n", ring->deq_updates); - xhci_dbg(xhci, "Ring enq = %p (virt), 0x%llx (dma)\n", + xhci_dbg(xhci, "Ring enq = %pK (virt), 0x%llx (dma)\n", ring->enqueue, (unsigned long long)xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue)); @@ -425,7 +425,7 @@ static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma) { int i; for (i = 0; i < 4; ++i) { - xhci_dbg(xhci, "@%p (virt) @%08llx " + xhci_dbg(xhci, "@%pK (virt) @%08llx " "(dma) %#08llx - rsvd64[%d]\n", &ctx[4 + i], (unsigned long long)dma, ctx[4 + i], i); @@ -464,24 +464,24 @@ static void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx * int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); xhci_dbg(xhci, "Slot Context:\n"); - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - dev_info\n", &slot_ctx->dev_info, (unsigned long long)dma, slot_ctx->dev_info); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - dev_info2\n", &slot_ctx->dev_info2, (unsigned long long)dma, slot_ctx->dev_info2); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - tt_info\n", &slot_ctx->tt_info, (unsigned long long)dma, slot_ctx->tt_info); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - dev_state\n", &slot_ctx->dev_state, (unsigned long long)dma, slot_ctx->dev_state); dma += field_size; for (i = 0; i < 4; ++i) { - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &slot_ctx->reserved[i], (unsigned long long)dma, slot_ctx->reserved[i], i); dma += field_size; @@ -509,24 +509,24 @@ static void xhci_dbg_ep_ctx(struct xhci_hcd *xhci, ((unsigned long)ep_ctx - (unsigned long)ctx->bytes); xhci_dbg(xhci, "Endpoint %02d Context:\n", i); - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - ep_info\n", &ep_ctx->ep_info, (unsigned long long)dma, ep_ctx->ep_info); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - ep_info2\n", &ep_ctx->ep_info2, (unsigned long long)dma, ep_ctx->ep_info2); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08llx - deq\n", &ep_ctx->deq, (unsigned long long)dma, ep_ctx->deq); dma += 2*field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - tx_info\n", &ep_ctx->tx_info, (unsigned long long)dma, ep_ctx->tx_info); dma += field_size; for (j = 0; j < 3; ++j) { - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &ep_ctx->reserved[j], (unsigned long long)dma, ep_ctx->reserved[j], j); @@ -551,16 +551,16 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, if (ctx->type == XHCI_CTX_TYPE_INPUT) { struct xhci_input_control_ctx *ctrl_ctx = xhci_get_input_control_ctx(xhci, ctx); - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - drop flags\n", &ctrl_ctx->drop_flags, (unsigned long long)dma, ctrl_ctx->drop_flags); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - add flags\n", &ctrl_ctx->add_flags, (unsigned long long)dma, ctrl_ctx->add_flags); dma += field_size; for (i = 0; i < 6; ++i) { - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", + xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", &ctrl_ctx->rsvd2[i], (unsigned long long)dma, ctrl_ctx->rsvd2[i], i); dma += field_size; @@ -682,7 +682,7 @@ xhci_dbg_log_event(struct dbg_data *d, struct urb *urb, char *event, if (!xhci_str_to_event(event)) { write_lock_irqsave(&d->ctrl_lck, flags); scnprintf(d->ctrl_buf[d->ctrl_idx], - DBG_MSG_LEN, "%s: [%s : %p]:[%s] " + DBG_MSG_LEN, "%s: [%s : %pK]:[%s] " "%02x %02x %04x %04x %04x %u %d %s", get_timestamp(tbuf), event, urb, usb_urb_dir_in(urb) ? "in" : "out", @@ -702,7 +702,7 @@ xhci_dbg_log_event(struct dbg_data *d, struct urb *urb, char *event, } else { write_lock_irqsave(&d->ctrl_lck, flags); scnprintf(d->ctrl_buf[d->ctrl_idx], - DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d %s", + DBG_MSG_LEN, "%s: [%s : %pK]:[%s] %u %d %s", get_timestamp(tbuf), event, urb, usb_urb_dir_in(urb) ? "in" : "out", urb->actual_length, extra, @@ -715,7 +715,7 @@ xhci_dbg_log_event(struct dbg_data *d, struct urb *urb, char *event, } else { write_lock_irqsave(&d->data_lck, flags); scnprintf(d->data_buf[d->data_idx], DBG_MSG_LEN, - "%s: [%s : %p]:ep%d[%s] %u %d %s", + "%s: [%s : %pK]:ep%d[%s] %u %d %s", get_timestamp(tbuf), event, urb, ep_addr & 0x0f, usb_urb_dir_in(urb) ? "in" : "out", xhci_str_to_event(event) ? urb->actual_length : diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6a22eaf2f0ba..591f8db7f326 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -542,7 +542,7 @@ static int xhci_test_radix_tree(struct xhci_hcd *xhci, if (cur_ring != mapped_ring) { xhci_warn(xhci, "WARN: DMA address 0x%08llx " "didn't map to stream ID %u; " - "mapped to ring %p\n", + "mapped to ring %pK\n", (unsigned long long) addr, cur_stream, mapped_ring); @@ -562,7 +562,7 @@ static int xhci_test_radix_tree(struct xhci_hcd *xhci, if (mapped_ring == cur_ring) { xhci_warn(xhci, "WARN: Bad DMA address 0x%08llx " "mapped to valid stream ID %u; " - "mapped ring = %p\n", + "mapped ring = %pK\n", (unsigned long long) addr, cur_stream, mapped_ring); @@ -1002,7 +1002,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(dev->out_ctx->dma); - xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", + xhci_dbg(xhci, "Set slot id %d dcbaa entry %pK to 0x%llx\n", slot_id, &xhci->dcbaa->dev_context_ptrs[slot_id], le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id])); @@ -1157,7 +1157,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud if (udev->tt->multi) slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); } - xhci_dbg(xhci, "udev->tt = %p\n", udev->tt); + xhci_dbg(xhci, "udev->tt = %pK\n", udev->tt); xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport); /* Step 4 - ring already allocated */ @@ -1904,15 +1904,15 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci, if (seg != result_seg) { xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n", test_name, test_number); - xhci_warn(xhci, "Tested TRB math w/ seg %p and " + xhci_warn(xhci, "Tested TRB math w/ seg %pK and " "input DMA 0x%llx\n", input_seg, (unsigned long long) input_dma); - xhci_warn(xhci, "starting TRB %p (0x%llx DMA), " - "ending TRB %p (0x%llx DMA)\n", + xhci_warn(xhci, "starting TRB %pK (0x%llx DMA), " + "ending TRB %pK (0x%llx DMA)\n", start_trb, start_dma, end_trb, end_dma); - xhci_warn(xhci, "Expected seg %p, got seg %p\n", + xhci_warn(xhci, "Expected seg %pK, got seg %pK\n", result_seg, seg); return -1; } @@ -2072,7 +2072,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, if (major_revision > 0x03) { xhci_warn(xhci, "Ignoring unknown port speed, " - "Ext Cap %p, revision = 0x%x\n", + "Ext Cap %pK, revision = 0x%x\n", addr, major_revision); /* Ignoring port protocol we can't understand. FIXME */ return; @@ -2082,7 +2082,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, temp = xhci_readl(xhci, addr + 2); port_offset = XHCI_EXT_PORT_OFF(temp); port_count = XHCI_EXT_PORT_COUNT(temp); - xhci_dbg(xhci, "Ext Cap %p, port offset = %u, " + xhci_dbg(xhci, "Ext Cap %pK, port offset = %u, " "count = %u, revision = 0x%x\n", addr, port_offset, port_count, major_revision); /* Port count includes the current port offset */ @@ -2110,7 +2110,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, for (i = port_offset; i < (port_offset + port_count); i++) { /* Duplicate entry. Ignore the port if the revisions differ. */ if (xhci->port_array[i] != 0) { - xhci_warn(xhci, "Duplicate port entry, Ext Cap %p," + xhci_warn(xhci, "Duplicate port entry, Ext Cap %pK," " port %u\n", addr, i); xhci_warn(xhci, "Port was marked as USB %u, " "duplicated as USB %u\n", @@ -2242,7 +2242,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) &xhci->op_regs->port_status_base + NUM_PORT_REGS*i; xhci_dbg(xhci, "USB 2.0 port at index %u, " - "addr = %p\n", i, + "addr = %pK\n", i, xhci->usb2_ports[port_index]); port_index++; if (port_index == xhci->num_usb2_ports) @@ -2262,7 +2262,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) &xhci->op_regs->port_status_base + NUM_PORT_REGS*i; xhci_dbg(xhci, "USB 3.0 port at index %u, " - "addr = %p\n", i, + "addr = %pK\n", i, xhci->usb3_ports[port_index]); port_index++; if (port_index == xhci->num_usb3_ports) @@ -2324,7 +2324,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) goto fail; memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); xhci->dcbaa->dma = dma; - xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n", + xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %pK (virt)\n", (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa); xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr); @@ -2363,7 +2363,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; - xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); + xhci_dbg(xhci, "Allocated command ring at %pK\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); @@ -2419,7 +2419,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) memset(xhci->erst.entries, 0, sizeof(struct xhci_erst_entry)*ERST_NUM_SEGS); xhci->erst.num_entries = ERST_NUM_SEGS; xhci->erst.erst_dma_addr = dma; - xhci_dbg(xhci, "Set ERST to 0; private num segs = %i, virt addr = %p, dma addr = 0x%llx\n", + xhci_dbg(xhci, "Set ERST to 0; private num segs = %i, virt addr = %pK, dma addr = 0x%llx\n", xhci->erst.num_entries, xhci->erst.entries, (unsigned long long)xhci->erst.erst_dma_addr); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 676bf3a2fa8a..15a9147968a4 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -610,7 +610,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state); /* Don't update the ring cycle state for the producer (us). */ - xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n", + xhci_dbg(xhci, "New dequeue segment = %pK (virtual)\n", state->new_deq_seg); addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr); xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n", @@ -642,8 +642,8 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, cur_trb->generic.field[3] ^= cpu_to_le32(TRB_CYCLE); xhci_dbg(xhci, "Cancel (unchain) link TRB\n"); - xhci_dbg(xhci, "Address = %p (0x%llx dma); " - "in seg %p (0x%llx dma)\n", + xhci_dbg(xhci, "Address = %pK (0x%llx dma); " + "in seg %pK (0x%llx dma)\n", cur_trb, (unsigned long long)xhci_trb_virt_to_dma(cur_seg, cur_trb), cur_seg, @@ -682,8 +682,8 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, { struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; - xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), " - "new deq ptr = %p (0x%llx dma), new cycle = %u\n", + xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %pK (0x%llx dma), " + "new deq ptr = %pK (0x%llx dma), new cycle = %u\n", deq_state->new_deq_seg, (unsigned long long)deq_state->new_deq_seg->dma, deq_state->new_deq_ptr, @@ -841,7 +841,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * short, don't muck with the stream ID after * submission. */ - xhci_warn(xhci, "WARN Cancelled URB %p " + xhci_warn(xhci, "WARN Cancelled URB %pK " "has invalid stream ID %u.\n", cur_td->urb, cur_td->urb->stream_id); @@ -1168,7 +1168,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, } else { xhci_warn(xhci, "Mismatch between completed Set TR Deq " "Ptr command & xHCI internal state.\n"); - xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n", + xhci_warn(xhci, "ep deq seg = %pK, deq ptr = %pK\n", dev->eps[ep_index].queued_deq_seg, dev->eps[ep_index].queued_deq_ptr); } @@ -1277,7 +1277,7 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) xhci->cmd_ring->dequeue, &cycle_state); if (!cur_seg) { - xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci_warn(xhci, "Command ring mismatch, dequeue = %pK %llx (dma)\n", xhci->cmd_ring->dequeue, (unsigned long long) xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, @@ -2660,7 +2660,7 @@ cleanup: URB_SHORT_NOT_OK)) || (status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc))) - xhci_dbg(xhci, "Giveback URB %p, len = %d, " + xhci_dbg(xhci, "Giveback URB %pK, len = %d, " "expected = %d, status = %d\n", urb, urb->actual_length, urb->transfer_buffer_length, @@ -4198,7 +4198,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr); if (addr == 0) { xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); - xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n", + xhci_warn(xhci, "WARN deq seg = %pK, deq pt = %pK\n", deq_seg, deq_ptr); return 0; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9361bd8eef6b..c94f752a5af9 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -678,7 +678,7 @@ int xhci_run(struct usb_hcd *hcd) xhci_writel(xhci, temp, &xhci->op_regs->command); temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); - xhci_dbg(xhci, "// Enabling event ring interrupter %p by writing 0x%x to irq_pending\n", + xhci_dbg(xhci, "// Enabling event ring interrupter %pK by writing 0x%x to irq_pending\n", xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp)); xhci_writel(xhci, ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); @@ -1415,7 +1415,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) exit: return ret; dying: - xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for " + xhci_dbg(xhci, "Ep 0x%x: URB %pK submitted for " "non-responsive xHCI host.\n", urb->ep->desc.bEndpointAddress, urb); ret = -ESHUTDOWN; @@ -1536,7 +1536,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } if ((xhci->xhc_state & XHCI_STATE_DYING) || (xhci->xhc_state & XHCI_STATE_HALTED)) { - xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on " + xhci_dbg(xhci, "Ep 0x%x: URB %pK to be canceled on " "non-responsive xHCI host.\n", urb->ep->desc.bEndpointAddress, urb); /* Let the stop endpoint command watchdog timer (which set this @@ -1558,7 +1558,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) urb_priv = urb->hcpriv; i = urb_priv->td_cnt; if (i < urb_priv->length) - xhci_dbg(xhci, "Cancel URB %p, dev %s, ep 0x%x, " + xhci_dbg(xhci, "Cancel URB %pK, dev %s, ep 0x%x, " "starting at offset 0x%llx\n", urb, urb->dev->devpath, urb->ep->desc.bEndpointAddress, @@ -1622,7 +1622,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, if (xhci->xhc_state & XHCI_STATE_DYING) return -ENODEV; - xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); + xhci_dbg(xhci, "%s called for udev %pK\n", __func__, udev); drop_flag = xhci_get_endpoint_flag(&ep->desc); if (drop_flag == SLOT_FLAG || drop_flag == EP0_FLAG) { xhci_dbg(xhci, "xHCI %s - can't drop slot or ep 0 %#x\n", @@ -1642,7 +1642,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, cpu_to_le32(EP_STATE_DISABLED)) || le32_to_cpu(ctrl_ctx->drop_flags) & xhci_get_endpoint_flag(&ep->desc)) { - xhci_warn(xhci, "xHCI %s called with disabled ep %p\n", + xhci_warn(xhci, "xHCI %s called with disabled ep %pK\n", __func__, ep); return 0; } @@ -1746,7 +1746,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, */ if (le32_to_cpu(ctrl_ctx->add_flags) & xhci_get_endpoint_flag(&ep->desc)) { - xhci_warn(xhci, "xHCI %s called with enabled ep %p\n", + xhci_warn(xhci, "xHCI %s called with enabled ep %pK\n", __func__, ep); return 0; } @@ -2712,7 +2712,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) if (xhci->xhc_state & XHCI_STATE_DYING) return -ENODEV; - xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); + xhci_dbg(xhci, "%s called for udev %pK\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */ @@ -2780,7 +2780,7 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) return; xhci = hcd_to_xhci(hcd); - xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); + xhci_dbg(xhci, "%s called for udev %pK\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; /* Free any rings allocated for added endpoints */ for (i = 0; i < 31; ++i) { @@ -2826,7 +2826,7 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, if (addr == 0) { xhci_warn(xhci, "WARN Cannot submit config ep after " "reset ep command\n"); - xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n", + xhci_warn(xhci, "WARN deq seg = %pK, deq ptr = %pK\n", deq_state->new_deq_seg, deq_state->new_deq_ptr); return; @@ -3811,7 +3811,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) } temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64); - xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n", + xhci_dbg(xhci, "Slot ID %d dcbaa entry @%pK = %#016llx\n", udev->slot_id, &xhci->dcbaa->dev_context_ptrs[udev->slot_id], (unsigned long long) diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index ad408251d955..060d78d53118 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -347,7 +347,7 @@ static int mon_text_open(struct inode *inode, struct file *file) rp->r.rnf_error = mon_text_error; rp->r.rnf_complete = mon_text_complete; - snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp); + snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%pK", rp); rp->e_slab = kmem_cache_create(rp->slab_name, sizeof(struct mon_event_text), sizeof(long), 0, mon_text_ctor); diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index b7a2365c93a5..03bf5ccd5187 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -5833,7 +5833,7 @@ static int msm_otg_probe(struct platform_device *pdev) ret = -ENOMEM; goto devote_bus_bw; } - dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); + dev_info(&pdev->dev, "OTG regs = %pK\n", motg->regs); if (pdata->enable_sec_phy) { res = platform_get_resource_byname(pdev, diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 85a0c3f91267..882187a1512f 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -336,7 +336,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb, /* check for state-transition errors */ if (us->srb != NULL) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", + printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %pK\n", __func__, us->srb); return SCSI_MLQUEUE_HOST_BUSY; } diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index d966b59f7d7b..2778a1a93d76 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -235,7 +235,7 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) { struct uas_cmd_info *ci = (void *)&cmnd->SCp; - scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:" + scmd_printk(KERN_INFO, cmnd, "%s %pK tag %d, inflight:" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", caller, cmnd, cmnd->request->tag, (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e3e8560c2e46..c9000a433475 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -334,7 +334,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) err = usb_submit_urb(ctx->urb, GFP_ATOMIC); if (err < 0) - snd_printk(KERN_ERR "Unable to submit urb #%d: %d (urb %p)\n", + snd_printk(KERN_ERR "Unable to submit urb #%d: %d (urb %pK)\n", ctx->index, err, ctx->urb); else set_bit(ctx->index, &ep->active_mask); @@ -424,7 +424,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, if (ep->ep_num == ep_num && ep->iface == alts->desc.bInterfaceNumber && ep->alt_idx == alts->desc.bAlternateSetting) { - snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%p\n", + snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%pK\n", ep_num, ep->iface, ep->alt_idx, ep); goto __exit_unlock; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0d7a872dab36..05f333ff9c7b 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -228,7 +228,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->data_endpoint; - snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); + snd_printdd(KERN_DEBUG "Starting data EP @%pK\n", ep); ep->data_subs = subs; err = snd_usb_endpoint_start(ep, can_sleep); @@ -257,7 +257,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) } } - snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); + snd_printdd(KERN_DEBUG "Starting sync EP @%pK\n", ep); ep->sync_slave = subs->data_endpoint; err = snd_usb_endpoint_start(ep, can_sleep); @@ -474,12 +474,12 @@ static int match_endpoint_audioformats(struct audioformat *fp, int score = 0; if (fp->channels < 1) { - snd_printdd("%s: (fmt @%p) no channels\n", __func__, fp); + snd_printdd("%s: (fmt @%pK) no channels\n", __func__, fp); return 0; } if (!(fp->formats & pcm_format_to_bits(pcm_format))) { - snd_printdd("%s: (fmt @%p) no match for format %d\n", __func__, + snd_printdd("%s: (fmt @%pK) no match for format %d\n", __func__, fp, pcm_format); return 0; } @@ -491,7 +491,7 @@ static int match_endpoint_audioformats(struct audioformat *fp, } } if (!score) { - snd_printdd("%s: (fmt @%p) no match for rate %d\n", __func__, + snd_printdd("%s: (fmt @%pK) no match for rate %d\n", __func__, fp, rate); return 0; } @@ -499,7 +499,7 @@ static int match_endpoint_audioformats(struct audioformat *fp, if (fp->channels == match->channels) score++; - snd_printdd("%s: (fmt @%p) score %d\n", __func__, fp, score); + snd_printdd("%s: (fmt @%pK) score %d\n", __func__, fp, score); return score; } From 2ce28b255420fbe1337fc414d906987197ae1613 Mon Sep 17 00:00:00 2001 From: Surendar karka Date: Tue, 19 Jul 2016 17:57:02 +0530 Subject: [PATCH 115/210] ASoC: msm: qdsp6v2: Add support to set volume in ASM loopback Allow to set volume in ASM for the loopback driver. Without the get() function the corresponding volume mixer control is failing to set volume. CRs-Fixed: 1034862 Change-Id: I621dd9de3a8d4a0f4102227989e1dd17638c20ea Signed-off-by: Surendar karka --- sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c | 49 +++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c index 5d24a0cd55b7..b899d3280fdb 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2017, 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 @@ -48,7 +48,7 @@ struct msm_pcm_loopback { int capture_start; int session_id; struct audio_client *audio_client; - int volume; + uint32_t volume; }; static void stop_pcm(struct msm_pcm_loopback *pcm); @@ -108,7 +108,8 @@ static void msm_pcm_loopback_event_handler(uint32_t opcode, uint32_t token, } } -static int pcm_loopback_set_volume(struct msm_pcm_loopback *prtd, int volume) +static int pcm_loopback_set_volume(struct msm_pcm_loopback *prtd, + uint32_t volume) { int rc = -EINVAL; @@ -354,10 +355,49 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, int rc = 0; struct snd_pcm_volume *vol = kcontrol->private_data; struct snd_pcm_substream *substream = vol->pcm->streams[0].substream; - struct msm_pcm_loopback *prtd = substream->runtime->private_data; + struct msm_pcm_loopback *prtd; int volume = ucontrol->value.integer.value[0]; + pr_debug("%s: volume : 0x%x\n", __func__, volume); + if ((!substream) || (!substream->runtime)) { + pr_err("%s substream or runtime not found\n", __func__); + rc = -ENODEV; + goto exit; + } + prtd = substream->runtime->private_data; + if (!prtd) { + rc = -ENODEV; + goto exit; + } rc = pcm_loopback_set_volume(prtd, volume); + +exit: + return rc; +} + +static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int rc = 0; + struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream = + vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct msm_pcm_loopback *prtd; + + pr_debug("%s\n", __func__); + if ((!substream) || (!substream->runtime)) { + pr_err("%s substream or runtime not found\n", __func__); + rc = -ENODEV; + goto exit; + } + prtd = substream->runtime->private_data; + if (!prtd) { + rc = -ENODEV; + goto exit; + } + ucontrol->value.integer.value[0] = prtd->volume; + +exit: return rc; } @@ -377,6 +417,7 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) return ret; kctl = volume_info->kctl; kctl->put = msm_pcm_volume_ctl_put; + kctl->get = msm_pcm_volume_ctl_get; kctl->tlv.p = loopback_rx_vol_gain; return 0; } From a11ddddf16b8d175a99d56bf6673e386de1c1a7c Mon Sep 17 00:00:00 2001 From: Yang Xu Date: Thu, 29 Oct 2015 17:46:15 +0800 Subject: [PATCH 116/210] msm: mdss: Add debugfs support for panel command data type Register debugfs node to read from and write to the panel command data type. The default data type is DCS_LONG_WRITE 0x39. Give following command in adb shell to read panel register: cat /sys/kernel/debug/mdp/panel_cmd_data_type To write panel command data type: echo "command_data_type" > /sys/kernel/debug/mdp/panel_cmd_data_type Change-Id: I6dbe5bccb3142e93400825eddf7f05180acfc710 Signed-off-by: Yang Xu --- drivers/video/msm/mdss/mdss_debug.c | 71 +++++++++++++++++------------ drivers/video/msm/mdss/mdss_debug.h | 1 + 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index e93a4edc7fa6..c8e105273910 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -125,32 +125,22 @@ static ssize_t panel_debug_base_reg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; - - u32 cnt, tmp, i; - u32 len = 0; char buf[PANEL_TX_MAX_BUF] = {0x0}; - char *p = NULL; char reg[PANEL_TX_MAX_BUF] = {0x0}; + u32 len = 0, step = 0, value = 0; + char *bufp; struct mdss_data_type *mdata = mdss_res; - struct mdss_mdp_ctl *ctl = mdata->ctl_off + 0; - struct mdss_panel_data *panel_data = ctl->panel_data; - struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, - struct mdss_dsi_ctrl_pdata, panel_data); - + struct mdss_mdp_ctl *ctl; + struct mdss_dsi_ctrl_pdata *ctrl_pdata; struct dsi_cmd_desc dsi_write_cmd = { - {DTYPE_GEN_LWRITE, 1, 0, 0, 0, 0/*len*/}, reg}; + {0/*data type*/, 1, 0, 0, 0, 0/* len */}, reg}; struct dcs_cmd_req cmdreq; - cmdreq.cmds = &dsi_write_cmd; - cmdreq.cmds_cnt = 1; - cmdreq.flags = CMD_REQ_COMMIT; - cmdreq.rlen = 0; - cmdreq.cb = NULL; - if (!dbg || !mdata) return -ENODEV; + /* get command string from user */ if (count >= sizeof(buf)) return -EFAULT; @@ -159,26 +149,38 @@ static ssize_t panel_debug_base_reg_write(struct file *file, buf[count] = 0; /* end of string */ - len = count / 3; - + bufp = buf; + while (sscanf(bufp, "%x%n", &value, &step) > 0) { + reg[len++] = value; + if (len >= PANEL_TX_MAX_BUF) { + pr_err("wrong input reg len\n"); + return -EFAULT; + } + bufp += step; + } if (len < PANEL_CMD_MIN_TX_COUNT) { pr_err("wrong input reg len\n"); return -EFAULT; } - for (i = 0; i < len; i++) { - p = buf + i * 3; - p[2] = 0; - pr_debug("p[%d] = %pK:%s\n", i, p, p); - cnt = sscanf(p, "%x", &tmp); - reg[i] = tmp; - pr_debug("reg[%d] = %x\n", i, (int)reg[i]); - } + /* put command to cmdlist */ + dsi_write_cmd.dchdr.dtype = dbg->cmd_data_type; + dsi_write_cmd.dchdr.dlen = len; + dsi_write_cmd.payload = reg; + + cmdreq.cmds = &dsi_write_cmd; + cmdreq.cmds_cnt = 1; + cmdreq.flags = CMD_REQ_COMMIT; + cmdreq.rlen = 0; + cmdreq.cb = NULL; + + ctl = mdata->ctl_off + 0; + ctrl_pdata = container_of(ctl->panel_data, + struct mdss_dsi_ctrl_pdata, panel_data); if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); - dsi_write_cmd.dchdr.dlen = len; if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); @@ -277,7 +279,7 @@ int panel_debug_register_base(const char *name, void __iomem *base, struct mdss_data_type *mdata = mdss_res; struct mdss_debug_data *mdd; struct mdss_debug_base *dbg; - struct dentry *ent_off, *ent_reg; + struct dentry *ent_off, *ent_reg, *ent_type; char dn[PANEL_DATA_NODE_LEN] = ""; int prefix_len = 0; @@ -294,10 +296,20 @@ int panel_debug_register_base(const char *name, void __iomem *base, dbg->max_offset = max_offset; dbg->off = 0x0a; dbg->cnt = 0x01; + dbg->cmd_data_type = DTYPE_DCS_LWRITE; if (name) prefix_len = snprintf(dn, sizeof(dn), "%s_", name); + strlcpy(dn + prefix_len, "cmd_data_type", sizeof(dn) - prefix_len); + ent_type = debugfs_create_x8(dn, 0644, mdd->root, + (u8 *)&dbg->cmd_data_type); + + if (IS_ERR_OR_NULL(ent_type)) { + pr_err("debugfs_create_file: data_type fail\n"); + goto type_fail; + } + strlcpy(dn + prefix_len, "off", sizeof(dn) - prefix_len); ent_off = debugfs_create_file(dn, 0644, mdd->root, dbg, &panel_off_fops); @@ -318,9 +330,12 @@ int panel_debug_register_base(const char *name, void __iomem *base, list_add(&dbg->head, &mdd->base_list); return 0; + reg_fail: debugfs_remove(ent_off); off_fail: + debugfs_remove(ent_type); +type_fail: kfree(dbg); return -ENODEV; } diff --git a/drivers/video/msm/mdss/mdss_debug.h b/drivers/video/msm/mdss/mdss_debug.h index 830a4518e8a2..8e28f69c86da 100644 --- a/drivers/video/msm/mdss/mdss_debug.h +++ b/drivers/video/msm/mdss/mdss_debug.h @@ -119,6 +119,7 @@ struct mdss_debug_base { void __iomem *base; size_t off; size_t cnt; + u8 cmd_data_type; size_t max_offset; char *buf; size_t buf_len; From 4ec81211788d152bb638aa6866b30e254427bb55 Mon Sep 17 00:00:00 2001 From: Yeleswarapu Nagaradhesh Date: Tue, 14 Feb 2017 14:27:56 +0530 Subject: [PATCH 117/210] ASoC: msm: acquire lock in ioctl If two ioctls are triggered with different commands, there is a possibility to access freed confidence level memory. To resolve this acquire lock in ioctl. Also release mutex lock properly in error cases. CRs-Fixed: 1103085 Change-Id: I7d6b2eff21c8297e5f0755a0c141254be32f777d Signed-off-by: Yeleswarapu Nagaradhesh --- sound/soc/msm/qdsp6v2/msm-lsm-client.c | 93 +++++++++++++++++++------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c index c365220b33c0..63abd1ab39ca 100644 --- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c +++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -84,6 +84,7 @@ struct lsm_priv { atomic_t buf_count; atomic_t read_abort; wait_queue_head_t period_wait; + struct mutex lsm_api_lock; int appl_cnt; int dma_write; }; @@ -869,10 +870,18 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, case SNDRV_LSM_EVENT_STATUS: dev_dbg(rtd->dev, "%s: Get event status\n", __func__); atomic_set(&prtd->event_wait_stop, 0); + + /* + * Release the api lock before wait to allow + * other IOCTLs to be invoked while waiting + * for event + */ + mutex_unlock(&prtd->lsm_api_lock); rc = wait_event_freezable(prtd->event_wait, (cmpxchg(&prtd->event_avail, 1, 0) || (xchg = atomic_cmpxchg(&prtd->event_wait_stop, 1, 0)))); + mutex_lock(&prtd->lsm_api_lock); dev_dbg(rtd->dev, "%s: wait_event_freezable %d event_wait_stop %d\n", __func__, rc, xchg); if (!rc && !xchg) { @@ -1116,6 +1125,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, rtd = substream->private_data; prtd = runtime->private_data; + mutex_lock(&prtd->lsm_api_lock); + switch (cmd) { case SNDRV_LSM_EVENT_STATUS: { struct snd_lsm_event_status *user = NULL, userarg32; @@ -1123,7 +1134,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", __func__, "SNDRV_LSM_EVENT_STATUS"); - return -EFAULT; + err = -EFAULT; + goto done; } if (userarg32.payload_size > @@ -1131,7 +1143,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, pr_err("%s: payload_size %d is invalid, max allowed = %d\n", __func__, userarg32.payload_size, LISTEN_MAX_STATUS_PAYLOAD_SIZE); - return -EINVAL; + err = -EINVAL; + goto done; } size = sizeof(*user) + userarg32.payload_size; @@ -1140,7 +1153,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: Allocation failed event status size %d\n", __func__, size); - return -EFAULT; + err = -EFAULT; + goto done; } else { cmd = SNDRV_LSM_EVENT_STATUS; user->payload_size = userarg32.payload_size; @@ -1189,7 +1203,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: not supported if using topology\n", __func__, "REG_SND_MODEL_V2"); - return -EINVAL; + err = -EINVAL; + goto done; } if (copy_from_user(&snd_modelv232, arg, @@ -1230,7 +1245,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: not supported if using topology\n", __func__, "SET_PARAMS_32"); - return -EINVAL; + err = -EINVAL; } if (copy_from_user(&det_params32, arg, @@ -1273,7 +1288,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: not supported if not using topology\n", __func__, "SET_MODULE_PARAMS_32"); - return -EINVAL; + err = -EINVAL; + goto done; } if (copy_from_user(&p_data_32, arg, @@ -1282,7 +1298,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, "%s: %s: copy_from_user failed, size = %zd\n", __func__, "SET_MODULE_PARAMS_32", sizeof(p_data_32)); - return -EFAULT; + err = -EFAULT; + goto done; } p_data.params = compat_ptr(p_data_32.params); @@ -1294,7 +1311,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, "%s: %s: Invalid num_params %d\n", __func__, "SET_MODULE_PARAMS_32", p_data.num_params); - return -EINVAL; + err = -EINVAL; + goto done; } if (p_data.data_size != @@ -1303,7 +1321,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, "%s: %s: Invalid size %d\n", __func__, "SET_MODULE_PARAMS_32", p_data.data_size); - return -EINVAL; + err = -EINVAL; + goto done; } p_size = sizeof(struct lsm_params_info_32) * @@ -1314,7 +1333,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: no memory for params32, size = %zd\n", __func__, p_size); - return -ENOMEM; + err = -ENOMEM; + goto done; } p_size = sizeof(struct lsm_params_info) * p_data.num_params; @@ -1324,7 +1344,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, "%s: no memory for params, size = %zd\n", __func__, p_size); kfree(params32); - return -ENOMEM; + err = -ENOMEM; + goto done; } if (copy_from_user(params32, p_data.params, @@ -1334,7 +1355,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, __func__, "params32", p_data.data_size); kfree(params32); kfree(params); - return -EFAULT; + err = -EFAULT; + goto done; } p_info_32 = (struct lsm_params_info_32 *) params32; @@ -1377,6 +1399,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, err = msm_lsm_ioctl_shared(substream, cmd, arg); break; } +done: + mutex_unlock(&prtd->lsm_api_lock); return err; } #else @@ -1401,6 +1425,7 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, prtd = runtime->private_data; rtd = substream->private_data; + mutex_lock(&prtd->lsm_api_lock); switch (cmd) { case SNDRV_LSM_REG_SND_MODEL_V2: { struct snd_lsm_sound_model_v2 snd_model_v2; @@ -1409,7 +1434,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: not supported if using topology\n", __func__, "REG_SND_MODEL_V2"); - return -EINVAL; + err = -EINVAL; + goto done; } if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) { @@ -1436,7 +1462,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: not supported if using topology\n", __func__, "SET_PARAMS"); - return -EINVAL; + err = -EINVAL; + goto done; } pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__); @@ -1457,7 +1484,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: LSM_SET_PARAMS failed, err %d\n", __func__, err); - return err; + + goto done; } case SNDRV_LSM_SET_MODULE_PARAMS: { @@ -1469,7 +1497,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: not supported if not using topology\n", __func__, "SET_MODULE_PARAMS"); - return -EINVAL; + err = -EINVAL; + goto done; } if (copy_from_user(&p_data, arg, @@ -1477,7 +1506,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: %s: copy_from_user failed, size = %zd\n", __func__, "p_data", sizeof(p_data)); - return -EFAULT; + err = -EFAULT; + goto done; } if (p_data.num_params > LSM_PARAMS_MAX) { @@ -1485,7 +1515,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, "%s: %s: Invalid num_params %d\n", __func__, "SET_MODULE_PARAMS", p_data.num_params); - return -EINVAL; + err = -EINVAL; + goto done; } p_size = p_data.num_params * @@ -1496,7 +1527,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, "%s: %s: Invalid size %zd\n", __func__, "SET_MODULE_PARAMS", p_size); - return -EFAULT; + err = -EFAULT; + goto done; } params = kzalloc(p_size, GFP_KERNEL); @@ -1504,7 +1536,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: no memory for params\n", __func__); - return -ENOMEM; + err = -ENOMEM; + goto done; } if (copy_from_user(params, p_data.params, @@ -1513,7 +1546,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, "%s: %s: copy_from_user failed, size = %d\n", __func__, "params", p_data.data_size); kfree(params); - return -EFAULT; + err = -EFAULT; + goto done; } err = msm_lsm_process_params(substream, &p_data, params); @@ -1533,7 +1567,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: err copyuser event_status\n", __func__); - return -EFAULT; + err = -EFAULT; + goto done; } if (userarg.payload_size > @@ -1541,7 +1576,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, pr_err("%s: payload_size %d is invalid, max allowed = %d\n", __func__, userarg.payload_size, LISTEN_MAX_STATUS_PAYLOAD_SIZE); - return -EINVAL; + err = -EINVAL; + goto done; } size = sizeof(struct snd_lsm_event_status) + @@ -1551,7 +1587,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: Allocation failed event status size %d\n", __func__, size); - return -EFAULT; + err = -EFAULT; + goto done; } else { user->payload_size = userarg.payload_size; err = msm_lsm_ioctl_shared(substream, cmd, user); @@ -1574,12 +1611,14 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, if (err) dev_err(rtd->dev, "%s: lsmevent failed %d", __func__, err); - return err; + goto done; } default: err = msm_lsm_ioctl_shared(substream, cmd, arg); break; } +done: + mutex_unlock(&prtd->lsm_api_lock); return err; } @@ -1596,6 +1635,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) __func__); return -ENOMEM; } + mutex_init(&prtd->lsm_api_lock); spin_lock_init(&prtd->event_lock); init_waitqueue_head(&prtd->event_wait); init_waitqueue_head(&prtd->period_wait); @@ -1725,6 +1765,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) kfree(prtd->event_status); prtd->event_status = NULL; spin_unlock_irqrestore(&prtd->event_lock, flags); + mutex_destroy(&prtd->lsm_api_lock); kfree(prtd); runtime->private_data = NULL; From dd2b9f3012ff3ab663d0bb725f00372da6fca14c Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Tue, 7 Mar 2017 12:09:57 +0530 Subject: [PATCH 118/210] msm: camera: cpp: Fixing Heap overflow in output buffer Issue: Missing bound check when writing into the output array buffer, which can lead to out-of-bound heap write. Fix: Addding hardcoded constant 8 in the MSM_OUTPUT_BUF_CNT macro and size check to the place where the array is accessed. Returning '0' if exceeds MSM_OUTPUT_BUF_CNT. Caller will return -EINVAL for '0'. CRs-Fixed: 2004036 Change-Id: Ic03f86e3e47ece9ca7069527e741a75ad9a0f83f Signed-off-by: Pratap Nirujogi Signed-off-by: VijayaKumar T M --- drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 2 ++ include/media/msmb_pproc.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 5b09cd230d20..1494ff4c789b 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1794,6 +1794,8 @@ static int msm_cpp_check_buf_type(struct msm_buf_mngr_info *buff_mgr_info, /* More or equal bufs as Input buffer */ num_output_bufs = new_frame->batch_info.batch_size; } + if (num_output_bufs > MSM_OUTPUT_BUF_CNT) + return 0; for (i = 0; i < num_output_bufs; i++) { new_frame->output_buffer_info[i].index = buff_mgr_info->user_buf.buf_idx[i]; diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h index 1650ded2d8a1..cc666c507739 100644 --- a/include/media/msmb_pproc.h +++ b/include/media/msmb_pproc.h @@ -22,6 +22,7 @@ #define MSM_CPP_MAX_FRAME_LENGTH 4096 #define MSM_CPP_MAX_FW_NAME_LEN 32 #define MAX_FREQ_TBL 10 +#define MSM_OUTPUT_BUF_CNT 8 enum msm_cpp_frame_type { MSM_CPP_OFFLINE_FRAME, @@ -82,7 +83,7 @@ struct msm_cpp_frame_info_t { uint32_t feature_mask; uint8_t we_disable; struct msm_cpp_buffer_info_t input_buffer_info; - struct msm_cpp_buffer_info_t output_buffer_info[8]; + struct msm_cpp_buffer_info_t output_buffer_info[MSM_OUTPUT_BUF_CNT]; struct msm_cpp_buffer_info_t duplicate_buffer_info; struct msm_cpp_buffer_info_t tnr_scratch_buffer_info[2]; uint32_t reserved; @@ -277,7 +278,7 @@ struct msm_cpp_frame_info32_t { uint32_t feature_mask; uint8_t we_disable; struct msm_cpp_buffer_info_t input_buffer_info; - struct msm_cpp_buffer_info_t output_buffer_info[8]; + struct msm_cpp_buffer_info_t output_buffer_info[MSM_OUTPUT_BUF_CNT]; struct msm_cpp_buffer_info_t duplicate_buffer_info; struct msm_cpp_buffer_info_t tnr_scratch_buffer_info[2]; uint32_t reserved; From b663f12ea9a04f5d7f1ca9b9dbfa531363dcdb9d Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Tue, 7 Mar 2017 14:50:25 +0530 Subject: [PATCH 119/210] msm: camera: return appropriate error value EINVAL Restructure changes(Ie896fd3da326e5e972266d8004baecf8681aea6d) to return proper error value to the calling function. CRs-Fixed: 1064608 Change-Id: Id56090001856b1aba94b6138041d7973885df590 Signed-off-by: VijayaKumar T M --- drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 3f483ec6a47a..71a919c48fd7 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -889,6 +889,7 @@ static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg) if (++count >= MAX_ISP_REG_LIST) { pr_err("%s:%d Error exceeding the max register count:%u\n", __func__, __LINE__, count); + rc = -EINVAL; break; } if (copy_from_user(&cmd_next, (void __user *)cmd.next, @@ -965,6 +966,7 @@ static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg) if (++count >= MAX_ISP_REG_LIST) { pr_err("%s:%d Error exceeding the max register count:%u\n", __func__, __LINE__, count); + rc = -EINVAL; break; } if (copy_from_user(&cmd_next, compat_ptr(cmd.next), From 1ff52b8fc14bcf92e7230026b698645c2978f77f Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Thu, 12 Jan 2017 13:43:38 -0800 Subject: [PATCH 120/210] misc: qcom: qdsp6v2: Add range check in function aac_in_ioctl_shared Add range check for cfg->sample_rate to prevent the user space from providing an invalid sample rate. CRs-Fixed: 1108109 Change-Id: I17ccda0901aa4ad84d6e2f78679d71aa327f42eb Signed-off-by: Xiaoyu Ye --- drivers/misc/qcom/qdsp6v2/aac_in.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/misc/qcom/qdsp6v2/aac_in.c b/drivers/misc/qcom/qdsp6v2/aac_in.c index 7176c114f85b..ef963451a3f9 100644 --- a/drivers/misc/qcom/qdsp6v2/aac_in.c +++ b/drivers/misc/qcom/qdsp6v2/aac_in.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2017, 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 @@ -34,6 +34,8 @@ #define AAC_FORMAT_ADTS 65535 +#define MAX_SAMPLE_RATE_384K 384000 + static long aac_in_ioctl_shared(struct file *file, unsigned int cmd, void *arg) { struct q6audio_in *audio = file->private_data; @@ -233,6 +235,13 @@ static long aac_in_ioctl_shared(struct file *file, unsigned int cmd, void *arg) break; } + if (cfg->sample_rate > MAX_SAMPLE_RATE_384K) { + pr_err("%s: ERROR: invalid sample rate = %u", + __func__, cfg->sample_rate); + rc = -EINVAL; + break; + } + min_bitrate = ((cfg->sample_rate)*(cfg->channels))/2; /* This calculation should be based on AAC mode. But we cannot * get AAC mode in this setconfig. min_bitrate's logical max From 3e59c6edcb98b289f8e993187fb484242508aa5b Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Wed, 11 Jan 2017 11:09:24 -0800 Subject: [PATCH 121/210] ASoC: msm: qdsp6v2: extend validation of virtual address Validate a buffer virtual address is fully within the region before returning the region to ensure functionality for an extended edge case. Change-Id: Iba3e080889980f393d6a9f0afe0231408b92d654 Signed-off-by: Siena Richard CRs-fixed: 1108461 --- drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c index 1efa994a33e4..cb7e9c94dded 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c @@ -1,6 +1,6 @@ /* Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2017, 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 @@ -120,7 +120,10 @@ static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr, list_for_each_entry(region_elt, &audio->ion_region_queue, list) { if (addr >= region_elt->vaddr && addr < region_elt->vaddr + region_elt->len && - addr + len <= region_elt->vaddr + region_elt->len) { + addr + len <= region_elt->vaddr + region_elt->len && + addr + len > addr) { + /* to avoid integer addition overflow */ + /* offset since we could pass vaddr inside a registerd * ion buffer */ From 317219684c0ffa82b9305b11f0317e953175c7e2 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Tue, 29 Mar 2016 10:24:08 +0530 Subject: [PATCH 122/210] msm: mdss: Remove restore config call in resume MDSS driver calls restore_sec_cfg on every MDSS gdsc toggle. This call is not required for targets where SMMU settings are retained across MDSS power collapse. Hence remove this call for those targets. Change-Id: I09385aee16efca4007b3fc71a988e0de33bc5c65 Signed-off-by: Jayant Shekhar Signed-off-by: Raghavendra Ambadas --- drivers/video/msm/mdss/mdss_mdp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c index d626e9c1d42a..e1a7d2ecd222 100644 --- a/drivers/video/msm/mdss/mdss_mdp.c +++ b/drivers/video/msm/mdss/mdss_mdp.c @@ -1,7 +1,7 @@ /* * MDSS MDP Interface (used by framebuffer core) * - * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2007-2017, The Linux Foundation. All rights reserved. * Copyright (C) 2007 Google Incorporated * * This software is licensed under the terms of the GNU General Public @@ -1014,8 +1014,14 @@ static int mdss_mdp_gdsc_notifier_call(struct notifier_block *self, mdata = container_of(self, struct mdss_data_type, gdsc_cb); - if (event & REGULATOR_EVENT_ENABLE) - __mdss_restore_sec_cfg(mdata); + if (event & REGULATOR_EVENT_ENABLE) { + /* + * As SMMU in low tier targets is not power collapsible, + * hence we don't need to restore sec configuration. + */ + if (!mdss_mdp_req_init_restore_cfg(mdata)) + __mdss_restore_sec_cfg(mdata); + } return NOTIFY_OK; } From 79ef5ed29aa126445c4687ff4cf940212e16e1c2 Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Tue, 28 Feb 2017 12:52:30 -0800 Subject: [PATCH 123/210] drivers: soc: add size check Add size check to ensure the payload fits inside the declared payload size to prevent loss of data when copying. CRs-Fixed: 2009224 Signed-off-by: Siena Richard Change-Id: I4275c626605272941143b54a7b8861b25f8e750a --- drivers/soc/qcom/qdsp6v2/voice_svc.c | 57 +++++++++++++++++++++------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index 10f71b85a15b..fe5458974406 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -368,6 +368,9 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, struct voice_svc_prvt *prtd; struct voice_svc_write_msg *data = NULL; uint32_t cmd; + struct voice_svc_register *register_data = NULL; + struct voice_svc_cmd_request *request_data = NULL; + uint32_t request_payload_size; pr_debug("%s\n", __func__); @@ -416,12 +419,19 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, */ if (count == (sizeof(struct voice_svc_write_msg) + sizeof(struct voice_svc_register))) { - ret = process_reg_cmd( - (struct voice_svc_register *)data->payload, prtd); + register_data = + (struct voice_svc_register *)data->payload; + if (register_data == NULL) { + pr_err("%s: register data is NULL", __func__); + ret = -EINVAL; + goto done; + } + ret = process_reg_cmd(register_data, prtd); if (!ret) ret = count; } else { - pr_err("%s: invalid payload size\n", __func__); + pr_err("%s: invalid data payload size for register command\n", + __func__); ret = -EINVAL; goto done; } @@ -430,19 +440,40 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, /* * Check that count reflects the expected size to ensure * sufficient memory was allocated. Since voice_svc_cmd_request - * has a variable size, check the minimum value count must be. + * has a variable size, check the minimum value count must be to + * parse the message request then check the minimum size to hold + * the payload of the message request. */ if (count >= (sizeof(struct voice_svc_write_msg) + sizeof(struct voice_svc_cmd_request))) { - ret = voice_svc_send_req( - (struct voice_svc_cmd_request *)data->payload, prtd); - if (!ret) - ret = count; - } else { - pr_err("%s: invalid payload size\n", __func__); - ret = -EINVAL; - goto done; - } + request_data = + (struct voice_svc_cmd_request *)data->payload; + if (request_data == NULL) { + pr_err("%s: request data is NULL", __func__); + ret = -EINVAL; + goto done; + } + + request_payload_size = request_data->payload_size; + + if (count >= (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_cmd_request) + + request_payload_size)) { + ret = voice_svc_send_req(request_data, prtd); + if (!ret) + ret = count; + } else { + pr_err("%s: invalid request payload size\n", + __func__); + ret = -EINVAL; + goto done; + } + } else { + pr_err("%s: invalid data payload size for request command\n", + __func__); + ret = -EINVAL; + goto done; + } break; default: pr_debug("%s: Invalid command: %u\n", __func__, cmd); From 28e1b900674d2d7b4db9389de6fe44a3e1bfa145 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Wed, 1 Feb 2017 16:24:01 -0500 Subject: [PATCH 124/210] msm: mdss: Install sync fences after user copy If userspace closes the fd after an error on copying to userspace, the fences may be freed incorrectly. Make sure fences are installed after all checks pass. Bug: 32402303 Change-Id: Ieb50296c87e09549db2734bd70bb6ee8d311ad40 CRs-Fixed: 2000664 Signed-off-by: Naseer Ahmed --- drivers/video/msm/mdss/mdss_fb.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index abd11be0f2f1..2f3bc524045f 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -2,7 +2,7 @@ * Core MDSS framebuffer driver. * * Copyright (C) 2007 Google Incorporated - * Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2008-2017, 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 @@ -3519,8 +3519,6 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_2; } - sync_fence_install(rel_fence, rel_fen_fd); - ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int)); if (ret) { pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name); @@ -3557,8 +3555,6 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_3; } - sync_fence_install(retire_fence, retire_fen_fd); - ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd, sizeof(int)); if (ret) { @@ -3569,6 +3565,9 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_3; } + sync_fence_install(rel_fence, rel_fen_fd); + sync_fence_install(retire_fence, retire_fen_fd); + skip_retire_fence: mutex_unlock(&sync_pt_data->sync_mutex); From 53ad76cced2ef983a8532e2292578afeb4c95817 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Tue, 10 Jan 2017 12:19:08 -0800 Subject: [PATCH 125/210] qseecom: fix potential memory leak in __qseecom_update_cmd_buf_64 __qseecom_update_cmd_buf_64() called __qseecom_allocate_sg_list_buffer() to allocate memory from within a for loop. Should it fail on any other than the first time through the loop, the prior allocations will not be deallocated, make change to deallocate memory in this error case. Change-Id: I8cb71a3b141249d8266aec4890632f200d147405 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index d80e5afb64c3..339ce5d510f7 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -3430,6 +3430,13 @@ cleanup: } return ret; err: + for (i = 0; i < MAX_ION_FD; i++) + if (data->client.sec_buf_fd[i].is_sec_buf_fd && + data->client.sec_buf_fd[i].vbase) + dma_free_coherent(qseecom.pdev, + data->client.sec_buf_fd[i].size, + data->client.sec_buf_fd[i].vbase, + data->client.sec_buf_fd[i].pbase); if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); return -ENOMEM; From fbf3b29ea264c4e0c701a8c808be8a9e30e7fcd0 Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Tue, 13 Dec 2016 15:27:30 -0800 Subject: [PATCH 126/210] msm: ADSPRPC: Buffer length to be copied is truncated The buffer length that is being used to allocate gets truncated due to it being assigned to wrong type causing a much smaller buffer to be allocated than what is required for copying. Change-Id: I30818acd42bd282837c7c7aa16d56d3b95d4dfe7 Signed-off-by: Sathish Ambley --- drivers/char/adsprpc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 391bfe6bd510..91469cdf9f89 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -739,6 +739,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) /* calculate len requreed for copying */ for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; + uintptr_t mstart, mend; ssize_t len = lpra[i].buf.len; if (!len) continue; @@ -746,7 +747,15 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) continue; if (ctx->overps[oix]->offset == 0) copylen = ALIGN(copylen, BALIGN); - copylen += ctx->overps[oix]->mend - ctx->overps[oix]->mstart; + mstart = ctx->overps[oix]->mstart; + mend = ctx->overps[oix]->mend; + VERIFY(err, (mend - mstart) <= LONG_MAX); + if (err) + goto bail; + copylen += mend - mstart; + VERIFY(err, copylen >= 0); + if (err) + goto bail; } ctx->used = copylen; @@ -805,7 +814,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; struct fastrpc_mmap *map = ctx->maps[i]; - int mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; + ssize_t mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; uint64_t buf; ssize_t len = lpra[i].buf.len; if (!len) From 8435361a18a33823c8c8489e15a922c3769e8519 Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Mon, 13 Mar 2017 15:40:43 +0530 Subject: [PATCH 127/210] DSPRPC: Check for buffer overflow condition The buffer length that is being passed could result in overflow condition causing invalid memory to be accessed. gerrit 1841421 is missing few lines from original gerrit, adding missed out code to fix security errors. CRs-Fixed: 1110747 Change-Id: I642fde6bb2d4476e6e49de958be2770c34f116e6 Signed-off-by: Sathish Ambley Signed-off-by: Swetha Chikkaboraiah --- drivers/char/adsprpc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 391bfe6bd510..e0536a56464f 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -563,8 +563,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, goto bail; } ctx->sc = invoke->sc; - if (bufs) - context_build_overlap(ctx); + if (bufs) { + VERIFY(err, 0 == context_build_overlap(ctx)); + if (err) + goto bail; + } ctx->retval = -1; ctx->pid = current->pid; ctx->tgid = current->tgid; From 4e551b3aeba1c1fcd23a2a2ebad994b837ee447c Mon Sep 17 00:00:00 2001 From: Walter Yang Date: Thu, 2 Mar 2017 12:13:34 +0800 Subject: [PATCH 128/210] ASoC: Add backend user count checking Add backend user count checking to protect the index boundary. Change-Id: Ic1b61d1f7130252cc54da0b16553858714988dbd CRs-Fixed: 2009216 Signed-off-by: Walter Yang --- sound/soc/soc-compress.c | 5 +++++ sound/soc/soc-pcm.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 026e51b5ed12..bec8016937a2 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -573,6 +573,11 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, cstream, &async_domain); } else { be_list[j++] = be; + if (j == DPCM_MAX_BE_USERS) { + dev_dbg(fe->dev, + "ASoC: MAX backend users!\n"); + break; + } } } for (i = 0; i < j; i++) { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 425250cc4a64..712ef982c271 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1872,6 +1872,10 @@ void dpcm_be_dai_prepare_async(struct snd_soc_pcm_runtime *fe, int stream, dpcm, domain); } else { dpcm_async[i++] = dpcm; + if (i == DPCM_MAX_BE_USERS) { + dev_dbg(fe->dev, "ASoC: MAX backend users!\n"); + break; + } } } From c430133fa98f9fb4631a551c45a169dd0afca293 Mon Sep 17 00:00:00 2001 From: Puja Gupta Date: Mon, 6 Feb 2017 14:33:19 -0800 Subject: [PATCH 129/210] soc: qcom: pil: Clear elf memory on validation failure Clear memory where elf segments are loaded if any of the segments fail authentication. CRs-Fixed: 1113126 Change-Id: I85d6bdc8efbb5738a863e59c0244222defcc1bcb Signed-off-by: Puja Gupta --- drivers/soc/qcom/peripheral-loader.c | 31 +++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 94e851c89af1..8affd9042159 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -499,11 +499,35 @@ static int pil_init_mmap(struct pil_desc *desc, const struct pil_mdt *mdt) return pil_init_entry_addr(priv, mdt); } +struct pil_map_fw_info { + void *region; + struct dma_attrs attrs; + phys_addr_t base_addr; + struct device *dev; +}; + static void pil_release_mmap(struct pil_desc *desc) { struct pil_priv *priv = desc->priv; struct pil_seg *p, *tmp; u64 zero = 0ULL; + u8 __iomem *buf; + + struct pil_map_fw_info map_fw_info = { + .attrs = desc->attrs, + .region = priv->region, + .base_addr = priv->region_start, + .dev = desc->dev, + }; + + void *map_data = desc->map_data ? desc->map_data : &map_fw_info; + + /* Clear memory so that unauthorized ELF code is not left behind */ + buf = desc->map_fw_mem(priv->region_start, (priv->region_end - + priv->region_start), map_data); + pil_memset_io(buf, 0, (priv->region_end - priv->region_start)); + desc->unmap_fw_mem(buf, (priv->region_end - priv->region_start), + map_data); if (priv->info) { __iowrite32_copy(&priv->info->start, &zero, @@ -519,13 +543,6 @@ static void pil_release_mmap(struct pil_desc *desc) #define IOMAP_SIZE SZ_1M -struct pil_map_fw_info { - void *region; - struct dma_attrs attrs; - phys_addr_t base_addr; - struct device *dev; -}; - static void *map_fw_mem(phys_addr_t paddr, size_t size, void *data) { struct pil_map_fw_info *info = data; From e8dbcc4d772206080c69b164965e95fadb427676 Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Tue, 3 Jan 2017 14:46:23 -0800 Subject: [PATCH 130/210] ASoC: msm: qdsp6v2: Fix out-of-bounds access in put functions Add out of bounds check in routing put functions for the mux value before accessing the texts pointer of soc_enum struct with mux as index. CRs-fixed: 1097569 Change-Id: Ib9ef8d398f0765754b0f79666963fac043b66077 Signed-off-by: Karthikeyan Mani --- sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index aec051dd883b..92ea7d6f6666 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -1549,6 +1549,11 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol, int mux = ucontrol->value.enumerated.item[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + if (mux >= e->max) { + pr_err("%s: Invalid mux value %d\n", __func__, mux); + return -EINVAL; + } + mutex_lock(&routing_lock); switch (ucontrol->value.integer.value[0]) { case 0: @@ -1673,6 +1678,10 @@ static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol, pr_debug("%s: msm_route_ec_ref_rx = %d value = %ld\n", __func__, msm_route_ext_ec_ref, ucontrol->value.integer.value[0]); + if (mux >= e->max) { + pr_err("%s: Invalid mux value %d\n", __func__, mux); + return -EINVAL; + } mutex_lock(&routing_lock); switch (ucontrol->value.integer.value[0]) { From 23769d769299468cf782bf57f29390c426d86edc Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Wed, 11 Jan 2017 12:57:48 -0500 Subject: [PATCH 131/210] msm: mdss: Validate cursor image size Check size of cursor image provided by userspace and return error appropriately. Bug: 34125463 CRs-Fixed: 1115406 Change-Id: I31aee3c9219921cf5c4306b36f8708582b838c38 Signed-off-by: Naseer Ahmed --- drivers/video/msm/mdss/mdss_mdp_overlay.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index c92cdee5325c..179db3fb864f 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -3695,6 +3695,11 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd, if (cursor->set & FB_CUR_SETIMAGE) { u32 cursor_addr; + if (img->width * img->height * 4 > cursor_frame_size) { + pr_err("cursor image size is too large\n"); + ret = -EINVAL; + goto done; + } ret = copy_from_user(mfd->cursor_buf, img->data, img->width * img->height * 4); if (ret) { From 8256767430a45de77596b9b9b8fde6926b9f4aeb Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 18 Nov 2016 22:13:00 +0100 Subject: [PATCH 132/210] l2tp: fix racy SOCK_ZAPPED flag check in l2tp_ip{,6}_bind() Lock socket before checking the SOCK_ZAPPED flag in l2tp_ip6_bind(). Without lock, a concurrent call could modify the socket flags between the sock_flag(sk, SOCK_ZAPPED) test and the lock_sock() call. This way, a socket could be inserted twice in l2tp_ip6_bind_table. Releasing it would then leave a stale pointer there, generating use-after-free errors when walking through the list or modifying adjacent entries. BUG: KASAN: use-after-free in l2tp_ip6_close+0x22e/0x290 at addr ffff8800081b0ed8 Write of size 8 by task syz-executor/10987 CPU: 0 PID: 10987 Comm: syz-executor Not tainted 4.8.0+ #39 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 ffff880031d97838 ffffffff829f835b ffff88001b5a1640 ffff8800081b0ec0 ffff8800081b15a0 ffff8800081b6d20 ffff880031d97860 ffffffff8174d3cc ffff880031d978f0 ffff8800081b0e80 ffff88001b5a1640 ffff880031d978e0 Call Trace: [] dump_stack+0xb3/0x118 lib/dump_stack.c:15 [] kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 [< inline >] print_address_description mm/kasan/report.c:194 [] kasan_report_error+0x1f6/0x4d0 mm/kasan/report.c:283 [< inline >] kasan_report mm/kasan/report.c:303 [] __asan_report_store8_noabort+0x3e/0x40 mm/kasan/report.c:329 [< inline >] __write_once_size ./include/linux/compiler.h:249 [< inline >] __hlist_del ./include/linux/list.h:622 [< inline >] hlist_del_init ./include/linux/list.h:637 [] l2tp_ip6_close+0x22e/0x290 net/l2tp/l2tp_ip6.c:239 [] inet_release+0xed/0x1c0 net/ipv4/af_inet.c:415 [] inet6_release+0x50/0x70 net/ipv6/af_inet6.c:422 [] sock_release+0x8d/0x1d0 net/socket.c:570 [] sock_close+0x16/0x20 net/socket.c:1017 [] __fput+0x28c/0x780 fs/file_table.c:208 [] ____fput+0x15/0x20 fs/file_table.c:244 [] task_work_run+0xf9/0x170 [] do_exit+0x85e/0x2a00 [] do_group_exit+0x108/0x330 [] get_signal+0x617/0x17a0 kernel/signal.c:2307 [] do_signal+0x7f/0x18f0 [] exit_to_usermode_loop+0xbf/0x150 arch/x86/entry/common.c:156 [< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:190 [] syscall_return_slowpath+0x1a0/0x1e0 arch/x86/entry/common.c:259 [] entry_SYSCALL_64_fastpath+0xc4/0xc6 Object at ffff8800081b0ec0, in cache L2TP/IPv6 size: 1448 Allocated: PID = 10987 [ 1116.897025] [] save_stack_trace+0x16/0x20 [ 1116.897025] [] save_stack+0x46/0xd0 [ 1116.897025] [] kasan_kmalloc+0xad/0xe0 [ 1116.897025] [] kasan_slab_alloc+0x12/0x20 [ 1116.897025] [< inline >] slab_post_alloc_hook mm/slab.h:417 [ 1116.897025] [< inline >] slab_alloc_node mm/slub.c:2708 [ 1116.897025] [< inline >] slab_alloc mm/slub.c:2716 [ 1116.897025] [] kmem_cache_alloc+0xc8/0x2b0 mm/slub.c:2721 [ 1116.897025] [] sk_prot_alloc+0x69/0x2b0 net/core/sock.c:1326 [ 1116.897025] [] sk_alloc+0x38/0xae0 net/core/sock.c:1388 [ 1116.897025] [] inet6_create+0x2d7/0x1000 net/ipv6/af_inet6.c:182 [ 1116.897025] [] __sock_create+0x37b/0x640 net/socket.c:1153 [ 1116.897025] [< inline >] sock_create net/socket.c:1193 [ 1116.897025] [< inline >] SYSC_socket net/socket.c:1223 [ 1116.897025] [] SyS_socket+0xef/0x1b0 net/socket.c:1203 [ 1116.897025] [] entry_SYSCALL_64_fastpath+0x23/0xc6 Freed: PID = 10987 [ 1116.897025] [] save_stack_trace+0x16/0x20 [ 1116.897025] [] save_stack+0x46/0xd0 [ 1116.897025] [] kasan_slab_free+0x71/0xb0 [ 1116.897025] [< inline >] slab_free_hook mm/slub.c:1352 [ 1116.897025] [< inline >] slab_free_freelist_hook mm/slub.c:1374 [ 1116.897025] [< inline >] slab_free mm/slub.c:2951 [ 1116.897025] [] kmem_cache_free+0xc8/0x330 mm/slub.c:2973 [ 1116.897025] [< inline >] sk_prot_free net/core/sock.c:1369 [ 1116.897025] [] __sk_destruct+0x32b/0x4f0 net/core/sock.c:1444 [ 1116.897025] [] sk_destruct+0x44/0x80 net/core/sock.c:1452 [ 1116.897025] [] __sk_free+0x53/0x220 net/core/sock.c:1460 [ 1116.897025] [] sk_free+0x23/0x30 net/core/sock.c:1471 [ 1116.897025] [] sk_common_release+0x28c/0x3e0 ./include/net/sock.h:1589 [ 1116.897025] [] l2tp_ip6_close+0x1fe/0x290 net/l2tp/l2tp_ip6.c:243 [ 1116.897025] [] inet_release+0xed/0x1c0 net/ipv4/af_inet.c:415 [ 1116.897025] [] inet6_release+0x50/0x70 net/ipv6/af_inet6.c:422 [ 1116.897025] [] sock_release+0x8d/0x1d0 net/socket.c:570 [ 1116.897025] [] sock_close+0x16/0x20 net/socket.c:1017 [ 1116.897025] [] __fput+0x28c/0x780 fs/file_table.c:208 [ 1116.897025] [] ____fput+0x15/0x20 fs/file_table.c:244 [ 1116.897025] [] task_work_run+0xf9/0x170 [ 1116.897025] [] do_exit+0x85e/0x2a00 [ 1116.897025] [] do_group_exit+0x108/0x330 [ 1116.897025] [] get_signal+0x617/0x17a0 kernel/signal.c:2307 [ 1116.897025] [] do_signal+0x7f/0x18f0 [ 1116.897025] [] exit_to_usermode_loop+0xbf/0x150 arch/x86/entry/common.c:156 [ 1116.897025] [< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:190 [ 1116.897025] [] syscall_return_slowpath+0x1a0/0x1e0 arch/x86/entry/common.c:259 [ 1116.897025] [] entry_SYSCALL_64_fastpath+0xc4/0xc6 Memory state around the buggy address: ffff8800081b0d80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8800081b0e00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc >ffff8800081b0e80: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb ^ ffff8800081b0f00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8800081b0f80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== The same issue exists with l2tp_ip_bind() and l2tp_ip_bind_table. Change-Id: Iad272f18b62d9234da3230056608833ad9fef45d Fixes: c51ce49735c1 ("l2tp: fix oops in L2TP IP sockets for connect() AF_UNSPEC case") Reported-by: Baozeng Ding Reported-by: Andrey Konovalov Tested-by: Baozeng Ding Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Git-commit: 32c231164b762dddefa13af5a0101032c70b50ef Signed-off-by: Srinivasa Rao Kuppala --- net/l2tp/l2tp_ip.c | 5 +++-- net/l2tp/l2tp_ip6.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index da1a1cee1a08..31317f0d6a5a 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -249,8 +249,6 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) int ret; int chk_addr_ret; - if (!sock_flag(sk, SOCK_ZAPPED)) - return -EINVAL; if (addr_len < sizeof(struct sockaddr_l2tpip)) return -EINVAL; if (addr->l2tp_family != AF_INET) @@ -265,6 +263,9 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) read_unlock_bh(&l2tp_ip_lock); lock_sock(sk); + if (!sock_flag(sk, SOCK_ZAPPED)) + goto out; + if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_l2tpip)) goto out; diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 3b61ddd6e4a6..19705cbafdca 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -264,8 +264,6 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) int addr_type; int err; - if (!sock_flag(sk, SOCK_ZAPPED)) - return -EINVAL; if (addr->l2tp_family != AF_INET6) return -EINVAL; if (addr_len < sizeof(*addr)) @@ -291,6 +289,9 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) lock_sock(sk); err = -EINVAL; + if (!sock_flag(sk, SOCK_ZAPPED)) + goto out_unlock; + if (sk->sk_state != TCP_CLOSE) goto out_unlock; From e1a2b0a5b2ea36406f4a531df48056247ce5f302 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Mon, 20 Mar 2017 20:05:08 -0400 Subject: [PATCH 133/210] msm: mdss: Fix fence installation when retire fence is skipped A previous change caused the release fence to not be installed when the retire fence was skipped. Install the release fence regardless of the retire fence status. Change-Id: I13fa1e98984867d8a7d9d318ece8c1a2f1c726ed Signed-off-by: Naseer Ahmed --- drivers/video/msm/mdss/mdss_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 2f3bc524045f..5478edfde6ad 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -3565,10 +3565,10 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_3; } - sync_fence_install(rel_fence, rel_fen_fd); sync_fence_install(retire_fence, retire_fen_fd); skip_retire_fence: + sync_fence_install(rel_fence, rel_fen_fd); mutex_unlock(&sync_pt_data->sync_mutex); if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) From 7f6bc1a3e1589d7d919c741a4f8853f137b6b73f Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Wed, 22 Feb 2017 20:21:27 +0530 Subject: [PATCH 134/210] input : touchscreen: synaptics: Remove fw_update sysfs entries Remove the sysfs entrypoints to fw_update of synaptics driver. BUG: 32769717 Change-Id: I710cb37a8b5382dce7aa6a1d8748be5853a18a7a Git-commit: 2615c5f302441568e6dd20007bc5246d72837e80 Git-repo: https://android.googlesource.com/kernel/msm.git Signed-off-by: Andrew Chant [shjain@codeaurora.org: picked those lines that are applying cleanly to the driver. Some of the lines as per googlesource.com git commit is not applying cleanly.] Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/Kconfig | 10 ++++++++++ drivers/input/touchscreen/synaptics_fw_update.c | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b2917ac46935..e3a44747fdd5 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -955,6 +955,16 @@ config TOUCHSCREEN_FT5X06_GESTURE If unsure, say N. +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + bool "Synaptics DSX firmware update extra sysfs attributes" + depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + help + Say Y here to enable support for extra sysfs attributes + supporting firmware update in a development environment. + This does not affect the core or other subsystem attributes. + + If unsure, say N. + config TOUCHSCREEN_GEN_VKEYS tristate "Touchscreen Virtual Keys Driver" help diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c index f50378046f5e..cac9c7a29a19 100644 --- a/drivers/input/touchscreen/synaptics_fw_update.c +++ b/drivers/input/touchscreen/synaptics_fw_update.c @@ -1305,6 +1305,7 @@ write_config: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_config(void) { int retval; @@ -1357,6 +1358,7 @@ static int fwu_start_write_config(void) return retval; } +#endif static int fwu_do_write_lockdown(bool reset) { @@ -1404,6 +1406,7 @@ exit: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_lockdown(void) { if (parse_header()) @@ -1507,6 +1510,7 @@ static int fwu_do_read_config(void) exit: return retval; } +#endif static int fwu_do_reflash(void) { @@ -1732,6 +1736,7 @@ int synaptics_fw_updater(void) } EXPORT_SYMBOL(synaptics_fw_updater); +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count) @@ -2155,6 +2160,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, (pkg_id[1] << 8) | pkg_id[0], (pkg_id[3] << 8) | pkg_id[2]); } +#endif static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v) { @@ -2188,6 +2194,7 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, return; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static struct bin_attribute dev_attr_data = { .attr = { .name = "data", @@ -2197,8 +2204,10 @@ static struct bin_attribute dev_attr_data = { .read = fwu_sysfs_show_image, .write = fwu_sysfs_store_image, }; +#endif static struct device_attribute attrs[] = { +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP, fwu_sysfs_image_name_show, fwu_sysfs_image_name_store), @@ -2247,6 +2256,7 @@ static struct device_attribute attrs[] = { __ATTR(package_id, S_IRUGO, fwu_sysfs_package_id_show, synaptics_rmi4_store_error), +#endif }; @@ -2332,6 +2342,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) fwu->initialized = true; fwu->polling_mode = false; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, &dev_attr_data); if (retval < 0) { @@ -2340,6 +2351,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) __func__); goto exit_free_mem; } +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj, @@ -2389,7 +2401,9 @@ exit_remove_attrs: &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif exit_free_mem: kfree(fwu->fn_ptr); @@ -2406,7 +2420,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) { unsigned char attr_count; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, From 33c00c70be735c0f0f1e66388619455a79693582 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 2 Dec 2016 09:44:53 -0800 Subject: [PATCH 135/210] net: avoid signed overflows for SO_{SND|RCV}BUFFORCE CAP_NET_ADMIN users should not be allowed to set negative sk_sndbuf or sk_rcvbuf values, as it can lead to various memory corruptions, crashes, OOM.... Note that before commit 82981930125a ("net: cleanups in sock_setsockopt()"), the bug was even more serious, since SO_SNDBUF and SO_RCVBUF were vulnerable. This needs to be backported to all known linux kernels. Again, many thanks to syzkaller team for discovering this gem. Change-Id: Ia33fe0e157dc0a519d69cb9a6604a6049eb24ad7 Signed-off-by: Eric Dumazet Reported-by: Andrey Konovalov Signed-off-by: David S. Miller Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Git-commit: b98b0bc8c431e3ceb4b26b0dfc8db509518fb290 Signed-off-by: Srinivasa Rao Kuppala --- net/core/sock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/sock.c b/net/core/sock.c index af65d17517b8..de1074c63776 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -727,7 +727,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, val = min_t(u32, val, sysctl_wmem_max); set_sndbuf: sk->sk_userlocks |= SOCK_SNDBUF_LOCK; - sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF); + sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); /* Wake up sending tasks if we upped the value. */ sk->sk_write_space(sk); break; @@ -763,7 +763,7 @@ set_rcvbuf: * returning the value we actually used in getsockopt * is the most desirable behavior. */ - sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF); + sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); break; case SO_RCVBUFFORCE: From 5bde210a925ebc0bdff3a9abd73be1dac2d74d87 Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Tue, 17 Jan 2017 07:37:52 -0800 Subject: [PATCH 136/210] input: synaptics: put offset checks under mutex. Place file offset validity checks under mutex. BUG: 33555878 BUG: 33002026 Change-Id: I1945cfc8af7d1a310ae0d7bbb85002d4c448f30b Signed-off-by: Andrew Chant Git-repo: https://android.googlesource.com/kernel/msm Git-commit: e1fb1600fc222337989e3084d68df929882deae5 Resolved minor merge conflict Signed-off-by: Srinivasa Rao Kuppala --- drivers/input/touchscreen/synaptics_rmi_dev.c | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c index ff4f426df7d5..64f051e70e6a 100644 --- a/drivers/input/touchscreen/synaptics_rmi_dev.c +++ b/drivers/input/touchscreen/synaptics_rmi_dev.c @@ -299,18 +299,26 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, return -EBADF; } - if (count == 0) - return 0; + mutex_lock(&(dev_data->file_mutex)); if (count > (REG_ADDR_LIMIT - *f_pos)) count = REG_ADDR_LIMIT - *f_pos; + if (count == 0) { + retval = 0; + goto unlock; + } + + if (*f_pos > REG_ADDR_LIMIT) { + retval = -EFAULT; + goto unlock; + } + tmpbuf = kzalloc(count + 1, GFP_KERNEL); - if (!tmpbuf) - return -ENOMEM; - - mutex_lock(&(dev_data->file_mutex)); - + if (!tmpbuf) { + retval = -ENOMEM; + goto unlock; + } retval = rmidev->fn_ptr->read(rmidev->rmi4_data, *f_pos, tmpbuf, @@ -324,8 +332,9 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, *f_pos += retval; clean_up: - mutex_unlock(&(dev_data->file_mutex)); kfree(tmpbuf); +unlock: + mutex_unlock(&(dev_data->file_mutex)); return retval; } @@ -349,22 +358,31 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, return -EBADF; } - if (count == 0) - return 0; + mutex_lock(&(dev_data->file_mutex)); + + if (*f_pos > REG_ADDR_LIMIT) { + retval = -EFAULT; + goto unlock; + } if (count > (REG_ADDR_LIMIT - *f_pos)) count = REG_ADDR_LIMIT - *f_pos; - tmpbuf = kzalloc(count + 1, GFP_KERNEL); - if (!tmpbuf) - return -ENOMEM; - - if (copy_from_user(tmpbuf, buf, count)) { - kfree(tmpbuf); - return -EFAULT; + if (count == 0) { + retval = 0; + goto unlock; } - mutex_lock(&(dev_data->file_mutex)); + tmpbuf = kzalloc(count + 1, GFP_KERNEL); + if (!tmpbuf) { + retval = -ENOMEM; + goto unlock; + } + + if (copy_from_user(tmpbuf, buf, count)) { + retval = -EFAULT; + goto clean_up; + } retval = rmidev->fn_ptr->write(rmidev->rmi4_data, *f_pos, @@ -373,8 +391,10 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, if (retval >= 0) *f_pos += retval; - mutex_unlock(&(dev_data->file_mutex)); +clean_up: kfree(tmpbuf); +unlock: + mutex_unlock(&(dev_data->file_mutex)); return retval; } From 8bc9801d206f4910101e44e55d5169123349f303 Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Thu, 24 Nov 2016 13:23:10 +0000 Subject: [PATCH 137/210] mpi: Fix NULL ptr dereference in mpi_powm() [ver #3] This fixes CVE-2016-8650. If mpi_powm() is given a zero exponent, it wants to immediately return either 1 or 0, depending on the modulus. However, if the result was initalised with zero limb space, no limbs space is allocated and a NULL-pointer exception ensues. Fix this by allocating a minimal amount of limb space for the result when the 0-exponent case when the result is 1 and not touching the limb space when the result is 0. This affects the use of RSA keys and X.509 certificates that carry them. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] mpi_powm+0x32/0x7e6 PGD 0 Oops: 0002 [#1] SMP Modules linked in: CPU: 3 PID: 3014 Comm: keyctl Not tainted 4.9.0-rc6-fscache+ #278 Hardware name: ASUS All Series/H97-PLUS, BIOS 2306 10/09/2014 task: ffff8804011944c0 task.stack: ffff880401294000 RIP: 0010:[] [] mpi_powm+0x32/0x7e6 RSP: 0018:ffff880401297ad8 EFLAGS: 00010212 RAX: 0000000000000000 RBX: ffff88040868bec0 RCX: ffff88040868bba0 RDX: ffff88040868b260 RSI: ffff88040868bec0 RDI: ffff88040868bee0 RBP: ffff880401297ba8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000047 R11: ffffffff8183b210 R12: 0000000000000000 R13: ffff8804087c7600 R14: 000000000000001f R15: ffff880401297c50 FS: 00007f7a7918c700(0000) GS:ffff88041fb80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 0000000401250000 CR4: 00000000001406e0 Stack: ffff88040868bec0 0000000000000020 ffff880401297b00 ffffffff81376cd4 0000000000000100 ffff880401297b10 ffffffff81376d12 ffff880401297b30 ffffffff81376f37 0000000000000100 0000000000000000 ffff880401297ba8 Call Trace: [] ? __sg_page_iter_next+0x43/0x66 [] ? sg_miter_get_next_page+0x1b/0x5d [] ? sg_miter_next+0x17/0xbd [] ? mpi_read_raw_from_sgl+0xf2/0x146 [] rsa_verify+0x9d/0xee [] ? pkcs1pad_sg_set_buf+0x2e/0xbb [] pkcs1pad_verify+0xc0/0xe1 [] public_key_verify_signature+0x1b0/0x228 [] x509_check_for_self_signed+0xa1/0xc4 [] x509_cert_parse+0x167/0x1a1 [] x509_key_preparse+0x21/0x1a1 [] asymmetric_key_preparse+0x34/0x61 [] key_create_or_update+0x145/0x399 [] SyS_add_key+0x154/0x19e [] do_syscall_64+0x80/0x191 [] entry_SYSCALL64_slow_path+0x25/0x25 Code: 56 41 55 41 54 53 48 81 ec a8 00 00 00 44 8b 71 04 8b 42 04 4c 8b 67 18 45 85 f6 89 45 80 0f 84 b4 06 00 00 85 c0 75 2f 41 ff ce <49> c7 04 24 01 00 00 00 b0 01 75 0b 48 8b 41 18 48 83 38 01 0f RIP [] mpi_powm+0x32/0x7e6 RSP CR2: 0000000000000000 ---[ end trace d82015255d4a5d8d ]--- Basically, this is a backport of a libgcrypt patch: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=patch;h=6e1adb05d290aeeb1c230c763970695f4a538526 Change-Id: I011db424f47dd96c0b6f39895610f8f8cbe92d0f Fixes: cdec9cb5167a ("crypto: GnuPG based MPI lib - source files (part 1)") Signed-off-by: Andrey Ryabinin Signed-off-by: David Howells cc: Dmitry Kasatkin cc: linux-ima-devel@lists.sourceforge.net cc: stable@vger.kernel.org Signed-off-by: James Morris Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Git-commit: f5527fffff3f002b0a6b376163613b82f69de073 Signed-off-by: Srinivasa Rao Kuppala --- lib/mpi/mpi-pow.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index 5464c8744ea9..e24388a863a7 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c @@ -64,8 +64,13 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) if (!esize) { /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 * depending on if MOD equals 1. */ - rp[0] = 1; res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; + if (res->nlimbs) { + if (mpi_resize(res, 1) < 0) + goto enomem; + rp = res->d; + rp[0] = 1; + } res->sign = 0; goto leave; } From f3c1156457506eff3450a7c40e3c668584da0904 Mon Sep 17 00:00:00 2001 From: Philip Pettersson Date: Wed, 30 Nov 2016 14:55:36 -0800 Subject: [PATCH 138/210] packet: fix race condition in packet_set_ring When packet_set_ring creates a ring buffer it will initialize a struct timer_list if the packet version is TPACKET_V3. This value can then be raced by a different thread calling setsockopt to set the version to TPACKET_V1 before packet_set_ring has finished. This leads to a use-after-free on a function pointer in the struct timer_list when the socket is closed as the previously initialized timer will not be deleted. The bug is fixed by taking lock_sock(sk) in packet_setsockopt when changing the packet version while also taking the lock at the start of packet_set_ring. Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.") Signed-off-by: Philip Pettersson Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Git-commit: 84ac7260236a49c79eede91617700174c2c19b0c Change-Id: Ie8237badf9fec9558bb9be1e1bc19fa99d009d1c Signed-off-by: Srinivasa Rao Kuppala --- net/packet/af_packet.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 84c2a1a03c15..10b76d75f55b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3137,19 +3137,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) - return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; switch (val) { case TPACKET_V1: case TPACKET_V2: case TPACKET_V3: - po->tp_version = val; - return 0; + break; default: return -EINVAL; } + lock_sock(sk); + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { + ret = -EBUSY; + } else { + po->tp_version = val; + ret = 0; + } + release_sock(sk); + return ret; } case PACKET_RESERVE: { @@ -3604,6 +3610,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, /* Added to avoid minimal code churn */ struct tpacket_req *req = &req_u->req; + lock_sock(sk); /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { WARN(1, "Tx-ring is not supported.\n"); @@ -3685,7 +3692,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, goto out; } - lock_sock(sk); /* Detach socket from network */ spin_lock(&po->bind_lock); @@ -3734,11 +3740,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, if (!tx_ring) prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue); } - release_sock(sk); if (pg_vec) free_pg_vec(pg_vec, order, req->tp_block_nr); out: + release_sock(sk); return err; } From 756640fa2ff2b4afdd62353d729c5874f96cacdb Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 5 Dec 2016 16:28:28 -0800 Subject: [PATCH 139/210] ANDROID: ion: check for kref overflow Userspace can cause the kref to handles to increment arbitrarily high. Ensure it does not overflow. Signed-off-by: Daniel Rosenberg Bug: 31992382 Test: See bug for poc Change-Id: I6bff1df385742b1d836d43180dc87fadcea80782 Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 0c702db4d90de88df11057bcf0d8fb2dfe741605 Signed-off-by: Dennis Cagle Signed-off-by: c_vkeert --- drivers/staging/android/ion/ion.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bbd6977ee68f..4703d8fecce9 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -16,6 +16,8 @@ * */ +#include +#include #include #include #include @@ -402,6 +404,15 @@ static void ion_handle_get(struct ion_handle *handle) kref_get(&handle->ref); } +/* Must hold the client lock */ +static struct ion_handle* ion_handle_get_check_overflow(struct ion_handle *handle) +{ + if (atomic_read(&handle->ref.refcount) + 1 == 0) + return ERR_PTR(-EOVERFLOW); + ion_handle_get(handle); + return handle; +} + static int ion_handle_put_nolock(struct ion_handle *handle) { int ret; @@ -448,9 +459,9 @@ static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, handle = idr_find(&client->idr, id); if (handle) - ion_handle_get(handle); + return ion_handle_get_check_overflow(handle); - return handle ? handle : ERR_PTR(-EINVAL); + return ERR_PTR(-EINVAL); } struct ion_handle *ion_handle_get_by_id(struct ion_client *client, @@ -1404,7 +1415,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) /* if a handle exists for this buffer just take a reference to it */ handle = ion_handle_lookup(client, buffer); if (!IS_ERR(handle)) { - ion_handle_get(handle); + handle = ion_handle_get_check_overflow(handle); mutex_unlock(&client->lock); goto end; } From d6b06d722c3c7aa16704972492b99f189a20a635 Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Fri, 13 Jan 2017 16:07:58 +0800 Subject: [PATCH 140/210] CHROMIUM: usb: gadget: configfs: Fix KASAN use-after-free When gadget is disconnected, running sequence is like this. . composite_disconnect . Call trace: usb_string_copy+0xd0/0x128 gadget_config_name_configuration_store+0x4 gadget_config_name_attr_store+0x40/0x50 configfs_write_file+0x198/0x1f4 vfs_write+0x100/0x220 SyS_write+0x58/0xa8 . configfs_composite_unbind . configfs_composite_bind In configfs_composite_bind, it has "cn->strings.s = cn->configuration;" When usb_string_copy is invoked. it would allocate memory, copy input string, release previous pointed memory space, and use new allocated memory. When gadget is connected, host sends down request to get information. Call trace: usb_gadget_get_string+0xec/0x168 lookup_string+0x64/0x98 composite_setup+0xa34/0x1ee8 If gadget is disconnected and connected quickly, in the failed case, cn->configuration memory has been released by usb_string_copy kfree but configfs_composite_bind hasn't been run in time to assign new allocated "cn->configuration" pointer to "cn->strings.s". When "strlen(s->s) of usb_gadget_get_string is being executed, the dangling memory is accessed, "BUG: KASAN: use-after-free" error occurs. BUG=chrome-os-partner:58412 TEST=After smaug device was connected to ubuntu PC host, detached and attached type-C cable quickly several times without seeing "BUG: KASAN: use-after-free in usb_gadget_get_string". Change-Id: I58240ee7c55ae8f8fb8597d14f09c5ac07abb032 Signed-off-by: Jim Lin Reviewed-on: https://chromium-review.googlesource.com/428059 Commit-Ready: Jim Lin Tested-by: Jim Lin Reviewed-by: Adrian Salido Reviewed-by: Benson Leung Git-repo: https://chromium.googlesource.com/chromiumos/third_party/kernel Git-commit: a7b597d255d70f6f0c6bfdfb7e4e04f67fcebf9d Signed-off-by: Dennis Cagle --- drivers/usb/gadget/configfs.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index c1d2f8f30b12..a520817fbc36 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -87,21 +87,28 @@ struct gadget_config_name { struct list_head list; }; +#define MAX_USB_STRING_LEN 126 +#define MAX_USB_STRING_WITH_NULL_LEN (MAX_USB_STRING_LEN+1) + static int usb_string_copy(const char *s, char **s_copy) { int ret; char *str; char *copy = *s_copy; ret = strlen(s); - if (ret > 126) + if (ret > MAX_USB_STRING_LEN) return -EOVERFLOW; - str = kstrdup(s, GFP_KERNEL); - if (!str) - return -ENOMEM; + if (copy) { + str = copy; + } else { + str = kmalloc(MAX_USB_STRING_WITH_NULL_LEN, GFP_KERNEL); + if (!str) + return -ENOMEM; + } + strncpy(str, s, MAX_USB_STRING_WITH_NULL_LEN); if (str[ret - 1] == '\n') str[ret - 1] = '\0'; - kfree(copy); *s_copy = str; return 0; } From 28960f526814fc6d351e6569f5df5e97c3f6eb16 Mon Sep 17 00:00:00 2001 From: Senthil Kumar Rajagopal Date: Sat, 4 Mar 2017 12:05:44 +0530 Subject: [PATCH 141/210] msm: camera: isp: fix for out of bound access array There is no bound check in stream_cfg_cmd->num_streams, in functions msm_isp_check_stream_cfg_cmd and msm_isp_stats_update_cgc_override num_streams is used as the index for stream_cfg_cmd->stream_handle array which has a size of 15. Current code did not check the num_streams to make sure that did not exceed the array size CRs-Fixed: 2006015 Change-Id: I7f195c764a4e6c12e4f7c680bc3c9aa7b078e625 Signed-off-by: Senthil Kumar Rajagopal --- .../msm/camera_v2/isp/msm_isp_stats_util.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index d4c545f14e99..8d63bef2153a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017 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 @@ -557,6 +557,12 @@ static int msm_isp_stats_update_cgc_override(struct vfe_device *vfe_dev, int i; uint32_t stats_mask = 0, idx; + if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { + pr_err("%s invalid num_streams %d\n", __func__, + stream_cfg_cmd->num_streams); + return -EINVAL; + } + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); @@ -631,6 +637,12 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, struct msm_vfe_stats_stream *stream_info; struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data; + if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { + pr_err("%s invalid num_streams %d\n", __func__, + stream_cfg_cmd->num_streams); + return -EINVAL; + } + num_stats_comp_mask = vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask; rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams( From e7c425a0bdf0c9eb5361c946b671b6804d20281b Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Tue, 21 Jun 2016 17:05:37 -0700 Subject: [PATCH 142/210] msm: mdss: Check for buffer boundary condition in panel_debug_reg_write - Before reading from new offset in a buffer, check for out of bounds condition. - Avoid using '%n' specifier. - Use kstrtouint() instead of single variable sscanf as per coding guidelines. Change-Id: I10ea6f2b22d554d02f302f5700f6674d08e4777d Signed-off-by: Krishna Srinivas --- drivers/video/msm/mdss/mdss_debug.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index c8e105273910..baa1c778dc2f 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -39,6 +39,9 @@ #define PANEL_CMD_MIN_TX_COUNT 2 #define PANEL_DATA_NODE_LEN 80 +/* Hex number + whitespace */ +#define NEXT_VALUE_OFFSET 3 + static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00}; static int panel_debug_base_open(struct inode *inode, struct file *file) @@ -127,7 +130,7 @@ static ssize_t panel_debug_base_reg_write(struct file *file, struct mdss_debug_base *dbg = file->private_data; char buf[PANEL_TX_MAX_BUF] = {0x0}; char reg[PANEL_TX_MAX_BUF] = {0x0}; - u32 len = 0, step = 0, value = 0; + u32 len = 0, value = 0; char *bufp; struct mdss_data_type *mdata = mdss_res; @@ -150,13 +153,21 @@ static ssize_t panel_debug_base_reg_write(struct file *file, buf[count] = 0; /* end of string */ bufp = buf; - while (sscanf(bufp, "%x%n", &value, &step) > 0) { + /* End of a hex value in given string */ + bufp[NEXT_VALUE_OFFSET - 1] = 0; + while (kstrtouint(bufp, 16, &value) == 0) { reg[len++] = value; if (len >= PANEL_TX_MAX_BUF) { pr_err("wrong input reg len\n"); return -EFAULT; } - bufp += step; + bufp += NEXT_VALUE_OFFSET; + if ((bufp >= (buf + count)) || (bufp < buf)) { + pr_warn("%s,buffer out-of-bounds\n", __func__); + break; + } + /* End of a hex value in given string */ + bufp[NEXT_VALUE_OFFSET - 1] = 0; } if (len < PANEL_CMD_MIN_TX_COUNT) { pr_err("wrong input reg len\n"); From 109ac68ea3008cac1a7d82462d9e71b2db3d9625 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 21 Feb 2017 12:08:50 +0530 Subject: [PATCH 143/210] soc: qcom: pil: Clear elf region on authentication failure In existing implementation elf region was being clearead before memory access to firmware region assigned to HLOS. So to avoid it using separate function which will be called only when HLOS is the owner. Change-Id: I8bb22e4dbe3e1f898678d0c0f6e60268b88fc150 Signed-off-by: Gaurav Kohli --- drivers/soc/qcom/peripheral-loader.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 8affd9042159..864b72061397 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -511,6 +511,22 @@ static void pil_release_mmap(struct pil_desc *desc) struct pil_priv *priv = desc->priv; struct pil_seg *p, *tmp; u64 zero = 0ULL; + + if (priv->info) { + __iowrite32_copy(&priv->info->start, &zero, + sizeof(zero) / 4); + writel_relaxed(0, &priv->info->size); + } + + list_for_each_entry_safe(p, tmp, &priv->segs, list) { + list_del(&p->list); + kfree(p); + } +} + +static void pil_clear_segment(struct pil_desc *desc) +{ + struct pil_priv *priv = desc->priv; u8 __iomem *buf; struct pil_map_fw_info map_fw_info = { @@ -529,16 +545,6 @@ static void pil_release_mmap(struct pil_desc *desc) desc->unmap_fw_mem(buf, (priv->region_end - priv->region_start), map_data); - if (priv->info) { - __iowrite32_copy(&priv->info->start, &zero, - sizeof(zero) / 4); - writel_relaxed(0, &priv->info->size); - } - - list_for_each_entry_safe(p, tmp, &priv->segs, list) { - list_del(&p->list); - kfree(p); - } } #define IOMAP_SIZE SZ_1M @@ -768,6 +774,7 @@ out: &desc->attrs); priv->region = NULL; } + pil_clear_segment(desc); pil_release_mmap(desc); } return ret; From 0199b1b4c09dfd409f0914b51bc31bd83c1ce1e1 Mon Sep 17 00:00:00 2001 From: Senthil Kumar Rajagopal Date: Wed, 15 Feb 2017 15:08:09 +0530 Subject: [PATCH 144/210] msm: isp: fix for potentitial array out of bound access There is no bound check on dual_hw_ms_cmd->num_src, which is coming from userspace num_src is used as the index for the input_src array which has a size of 5. The current code did not check the num_src to make sure that it never exceeds the input_src array size. CRs-Fixed: 2006169 Change-Id: If5927e06e70cce4afb0ae9f2cdfec80f76f83771 Signed-off-by: Senthil Kumar Rajagopal --- drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 71a919c48fd7..f1d0f941abf3 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -837,6 +837,11 @@ static int msm_isp_set_dual_HW_master_slave_mode( } ISP_DBG("%s: vfe %d num_src %d\n", __func__, vfe_dev->pdev->id, dual_hw_ms_cmd->num_src); + if (dual_hw_ms_cmd->num_src > VFE_SRC_MAX) { + pr_err("%s: Error! Invalid num_src %d\n", __func__, + dual_hw_ms_cmd->num_src); + return -EINVAL; + } /* This for loop is for non-primary intf to be marked with Master/Slave * in order for frame id sync. But their timestamp is not saved. * So no sof_info resource is allocated */ From 66cdec63e2ef374e011459034123a2bad32cb85e Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 20 Dec 2016 15:59:19 -0800 Subject: [PATCH 145/210] android: fiq_debugger: restrict access to critical commands. Sysrq must be enabled via /proc/sys/kernel/sysrq as a security measure to enable various critical fiq debugger commands that either leak information or can be used as a system attack. Default disabled, this will leave the reboot, reset, irqs, sleep, nosleep, console and ps commands. Reboot and reset commands will be restricted from taking any parameters. We will also switch to showing the limited command set in this mode. Signed-off-by: Mark Salyzyn Bug: 32402555 Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5 [d-cagle@codeaurora.org: Resolve merge conflict] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 1031836c0895f1f5a05c25efec83bfa11aa08ca9 Signed-off-by: Dennis Cagle --- .../android/fiq_debugger/fiq_debugger.c | 87 ++++++++++++------- drivers/tty/sysrq.c | 3 +- include/linux/sysrq.h | 1 + 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c index 1d733624d70a..ceb45bc9e2a8 100644 --- a/drivers/staging/android/fiq_debugger/fiq_debugger.c +++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -395,7 +396,7 @@ static void fiq_debugger_work(struct work_struct *work) cmd += 6; while (*cmd == ' ') cmd++; - if (cmd != '\0') + if ((cmd != '\0') && sysrq_on()) kernel_restart(cmd); else kernel_restart(NULL); @@ -425,30 +426,39 @@ static void fiq_debugger_irq_exec(struct fiq_debugger_state *state, char *cmd) static void fiq_debugger_help(struct fiq_debugger_state *state) { fiq_debugger_printf(&state->output, - "FIQ Debugger commands:\n" - " pc PC status\n" - " regs Register dump\n" - " allregs Extended Register dump\n" - " bt Stack trace\n"); + "FIQ Debugger commands:\n"); + if (sysrq_on()) { + fiq_debugger_printf(&state->output, + " pc PC status\n" + " regs Register dump\n" + " allregs Extended Register dump\n" + " bt Stack trace\n"); + fiq_debugger_printf(&state->output, + " reboot [] Reboot with command \n" + " reset [] Hard reset with command \n" + " irqs Interrupt status\n" + " kmsg Kernel log\n" + " version Kernel version\n"); + fiq_debugger_printf(&state->output, + " cpu Current CPU\n" + " cpu Switch to CPU\n" + " sysrq sysrq options\n" + " sysrq Execute sysrq with \n"); + } else { + fiq_debugger_printf(&state->output, + " reboot Reboot\n" + " reset Hard reset\n" + " irqs Interrupt status\n"); + } fiq_debugger_printf(&state->output, - " reboot [] Reboot with command \n" - " reset [] Hard reset with command \n" - " irqs Interupt status\n" - " kmsg Kernel log\n" - " version Kernel version\n"); - fiq_debugger_printf(&state->output, - " sleep Allow sleep while in FIQ\n" - " nosleep Disable sleep while in FIQ\n" - " console Switch terminal to console\n" - " cpu Current CPU\n" - " cpu Switch to CPU\n"); - fiq_debugger_printf(&state->output, - " ps Process list\n" - " sysrq sysrq options\n" - " sysrq Execute sysrq with \n"); + " sleep Allow sleep while in FIQ\n" + " nosleep Disable sleep while in FIQ\n" + " console Switch terminal to console\n" + " ps Process list\n"); #ifdef CONFIG_KGDB - fiq_debugger_printf(&state->output, - " kgdb Enter kernel debugger\n"); + if (fiq_kgdb_enable) { + fiq_debugger_printf(&state->output, + " kgdb Enter kernel debugger\n"); #endif } @@ -480,18 +490,23 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { fiq_debugger_help(state); } else if (!strcmp(cmd, "pc")) { - fiq_debugger_dump_pc(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_pc(&state->output, regs); } else if (!strcmp(cmd, "regs")) { - fiq_debugger_dump_regs(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_regs(&state->output, regs); } else if (!strcmp(cmd, "allregs")) { - fiq_debugger_dump_allregs(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_allregs(&state->output, regs); } else if (!strcmp(cmd, "bt")) { - fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp); + if (sysrq_on()) + fiq_debugger_dump_stacktrace(&state->output, regs, + 100, svc_sp); } else if (!strncmp(cmd, "reset", 5)) { cmd += 5; while (*cmd == ' ') cmd++; - if (*cmd) { + if (*cmd && sysrq_on()) { char tmp_cmd[32]; strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd)); machine_restart(tmp_cmd); @@ -501,9 +516,12 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, } else if (!strcmp(cmd, "irqs")) { fiq_debugger_dump_irqs(state); } else if (!strcmp(cmd, "kmsg")) { - fiq_debugger_dump_kernel_log(state); + if (sysrq_on()) + fiq_debugger_dump_kernel_log(state); } else if (!strcmp(cmd, "version")) { - fiq_debugger_printf(&state->output, "%s\n", linux_banner); + if (sysrq_on()) + fiq_debugger_printf(&state->output, "%s\n", + linux_banner); } else if (!strcmp(cmd, "sleep")) { state->no_sleep = false; fiq_debugger_printf(&state->output, "enabling sleep\n"); @@ -515,14 +533,17 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, fiq_debugger_uart_flush(state); state->console_enable = true; } else if (!strcmp(cmd, "cpu")) { - fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); - } else if (!strncmp(cmd, "cpu ", 4)) { + if (sysrq_on()) + fiq_debugger_printf(&state->output, "cpu %d\n", + state->current_cpu); + } else if (!strncmp(cmd, "cpu ", 4) && sysrq_on()) { unsigned long cpu = 0; if (strict_strtoul(cmd + 4, 10, &cpu) == 0) fiq_debugger_switch_cpu(state, cpu); else fiq_debugger_printf(&state->output, "invalid cpu\n"); - fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); + fiq_debugger_printf(&state->output, "cpu %d\n", + state->current_cpu); } else { if (state->debug_busy) { fiq_debugger_printf(&state->output, diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b51c15408ff3..08c9406ca6f8 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -55,10 +55,11 @@ static bool __read_mostly sysrq_always_enabled; unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; int sysrq_reset_downtime_ms __weak; -static bool sysrq_on(void) +bool sysrq_on(void) { return sysrq_enabled || sysrq_always_enabled; } +EXPORT_SYMBOL(sysrq_on); /* * A value of 1 means 'all', other nonzero values are an op mask: diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 7faf933cced7..5a0bd938c6a2 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -45,6 +45,7 @@ struct sysrq_key_op { * are available -- else NULL's). */ +bool sysrq_on(void); void handle_sysrq(int key); void __handle_sysrq(int key, bool check_mask); int register_sysrq_key(int key, struct sysrq_key_op *op); From a96e51831ce54b38e2bdf96826779b9b03ec3d81 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 1 Mar 2017 16:08:27 -0800 Subject: [PATCH 146/210] msm: IPA: add the check on intf query The ipa_ioc_query_intf_rx_props structure comes from the ioctl handler, and it is verified that the size of rx buffer does not exceed the IPA_NUM_PROPS_MAX elements. It is also verified that the "entry->rx" buffer does not exceed IPA_NUM_PROPS_MAX when "entry" is allocated. However, the sizes of the buffer "rx->rx" and the buffer "entry->rx" are not guaranteed to be the same and will lead memory corruption issue. The fix is to add the check before memcpy. Change-Id: Idf5c2d32f47c1a1cffeaa5607193855188893ddb Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_intf.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_intf.c b/drivers/platform/msm/ipa/ipa_intf.c index 9a741070652a..18924a773d05 100644 --- a/drivers/platform/msm/ipa/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_intf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -275,6 +275,14 @@ int ipa_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) mutex_lock(&ipa_ctx->lock); list_for_each_entry(entry, &ipa_ctx->intf_list, link) { if (!strncmp(entry->name, tx->name, IPA_RESOURCE_NAME_MAX)) { + /* add the entry check */ + if (entry->num_tx_props != tx->num_tx_props) { + IPAERR("invalid entry number(%u %u)\n", + entry->num_tx_props, + tx->num_tx_props); + mutex_unlock(&ipa_ctx->lock); + return result; + } memcpy(tx->tx, entry->tx, entry->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop)); result = 0; @@ -308,6 +316,14 @@ int ipa_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) mutex_lock(&ipa_ctx->lock); list_for_each_entry(entry, &ipa_ctx->intf_list, link) { if (!strncmp(entry->name, rx->name, IPA_RESOURCE_NAME_MAX)) { + /* add the entry check */ + if (entry->num_rx_props != rx->num_rx_props) { + IPAERR("invalid entry number(%u %u)\n", + entry->num_rx_props, + rx->num_rx_props); + mutex_unlock(&ipa_ctx->lock); + return result; + } memcpy(rx->rx, entry->rx, entry->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop)); result = 0; @@ -341,6 +357,14 @@ int ipa_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext) mutex_lock(&ipa_ctx->lock); list_for_each_entry(entry, &ipa_ctx->intf_list, link) { if (!strcmp(entry->name, ext->name)) { + /* add the entry check */ + if (entry->num_ext_props != ext->num_ext_props) { + IPAERR("invalid entry number(%u %u)\n", + entry->num_ext_props, + ext->num_ext_props); + mutex_unlock(&ipa_ctx->lock); + return result; + } memcpy(ext->ext, entry->ext, entry->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop)); result = 0; From 6afeb28ffb20e40c3505bef60f1e8542dcfef500 Mon Sep 17 00:00:00 2001 From: Ingrid Gallardo Date: Wed, 1 Mar 2017 12:24:06 -0800 Subject: [PATCH 147/210] msm: mdss: fix race condition in mdp debugfs Fix race condition in mdp debugfs properties during the read and write of the panel and mdp registers. This race condition can cause accessing memory out bounderies. Change-Id: I97a90a154237343d4aaf237c11f525bcc2c3a8e3 Signed-off-by: Ingrid Gallardo Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdss_debug.c | 48 ++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index c8e105273910..14f4e4c4e2bf 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2017, 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 @@ -39,6 +39,8 @@ #define PANEL_CMD_MIN_TX_COUNT 2 #define PANEL_DATA_NODE_LEN 80 +static DEFINE_MUTEX(mdss_debug_lock); + static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00}; static int panel_debug_base_open(struct inode *inode, struct file *file) @@ -88,8 +90,10 @@ static ssize_t panel_debug_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; + mutex_lock(&mdss_debug_lock); dbg->off = off; dbg->cnt = cnt; + mutex_unlock(&mdss_debug_lock); pr_debug("offset=%x cnt=%d\n", off, cnt); @@ -109,15 +113,21 @@ static ssize_t panel_debug_base_offset_read(struct file *file, if (*ppos) return 0; /* the end */ + mutex_lock(&mdss_debug_lock); len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt); - if (len < 0 || len >= sizeof(buf)) + if (len < 0 || len >= sizeof(buf)) { + mutex_unlock(&mdss_debug_lock); return 0; + } - if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { + mutex_unlock(&mdss_debug_lock); return -EFAULT; + } *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; } @@ -206,11 +216,16 @@ static ssize_t panel_debug_base_reg_read(struct file *file, if (!dbg) return -ENODEV; - if (!dbg->cnt) + mutex_lock(&mdss_debug_lock); + if (!dbg->cnt) { + mutex_unlock(&mdss_debug_lock); return 0; + } - if (*ppos) + if (*ppos) { + mutex_unlock(&mdss_debug_lock); return 0; /* the end */ + } /* '0x' + 2 digit + blank = 5 bytes for each number */ reg_buf_len = (dbg->cnt * PANEL_REG_FORMAT_LEN) @@ -251,11 +266,13 @@ static ssize_t panel_debug_base_reg_read(struct file *file, kfree(panel_reg_buf); *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; read_reg_fail: kfree(rx_buf); kfree(panel_reg_buf); + mutex_unlock(&mdss_debug_lock); return rc; } @@ -386,8 +403,10 @@ static ssize_t mdss_debug_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; + mutex_lock(&mdss_debug_lock); dbg->off = off; dbg->cnt = cnt; + mutex_unlock(&mdss_debug_lock); pr_debug("offset=%x cnt=%x\n", off, cnt); @@ -407,15 +426,21 @@ static ssize_t mdss_debug_base_offset_read(struct file *file, if (*ppos) return 0; /* the end */ + mutex_lock(&mdss_debug_lock); len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); - if (len < 0 || len >= sizeof(buf)) + if (len < 0 || len >= sizeof(buf)) { + mutex_unlock(&mdss_debug_lock); return 0; + } - if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { + mutex_unlock(&mdss_debug_lock); return -EFAULT; + } *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; } @@ -472,6 +497,8 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, return -ENODEV; } + mutex_lock(&mdss_debug_lock); + if (!dbg->buf) { char dump_buf[64]; char *ptr; @@ -483,6 +510,7 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, if (!dbg->buf) { pr_err("not enough memory to hold reg dump\n"); + mutex_unlock(&mdss_debug_lock); return -ENOMEM; } @@ -513,17 +541,21 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, dbg->buf_len = tot; } - if (*ppos >= dbg->buf_len) + if (*ppos >= dbg->buf_len) { + mutex_unlock(&mdss_debug_lock); return 0; /* done reading */ + } len = min(count, dbg->buf_len - (size_t) *ppos); if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { pr_err("failed to copy to user\n"); + mutex_unlock(&mdss_debug_lock); return -EFAULT; } *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; } From 3c8b7cba106c8a69ff30437565c95d71a9a3844c Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 5 Dec 2016 16:28:28 -0800 Subject: [PATCH 148/210] ANDROID: ion: check for kref overflow Userspace can cause the kref to handles to increment arbitrarily high. Ensure it does not overflow. Signed-off-by: Daniel Rosenberg Bug: 31992382 Test: See bug for poc Change-Id: I6bff1df385742b1d836d43180dc87fadcea80782 Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 0c702db4d90de88df11057bcf0d8fb2dfe741605 Signed-off-by: Dennis Cagle Signed-off-by: c_vkeert --- drivers/staging/android/ion/ion.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bbd6977ee68f..4703d8fecce9 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -16,6 +16,8 @@ * */ +#include +#include #include #include #include @@ -402,6 +404,15 @@ static void ion_handle_get(struct ion_handle *handle) kref_get(&handle->ref); } +/* Must hold the client lock */ +static struct ion_handle* ion_handle_get_check_overflow(struct ion_handle *handle) +{ + if (atomic_read(&handle->ref.refcount) + 1 == 0) + return ERR_PTR(-EOVERFLOW); + ion_handle_get(handle); + return handle; +} + static int ion_handle_put_nolock(struct ion_handle *handle) { int ret; @@ -448,9 +459,9 @@ static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, handle = idr_find(&client->idr, id); if (handle) - ion_handle_get(handle); + return ion_handle_get_check_overflow(handle); - return handle ? handle : ERR_PTR(-EINVAL); + return ERR_PTR(-EINVAL); } struct ion_handle *ion_handle_get_by_id(struct ion_client *client, @@ -1404,7 +1415,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) /* if a handle exists for this buffer just take a reference to it */ handle = ion_handle_lookup(client, buffer); if (!IS_ERR(handle)) { - ion_handle_get(handle); + handle = ion_handle_get_check_overflow(handle); mutex_unlock(&client->lock); goto end; } From be15b2cbb974de8763f1e0ce0bb1cbcbfc10eddb Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 20 Dec 2016 15:59:19 -0800 Subject: [PATCH 149/210] android: fiq_debugger: restrict access to critical commands. Sysrq must be enabled via /proc/sys/kernel/sysrq as a security measure to enable various critical fiq debugger commands that either leak information or can be used as a system attack. Default disabled, this will leave the reboot, reset, irqs, sleep, nosleep, console and ps commands. Reboot and reset commands will be restricted from taking any parameters. We will also switch to showing the limited command set in this mode. Signed-off-by: Mark Salyzyn Bug: 32402555 Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5 [d-cagle@codeaurora.org: Resolve merge conflict] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 1031836c0895f1f5a05c25efec83bfa11aa08ca9 Signed-off-by: Dennis Cagle --- .../android/fiq_debugger/fiq_debugger.c | 87 ++++++++++++------- drivers/tty/sysrq.c | 3 +- include/linux/sysrq.h | 1 + 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c index 1d733624d70a..ceb45bc9e2a8 100644 --- a/drivers/staging/android/fiq_debugger/fiq_debugger.c +++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -395,7 +396,7 @@ static void fiq_debugger_work(struct work_struct *work) cmd += 6; while (*cmd == ' ') cmd++; - if (cmd != '\0') + if ((cmd != '\0') && sysrq_on()) kernel_restart(cmd); else kernel_restart(NULL); @@ -425,30 +426,39 @@ static void fiq_debugger_irq_exec(struct fiq_debugger_state *state, char *cmd) static void fiq_debugger_help(struct fiq_debugger_state *state) { fiq_debugger_printf(&state->output, - "FIQ Debugger commands:\n" - " pc PC status\n" - " regs Register dump\n" - " allregs Extended Register dump\n" - " bt Stack trace\n"); + "FIQ Debugger commands:\n"); + if (sysrq_on()) { + fiq_debugger_printf(&state->output, + " pc PC status\n" + " regs Register dump\n" + " allregs Extended Register dump\n" + " bt Stack trace\n"); + fiq_debugger_printf(&state->output, + " reboot [] Reboot with command \n" + " reset [] Hard reset with command \n" + " irqs Interrupt status\n" + " kmsg Kernel log\n" + " version Kernel version\n"); + fiq_debugger_printf(&state->output, + " cpu Current CPU\n" + " cpu Switch to CPU\n" + " sysrq sysrq options\n" + " sysrq Execute sysrq with \n"); + } else { + fiq_debugger_printf(&state->output, + " reboot Reboot\n" + " reset Hard reset\n" + " irqs Interrupt status\n"); + } fiq_debugger_printf(&state->output, - " reboot [] Reboot with command \n" - " reset [] Hard reset with command \n" - " irqs Interupt status\n" - " kmsg Kernel log\n" - " version Kernel version\n"); - fiq_debugger_printf(&state->output, - " sleep Allow sleep while in FIQ\n" - " nosleep Disable sleep while in FIQ\n" - " console Switch terminal to console\n" - " cpu Current CPU\n" - " cpu Switch to CPU\n"); - fiq_debugger_printf(&state->output, - " ps Process list\n" - " sysrq sysrq options\n" - " sysrq Execute sysrq with \n"); + " sleep Allow sleep while in FIQ\n" + " nosleep Disable sleep while in FIQ\n" + " console Switch terminal to console\n" + " ps Process list\n"); #ifdef CONFIG_KGDB - fiq_debugger_printf(&state->output, - " kgdb Enter kernel debugger\n"); + if (fiq_kgdb_enable) { + fiq_debugger_printf(&state->output, + " kgdb Enter kernel debugger\n"); #endif } @@ -480,18 +490,23 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { fiq_debugger_help(state); } else if (!strcmp(cmd, "pc")) { - fiq_debugger_dump_pc(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_pc(&state->output, regs); } else if (!strcmp(cmd, "regs")) { - fiq_debugger_dump_regs(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_regs(&state->output, regs); } else if (!strcmp(cmd, "allregs")) { - fiq_debugger_dump_allregs(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_allregs(&state->output, regs); } else if (!strcmp(cmd, "bt")) { - fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp); + if (sysrq_on()) + fiq_debugger_dump_stacktrace(&state->output, regs, + 100, svc_sp); } else if (!strncmp(cmd, "reset", 5)) { cmd += 5; while (*cmd == ' ') cmd++; - if (*cmd) { + if (*cmd && sysrq_on()) { char tmp_cmd[32]; strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd)); machine_restart(tmp_cmd); @@ -501,9 +516,12 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, } else if (!strcmp(cmd, "irqs")) { fiq_debugger_dump_irqs(state); } else if (!strcmp(cmd, "kmsg")) { - fiq_debugger_dump_kernel_log(state); + if (sysrq_on()) + fiq_debugger_dump_kernel_log(state); } else if (!strcmp(cmd, "version")) { - fiq_debugger_printf(&state->output, "%s\n", linux_banner); + if (sysrq_on()) + fiq_debugger_printf(&state->output, "%s\n", + linux_banner); } else if (!strcmp(cmd, "sleep")) { state->no_sleep = false; fiq_debugger_printf(&state->output, "enabling sleep\n"); @@ -515,14 +533,17 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, fiq_debugger_uart_flush(state); state->console_enable = true; } else if (!strcmp(cmd, "cpu")) { - fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); - } else if (!strncmp(cmd, "cpu ", 4)) { + if (sysrq_on()) + fiq_debugger_printf(&state->output, "cpu %d\n", + state->current_cpu); + } else if (!strncmp(cmd, "cpu ", 4) && sysrq_on()) { unsigned long cpu = 0; if (strict_strtoul(cmd + 4, 10, &cpu) == 0) fiq_debugger_switch_cpu(state, cpu); else fiq_debugger_printf(&state->output, "invalid cpu\n"); - fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); + fiq_debugger_printf(&state->output, "cpu %d\n", + state->current_cpu); } else { if (state->debug_busy) { fiq_debugger_printf(&state->output, diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b51c15408ff3..08c9406ca6f8 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -55,10 +55,11 @@ static bool __read_mostly sysrq_always_enabled; unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; int sysrq_reset_downtime_ms __weak; -static bool sysrq_on(void) +bool sysrq_on(void) { return sysrq_enabled || sysrq_always_enabled; } +EXPORT_SYMBOL(sysrq_on); /* * A value of 1 means 'all', other nonzero values are an op mask: diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 7faf933cced7..5a0bd938c6a2 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -45,6 +45,7 @@ struct sysrq_key_op { * are available -- else NULL's). */ +bool sysrq_on(void); void handle_sysrq(int key); void __handle_sysrq(int key, bool check_mask); int register_sysrq_key(int key, struct sysrq_key_op *op); From 72dec50463e9c37668407645e0cdb7e393e961ae Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 1 Mar 2017 16:08:27 -0800 Subject: [PATCH 150/210] msm: IPA: add the check on intf query The ipa_ioc_query_intf_rx_props structure comes from the ioctl handler, and it is verified that the size of rx buffer does not exceed the IPA_NUM_PROPS_MAX elements. It is also verified that the "entry->rx" buffer does not exceed IPA_NUM_PROPS_MAX when "entry" is allocated. However, the sizes of the buffer "rx->rx" and the buffer "entry->rx" are not guaranteed to be the same and will lead memory corruption issue. The fix is to add the check before memcpy. Change-Id: Idf5c2d32f47c1a1cffeaa5607193855188893ddb Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_intf.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_intf.c b/drivers/platform/msm/ipa/ipa_intf.c index 9a741070652a..18924a773d05 100644 --- a/drivers/platform/msm/ipa/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_intf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -275,6 +275,14 @@ int ipa_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) mutex_lock(&ipa_ctx->lock); list_for_each_entry(entry, &ipa_ctx->intf_list, link) { if (!strncmp(entry->name, tx->name, IPA_RESOURCE_NAME_MAX)) { + /* add the entry check */ + if (entry->num_tx_props != tx->num_tx_props) { + IPAERR("invalid entry number(%u %u)\n", + entry->num_tx_props, + tx->num_tx_props); + mutex_unlock(&ipa_ctx->lock); + return result; + } memcpy(tx->tx, entry->tx, entry->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop)); result = 0; @@ -308,6 +316,14 @@ int ipa_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) mutex_lock(&ipa_ctx->lock); list_for_each_entry(entry, &ipa_ctx->intf_list, link) { if (!strncmp(entry->name, rx->name, IPA_RESOURCE_NAME_MAX)) { + /* add the entry check */ + if (entry->num_rx_props != rx->num_rx_props) { + IPAERR("invalid entry number(%u %u)\n", + entry->num_rx_props, + rx->num_rx_props); + mutex_unlock(&ipa_ctx->lock); + return result; + } memcpy(rx->rx, entry->rx, entry->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop)); result = 0; @@ -341,6 +357,14 @@ int ipa_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext) mutex_lock(&ipa_ctx->lock); list_for_each_entry(entry, &ipa_ctx->intf_list, link) { if (!strcmp(entry->name, ext->name)) { + /* add the entry check */ + if (entry->num_ext_props != ext->num_ext_props) { + IPAERR("invalid entry number(%u %u)\n", + entry->num_ext_props, + ext->num_ext_props); + mutex_unlock(&ipa_ctx->lock); + return result; + } memcpy(ext->ext, entry->ext, entry->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop)); result = 0; From 30700cfef165e1538136cb07f5837958faba6715 Mon Sep 17 00:00:00 2001 From: Senthil Kumar Rajagopal Date: Wed, 15 Feb 2017 15:08:09 +0530 Subject: [PATCH 151/210] msm: isp: fix for potentitial array out of bound access There is no bound check on dual_hw_ms_cmd->num_src, which is coming from userspace num_src is used as the index for the input_src array which has a size of 5. The current code did not check the num_src to make sure that it never exceeds the input_src array size. CRs-Fixed: 2006169 Change-Id: If5927e06e70cce4afb0ae9f2cdfec80f76f83771 Signed-off-by: Senthil Kumar Rajagopal --- drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 71a919c48fd7..f1d0f941abf3 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -837,6 +837,11 @@ static int msm_isp_set_dual_HW_master_slave_mode( } ISP_DBG("%s: vfe %d num_src %d\n", __func__, vfe_dev->pdev->id, dual_hw_ms_cmd->num_src); + if (dual_hw_ms_cmd->num_src > VFE_SRC_MAX) { + pr_err("%s: Error! Invalid num_src %d\n", __func__, + dual_hw_ms_cmd->num_src); + return -EINVAL; + } /* This for loop is for non-primary intf to be marked with Master/Slave * in order for frame id sync. But their timestamp is not saved. * So no sof_info resource is allocated */ From 7324f5a69c8a244dadf5e547334f7d1e644c1fd1 Mon Sep 17 00:00:00 2001 From: Senthil Kumar Rajagopal Date: Sat, 4 Mar 2017 12:05:44 +0530 Subject: [PATCH 152/210] msm: camera: isp: fix for out of bound access array There is no bound check in stream_cfg_cmd->num_streams, in functions msm_isp_check_stream_cfg_cmd and msm_isp_stats_update_cgc_override num_streams is used as the index for stream_cfg_cmd->stream_handle array which has a size of 15. Current code did not check the num_streams to make sure that did not exceed the array size CRs-Fixed: 2006015 Change-Id: I7f195c764a4e6c12e4f7c680bc3c9aa7b078e625 Signed-off-by: Senthil Kumar Rajagopal --- .../msm/camera_v2/isp/msm_isp_stats_util.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index d4c545f14e99..8d63bef2153a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017 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 @@ -557,6 +557,12 @@ static int msm_isp_stats_update_cgc_override(struct vfe_device *vfe_dev, int i; uint32_t stats_mask = 0, idx; + if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { + pr_err("%s invalid num_streams %d\n", __func__, + stream_cfg_cmd->num_streams); + return -EINVAL; + } + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); @@ -631,6 +637,12 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, struct msm_vfe_stats_stream *stream_info; struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data; + if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { + pr_err("%s invalid num_streams %d\n", __func__, + stream_cfg_cmd->num_streams); + return -EINVAL; + } + num_stats_comp_mask = vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask; rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams( From bde3e0071584d7e24129e9f756faf3958ccb2387 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Tue, 21 Jun 2016 17:05:37 -0700 Subject: [PATCH 153/210] msm: mdss: Check for buffer boundary condition in panel_debug_reg_write - Before reading from new offset in a buffer, check for out of bounds condition. - Avoid using '%n' specifier. - Use kstrtouint() instead of single variable sscanf as per coding guidelines. Change-Id: I10ea6f2b22d554d02f302f5700f6674d08e4777d Signed-off-by: Krishna Srinivas --- drivers/video/msm/mdss/mdss_debug.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index c8e105273910..baa1c778dc2f 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -39,6 +39,9 @@ #define PANEL_CMD_MIN_TX_COUNT 2 #define PANEL_DATA_NODE_LEN 80 +/* Hex number + whitespace */ +#define NEXT_VALUE_OFFSET 3 + static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00}; static int panel_debug_base_open(struct inode *inode, struct file *file) @@ -127,7 +130,7 @@ static ssize_t panel_debug_base_reg_write(struct file *file, struct mdss_debug_base *dbg = file->private_data; char buf[PANEL_TX_MAX_BUF] = {0x0}; char reg[PANEL_TX_MAX_BUF] = {0x0}; - u32 len = 0, step = 0, value = 0; + u32 len = 0, value = 0; char *bufp; struct mdss_data_type *mdata = mdss_res; @@ -150,13 +153,21 @@ static ssize_t panel_debug_base_reg_write(struct file *file, buf[count] = 0; /* end of string */ bufp = buf; - while (sscanf(bufp, "%x%n", &value, &step) > 0) { + /* End of a hex value in given string */ + bufp[NEXT_VALUE_OFFSET - 1] = 0; + while (kstrtouint(bufp, 16, &value) == 0) { reg[len++] = value; if (len >= PANEL_TX_MAX_BUF) { pr_err("wrong input reg len\n"); return -EFAULT; } - bufp += step; + bufp += NEXT_VALUE_OFFSET; + if ((bufp >= (buf + count)) || (bufp < buf)) { + pr_warn("%s,buffer out-of-bounds\n", __func__); + break; + } + /* End of a hex value in given string */ + bufp[NEXT_VALUE_OFFSET - 1] = 0; } if (len < PANEL_CMD_MIN_TX_COUNT) { pr_err("wrong input reg len\n"); From babcf5449d7fee4a29b7b6d805709fa4dfb2aa67 Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Wed, 22 Feb 2017 20:21:27 +0530 Subject: [PATCH 154/210] input : touchscreen: synaptics: Remove fw_update sysfs entries Remove the sysfs entrypoints to fw_update of synaptics driver. BUG: 32769717 Change-Id: I710cb37a8b5382dce7aa6a1d8748be5853a18a7a Git-commit: 2615c5f302441568e6dd20007bc5246d72837e80 Git-repo: https://android.googlesource.com/kernel/msm.git Signed-off-by: Andrew Chant [shjain@codeaurora.org: picked those lines that are applying cleanly to the driver. Some of the lines as per googlesource.com git commit is not applying cleanly.] Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/Kconfig | 10 ++++++++++ drivers/input/touchscreen/synaptics_fw_update.c | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b2917ac46935..e3a44747fdd5 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -955,6 +955,16 @@ config TOUCHSCREEN_FT5X06_GESTURE If unsure, say N. +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + bool "Synaptics DSX firmware update extra sysfs attributes" + depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + help + Say Y here to enable support for extra sysfs attributes + supporting firmware update in a development environment. + This does not affect the core or other subsystem attributes. + + If unsure, say N. + config TOUCHSCREEN_GEN_VKEYS tristate "Touchscreen Virtual Keys Driver" help diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c index f50378046f5e..cac9c7a29a19 100644 --- a/drivers/input/touchscreen/synaptics_fw_update.c +++ b/drivers/input/touchscreen/synaptics_fw_update.c @@ -1305,6 +1305,7 @@ write_config: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_config(void) { int retval; @@ -1357,6 +1358,7 @@ static int fwu_start_write_config(void) return retval; } +#endif static int fwu_do_write_lockdown(bool reset) { @@ -1404,6 +1406,7 @@ exit: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_lockdown(void) { if (parse_header()) @@ -1507,6 +1510,7 @@ static int fwu_do_read_config(void) exit: return retval; } +#endif static int fwu_do_reflash(void) { @@ -1732,6 +1736,7 @@ int synaptics_fw_updater(void) } EXPORT_SYMBOL(synaptics_fw_updater); +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count) @@ -2155,6 +2160,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, (pkg_id[1] << 8) | pkg_id[0], (pkg_id[3] << 8) | pkg_id[2]); } +#endif static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v) { @@ -2188,6 +2194,7 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, return; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static struct bin_attribute dev_attr_data = { .attr = { .name = "data", @@ -2197,8 +2204,10 @@ static struct bin_attribute dev_attr_data = { .read = fwu_sysfs_show_image, .write = fwu_sysfs_store_image, }; +#endif static struct device_attribute attrs[] = { +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP, fwu_sysfs_image_name_show, fwu_sysfs_image_name_store), @@ -2247,6 +2256,7 @@ static struct device_attribute attrs[] = { __ATTR(package_id, S_IRUGO, fwu_sysfs_package_id_show, synaptics_rmi4_store_error), +#endif }; @@ -2332,6 +2342,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) fwu->initialized = true; fwu->polling_mode = false; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, &dev_attr_data); if (retval < 0) { @@ -2340,6 +2351,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) __func__); goto exit_free_mem; } +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj, @@ -2389,7 +2401,9 @@ exit_remove_attrs: &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif exit_free_mem: kfree(fwu->fn_ptr); @@ -2406,7 +2420,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) { unsigned char attr_count; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, From 7eca2834095e512ea87909312c90b495a3052822 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Mon, 20 Mar 2017 20:05:08 -0400 Subject: [PATCH 159/210] msm: mdss: Fix fence installation when retire fence is skipped A previous change caused the release fence to not be installed when the retire fence was skipped. Install the release fence regardless of the retire fence status. Change-Id: I13fa1e98984867d8a7d9d318ece8c1a2f1c726ed Signed-off-by: Naseer Ahmed --- drivers/video/msm/mdss/mdss_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 2f3bc524045f..5478edfde6ad 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -3565,10 +3565,10 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, goto buf_sync_err_3; } - sync_fence_install(rel_fence, rel_fen_fd); sync_fence_install(retire_fence, retire_fen_fd); skip_retire_fence: + sync_fence_install(rel_fence, rel_fen_fd); mutex_unlock(&sync_pt_data->sync_mutex); if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) From 2adf65605213fb42ddc88fdacec2c58e6a2ad61b Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Tue, 21 Feb 2017 12:08:50 +0530 Subject: [PATCH 160/210] soc: qcom: pil: Clear elf region on authentication failure In existing implementation elf region was being clearead before memory access to firmware region assigned to HLOS. So to avoid it using separate function which will be called only when HLOS is the owner. Change-Id: I8bb22e4dbe3e1f898678d0c0f6e60268b88fc150 Signed-off-by: Gaurav Kohli --- drivers/soc/qcom/peripheral-loader.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 8affd9042159..864b72061397 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -511,6 +511,22 @@ static void pil_release_mmap(struct pil_desc *desc) struct pil_priv *priv = desc->priv; struct pil_seg *p, *tmp; u64 zero = 0ULL; + + if (priv->info) { + __iowrite32_copy(&priv->info->start, &zero, + sizeof(zero) / 4); + writel_relaxed(0, &priv->info->size); + } + + list_for_each_entry_safe(p, tmp, &priv->segs, list) { + list_del(&p->list); + kfree(p); + } +} + +static void pil_clear_segment(struct pil_desc *desc) +{ + struct pil_priv *priv = desc->priv; u8 __iomem *buf; struct pil_map_fw_info map_fw_info = { @@ -529,16 +545,6 @@ static void pil_release_mmap(struct pil_desc *desc) desc->unmap_fw_mem(buf, (priv->region_end - priv->region_start), map_data); - if (priv->info) { - __iowrite32_copy(&priv->info->start, &zero, - sizeof(zero) / 4); - writel_relaxed(0, &priv->info->size); - } - - list_for_each_entry_safe(p, tmp, &priv->segs, list) { - list_del(&p->list); - kfree(p); - } } #define IOMAP_SIZE SZ_1M @@ -768,6 +774,7 @@ out: &desc->attrs); priv->region = NULL; } + pil_clear_segment(desc); pil_release_mmap(desc); } return ret; From 2ecf35d99256fc409a0df8e153ab7c37fc3f3cec Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Fri, 13 Jan 2017 16:07:58 +0800 Subject: [PATCH 161/210] CHROMIUM: usb: gadget: configfs: Fix KASAN use-after-free When gadget is disconnected, running sequence is like this. . composite_disconnect . Call trace: usb_string_copy+0xd0/0x128 gadget_config_name_configuration_store+0x4 gadget_config_name_attr_store+0x40/0x50 configfs_write_file+0x198/0x1f4 vfs_write+0x100/0x220 SyS_write+0x58/0xa8 . configfs_composite_unbind . configfs_composite_bind In configfs_composite_bind, it has "cn->strings.s = cn->configuration;" When usb_string_copy is invoked. it would allocate memory, copy input string, release previous pointed memory space, and use new allocated memory. When gadget is connected, host sends down request to get information. Call trace: usb_gadget_get_string+0xec/0x168 lookup_string+0x64/0x98 composite_setup+0xa34/0x1ee8 If gadget is disconnected and connected quickly, in the failed case, cn->configuration memory has been released by usb_string_copy kfree but configfs_composite_bind hasn't been run in time to assign new allocated "cn->configuration" pointer to "cn->strings.s". When "strlen(s->s) of usb_gadget_get_string is being executed, the dangling memory is accessed, "BUG: KASAN: use-after-free" error occurs. BUG=chrome-os-partner:58412 TEST=After smaug device was connected to ubuntu PC host, detached and attached type-C cable quickly several times without seeing "BUG: KASAN: use-after-free in usb_gadget_get_string". Change-Id: I58240ee7c55ae8f8fb8597d14f09c5ac07abb032 Signed-off-by: Jim Lin Reviewed-on: https://chromium-review.googlesource.com/428059 Commit-Ready: Jim Lin Tested-by: Jim Lin Reviewed-by: Adrian Salido Reviewed-by: Benson Leung Git-repo: https://chromium.googlesource.com/chromiumos/third_party/kernel Git-commit: a7b597d255d70f6f0c6bfdfb7e4e04f67fcebf9d Signed-off-by: Dennis Cagle --- drivers/usb/gadget/configfs.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index c1d2f8f30b12..a520817fbc36 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -87,21 +87,28 @@ struct gadget_config_name { struct list_head list; }; +#define MAX_USB_STRING_LEN 126 +#define MAX_USB_STRING_WITH_NULL_LEN (MAX_USB_STRING_LEN+1) + static int usb_string_copy(const char *s, char **s_copy) { int ret; char *str; char *copy = *s_copy; ret = strlen(s); - if (ret > 126) + if (ret > MAX_USB_STRING_LEN) return -EOVERFLOW; - str = kstrdup(s, GFP_KERNEL); - if (!str) - return -ENOMEM; + if (copy) { + str = copy; + } else { + str = kmalloc(MAX_USB_STRING_WITH_NULL_LEN, GFP_KERNEL); + if (!str) + return -ENOMEM; + } + strncpy(str, s, MAX_USB_STRING_WITH_NULL_LEN); if (str[ret - 1] == '\n') str[ret - 1] = '\0'; - kfree(copy); *s_copy = str; return 0; } From 6e73d50c148fbefc3106a2cb1a03fc4f72920711 Mon Sep 17 00:00:00 2001 From: Ingrid Gallardo Date: Wed, 1 Mar 2017 12:24:06 -0800 Subject: [PATCH 162/210] msm: mdss: fix race condition in mdp debugfs Fix race condition in mdp debugfs properties during the read and write of the panel and mdp registers. This race condition can cause accessing memory out bounderies. Change-Id: I97a90a154237343d4aaf237c11f525bcc2c3a8e3 Signed-off-by: Ingrid Gallardo Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdss_debug.c | 48 ++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index baa1c778dc2f..3886183326a5 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2017, 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 @@ -39,6 +39,8 @@ #define PANEL_CMD_MIN_TX_COUNT 2 #define PANEL_DATA_NODE_LEN 80 +static DEFINE_MUTEX(mdss_debug_lock); + /* Hex number + whitespace */ #define NEXT_VALUE_OFFSET 3 @@ -91,8 +93,10 @@ static ssize_t panel_debug_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; + mutex_lock(&mdss_debug_lock); dbg->off = off; dbg->cnt = cnt; + mutex_unlock(&mdss_debug_lock); pr_debug("offset=%x cnt=%d\n", off, cnt); @@ -112,15 +116,21 @@ static ssize_t panel_debug_base_offset_read(struct file *file, if (*ppos) return 0; /* the end */ + mutex_lock(&mdss_debug_lock); len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt); - if (len < 0 || len >= sizeof(buf)) + if (len < 0 || len >= sizeof(buf)) { + mutex_unlock(&mdss_debug_lock); return 0; + } - if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { + mutex_unlock(&mdss_debug_lock); return -EFAULT; + } *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; } @@ -217,11 +227,16 @@ static ssize_t panel_debug_base_reg_read(struct file *file, if (!dbg) return -ENODEV; - if (!dbg->cnt) + mutex_lock(&mdss_debug_lock); + if (!dbg->cnt) { + mutex_unlock(&mdss_debug_lock); return 0; + } - if (*ppos) + if (*ppos) { + mutex_unlock(&mdss_debug_lock); return 0; /* the end */ + } /* '0x' + 2 digit + blank = 5 bytes for each number */ reg_buf_len = (dbg->cnt * PANEL_REG_FORMAT_LEN) @@ -262,11 +277,13 @@ static ssize_t panel_debug_base_reg_read(struct file *file, kfree(panel_reg_buf); *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; read_reg_fail: kfree(rx_buf); kfree(panel_reg_buf); + mutex_unlock(&mdss_debug_lock); return rc; } @@ -397,8 +414,10 @@ static ssize_t mdss_debug_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; + mutex_lock(&mdss_debug_lock); dbg->off = off; dbg->cnt = cnt; + mutex_unlock(&mdss_debug_lock); pr_debug("offset=%x cnt=%x\n", off, cnt); @@ -418,15 +437,21 @@ static ssize_t mdss_debug_base_offset_read(struct file *file, if (*ppos) return 0; /* the end */ + mutex_lock(&mdss_debug_lock); len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); - if (len < 0 || len >= sizeof(buf)) + if (len < 0 || len >= sizeof(buf)) { + mutex_unlock(&mdss_debug_lock); return 0; + } - if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { + mutex_unlock(&mdss_debug_lock); return -EFAULT; + } *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; } @@ -483,6 +508,8 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, return -ENODEV; } + mutex_lock(&mdss_debug_lock); + if (!dbg->buf) { char dump_buf[64]; char *ptr; @@ -494,6 +521,7 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, if (!dbg->buf) { pr_err("not enough memory to hold reg dump\n"); + mutex_unlock(&mdss_debug_lock); return -ENOMEM; } @@ -524,17 +552,21 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, dbg->buf_len = tot; } - if (*ppos >= dbg->buf_len) + if (*ppos >= dbg->buf_len) { + mutex_unlock(&mdss_debug_lock); return 0; /* done reading */ + } len = min(count, dbg->buf_len - (size_t) *ppos); if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { pr_err("failed to copy to user\n"); + mutex_unlock(&mdss_debug_lock); return -EFAULT; } *ppos += len; /* increase offset */ + mutex_unlock(&mdss_debug_lock); return len; } From 34d4883b046549166118dd8ee555676df6ce3a75 Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 163/210] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; From d2359a65d14fabbd06d79cc6cca58c14240af695 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Fri, 17 Feb 2017 20:02:47 +0800 Subject: [PATCH 164/210] usb: dwc3: Replace sscanf with kstrtou8_from_user Variable "ubuf " and "buf" may point to kernel address, a malicious user could use code logic to get kernel information. Use kstrtou8_from_user() which take care of copying buffer, and finding u8 value here. Change-Id: Ida147ab86b0185260d31b6025179a78de78d1553 Signed-off-by: Liangliang Lu --- drivers/usb/dwc3/debugfs.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index b5317548e92f..a625bea6c728 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -1000,22 +1000,30 @@ void dbg_print_reg(const char *name, int reg) static ssize_t dwc3_store_events(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned tty; + int ret; + u8 tty; if (buf == NULL) { pr_err("[%s] EINVAL\n", __func__); - goto done; + ret = -EINVAL; + return ret; } - if (sscanf(buf, "%u", &tty) != 1 || tty > 1) { + ret = kstrtou8_from_user(buf, count, 0, &tty); + if (ret < 0) { + pr_err("can't get enter value.\n"); + return ret; + } + + if (tty > 1) { pr_err("<1|0>: enable|disable console log\n"); - goto done; + ret = -EINVAL; + return ret; } dbg_dwc3_data.tty = tty; pr_info("tty = %u", dbg_dwc3_data.tty); - done: return count; } @@ -1056,21 +1064,30 @@ const struct file_operations dwc3_gadget_dbg_data_fops = { static ssize_t dwc3_store_int_events(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { - int clear_stats, i; + int i, ret; unsigned long flags; struct seq_file *s = file->private_data; struct dwc3 *dwc = s->private; struct dwc3_ep *dep; struct timespec ts; + u8 clear_stats; if (ubuf == NULL) { pr_err("[%s] EINVAL\n", __func__); - goto done; + ret = -EINVAL; + return ret; } - if (sscanf(ubuf, "%u", &clear_stats) != 1 || clear_stats != 0) { + ret = kstrtou8_from_user(ubuf, count, 0, &clear_stats); + if (ret < 0) { + pr_err("can't get enter value.\n"); + return ret; + } + + if (clear_stats != 0) { pr_err("Wrong value. To clear stats, enter value as 0.\n"); - goto done; + ret = -EINVAL; + return ret; } spin_lock_irqsave(&dwc->lock, flags); @@ -1087,7 +1104,6 @@ static ssize_t dwc3_store_int_events(struct file *file, spin_unlock_irqrestore(&dwc->lock, flags); -done: return count; } From ccfb4b622c74f756753420e604c9e4f03d05b82e Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Mon, 20 Mar 2017 10:51:32 -0700 Subject: [PATCH 165/210] qseecom: check img_len and mdt_len against ion buf len Variable "load_img_req.img_len" and "load_img_req.mdt_len" are from user land, so check their values against ion buf length to avoid buffer overread on QSEE side. Change-Id: I9e8bfe32d3b0cd5b441ad724543c56467fa5e4da Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 339ce5d510f7..7821612a1154 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -2081,7 +2081,13 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) ret); goto loadapp_err; } - + if (load_img_req.mdt_len > len || load_img_req.img_len > len) { + pr_err("ion len %zu is smaller than mdt_len %u or img_len %u\n", + len, load_img_req.mdt_len, + load_img_req.img_len); + ret = -EINVAL; + goto loadapp_err; + } /* Populate the structure for sending scm call to load image */ if (qseecom.qsee_version < QSEE_VERSION_40) { load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND; @@ -4874,6 +4880,12 @@ static int qseecom_load_external_elf(struct qseecom_dev_handle *data, ret); return ret; } + if (load_img_req.mdt_len > len || load_img_req.img_len > len) { + pr_err("ion len %zu is smaller than mdt_len %u or img_len %u\n", + len, load_img_req.mdt_len, + load_img_req.img_len); + return ret; + } /* Populate the structure for sending scm call to load image */ if (qseecom.qsee_version < QSEE_VERSION_40) { load_req.qsee_cmd_id = QSEOS_LOAD_EXTERNAL_ELF_COMMAND; From f50da43b790b3c65699b6c7c98259c25106988b5 Mon Sep 17 00:00:00 2001 From: Xiaojun Sang Date: Fri, 24 Feb 2017 16:13:20 +0800 Subject: [PATCH 166/210] ASoC: msm: qdsp6v2: set pointer to NULL after free Pointer after kfree is not sanitized. Set pointer to NULL. CRs-Fixed: 2008031 Change-Id: Ia59a57fcd142a6ed18d168992b8da4019314afa4 Signed-off-by: Xiaojun Sang --- sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 3 ++- sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c | 3 ++- sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c | 3 ++- sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c | 4 +++- sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 5 ++++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 54c93476d4d5..544fc2fad6f5 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -1283,6 +1283,7 @@ static int msm_compr_free(struct snd_compr_stream *cstream) kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; kfree(prtd); + runtime->private_data = NULL; return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c index f1c96ef071c4..4b17e91aebfa 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -499,6 +499,7 @@ done: mutex_unlock(&prtd->lock); prtd->prepared--; kfree(prtd); + runtime->private_data = NULL; return 0; } static int msm_afe_prepare(struct snd_pcm_substream *substream) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c index ad7e1149abed..f91b75239cdc 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2017 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 @@ -497,6 +497,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) pr_debug("%s\n", __func__); kfree(prtd); + runtime->private_data = NULL; return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index 7c690812580d..2fed32f28ba1 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -517,6 +517,8 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); + runtime->private_data = NULL; + return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index f657abe84c1c..454ef4244d6b 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -724,6 +724,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_PLAYBACK); kfree(prtd); + runtime->private_data = NULL; + return 0; } @@ -827,6 +829,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); + runtime->private_data = NULL; return 0; } From 2b6962d160b55f2a222b9e2faffeb914a513e04f Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Fri, 10 Mar 2017 12:17:47 +0530 Subject: [PATCH 167/210] input: touchscreen: synaptics_dsx: Remove fw_update sysfs entries Remove the sysfs entrypoints to fw_update of synaptics_dsx touch driver. BUG: 32769717 Change-Id: I1b2ea28e6a8c5c6c583077fbc6801ebb17447a38 Git-commit: 2615c5f302441568e6dd20007bc5246d72837e80 Git-repo: https://android.googlesource.com/kernel/msm.git Signed-off-by: Andrew Chant [shjain@codeaurora.org: kconfig change already cherry-picked as part of commit 663f06e13d9e506af328e433c6904e45ef0d8410.] Signed-off-by: Shantanu Jain --- .../synaptics_dsx/synaptics_dsx_fw_update.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c index 0ec16e606545..4787f2bcd768 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c @@ -102,6 +102,7 @@ (fwu->config_data[2] == config_id[2]) && \ (fwu->config_data[3] == config_id[3])) +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count); @@ -157,6 +158,7 @@ static ssize_t fwu_sysfs_config_id_show(struct device *dev, static ssize_t fwu_sysfs_package_id_show(struct device *dev, struct device_attribute *attr, char *buf); +#endif enum bl_version { V5 = 5, @@ -296,6 +298,7 @@ struct synaptics_rmi4_fwu_handle { struct synaptics_rmi4_data *rmi4_data; }; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static struct bin_attribute dev_attr_data = { .attr = { .name = "data", @@ -305,9 +308,11 @@ static struct bin_attribute dev_attr_data = { .read = fwu_sysfs_show_image, .write = fwu_sysfs_store_image, }; +#endif static struct device_attribute attrs[] = { +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS __ATTR(force_update_fw, S_IWUSR | S_IWGRP, NULL, fwu_sysfs_force_reflash_store), @@ -353,6 +358,7 @@ static struct device_attribute attrs[] = { __ATTR(package_id, S_IRUGO, fwu_sysfs_package_id_show, synaptics_rmi4_store_error), +#endif }; static struct synaptics_rmi4_fwu_handle *fwu; @@ -1220,6 +1226,7 @@ write_config: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_config(void) { int retval; @@ -1395,6 +1402,7 @@ exit: return retval; } +#endif static int fwu_do_lockdown(void) { @@ -1585,6 +1593,7 @@ int synaptics_dsx_fw_updater(unsigned char *fw_data) } EXPORT_SYMBOL(synaptics_dsx_fw_updater); +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count) @@ -1972,6 +1981,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, (package_id[1] << 8) | package_id[0], (package_id[3] << 8) | package_id[2]); } +#endif static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, unsigned char intr_mask) @@ -2045,6 +2055,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) fwu->do_lockdown = DO_LOCKDOWN; fwu->initialized = true; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); if (retval < 0) { @@ -2053,6 +2064,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) __func__); goto exit_free_fwu; } +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, @@ -2074,7 +2086,9 @@ exit_remove_attrs: &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif exit_free_fwu: kfree(fwu); @@ -2096,7 +2110,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif kfree(fwu->read_config_buf); kfree(fwu); From efb32d0dec83bc3247fd6e650db963550d798f88 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Fri, 17 Mar 2017 16:41:13 +0530 Subject: [PATCH 168/210] soc: qcom: Skip clearing modem FW region post load failure In existing implementation, we are clearing fw region when loading fails midway. This is not in consonance with MBA design so differentiate between modem and other PIL modules. While at it, rectify the data type of subsys_state in qmi_client_info as well. Change-Id: I985456fca42346947eac24df5bf66599dcbf4c53 Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Srinivasarao P --- drivers/soc/qcom/peripheral-loader.c | 3 ++- drivers/soc/qcom/peripheral-loader.h | 4 +++- drivers/soc/qcom/pil-q6v5.c | 3 ++- drivers/soc/qcom/subsys-pil-tz.c | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 864b72061397..dae7a1ebeb69 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -774,7 +774,8 @@ out: &desc->attrs); priv->region = NULL; } - pil_clear_segment(desc); + if (desc->clear_fw_region) + pil_clear_segment(desc); pil_release_mmap(desc); } return ret; diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h index e8b7ac309287..50c42511f96e 100644 --- a/drivers/soc/qcom/peripheral-loader.h +++ b/drivers/soc/qcom/peripheral-loader.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015,2017, 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 @@ -36,6 +36,7 @@ struct pil_priv; * @unmap_fw_mem: Custom function used to undo mapping by map_fw_mem. * This defaults to iounmap if not specified. * @shutdown_fail: Set if PIL op for shutting down subsystem fails. + * @clear_fw_region: Clear fw region on failure in loading. */ struct pil_desc { const char *name; @@ -53,6 +54,7 @@ struct pil_desc { void (*unmap_fw_mem)(void *virt, size_t size, void *data); void *map_data; bool shutdown_fail; + bool clear_fw_region; }; /** diff --git a/drivers/soc/qcom/pil-q6v5.c b/drivers/soc/qcom/pil-q6v5.c index 135263141e20..3e5bb81d620d 100644 --- a/drivers/soc/qcom/pil-q6v5.c +++ b/drivers/soc/qcom/pil-q6v5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015,2017, 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 @@ -466,6 +466,7 @@ struct q6v5_data *pil_q6v5_init(struct platform_device *pdev) if (ret) return ERR_PTR(ret); + desc->clear_fw_region = false; desc->dev = &pdev->dev; drv->qdsp6v5_2_0 = of_device_is_compatible(pdev->dev.of_node, diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index ff69f980b8db..de133f702855 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015,2017, 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 @@ -917,6 +917,7 @@ static int pil_tz_driver_probe(struct platform_device *pdev) d->desc.ops = &pil_ops_trusted; d->desc.proxy_timeout = PROXY_TIMEOUT_MS; + d->desc.clear_fw_region = true; rc = of_property_read_u32(pdev->dev.of_node, "qcom,proxy-timeout-ms", &proxy_timeout); From 3590acf0d76dcff0098db3b900e3006d41bc16bf Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Mon, 20 Mar 2017 15:53:15 +0530 Subject: [PATCH 169/210] soc: qcom: Do not clear segments if pil boot failed in memory allocation PIL boot failure if happened due to memory allocation failure then skip clearing segments as there is nothing loaded in fw region. Change-Id: If0c09dd47941be0d9fe42496db43365ece32f3e9 Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Srinivasarao P --- drivers/soc/qcom/peripheral-loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index dae7a1ebeb69..c8b1b8307516 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -774,7 +774,7 @@ out: &desc->attrs); priv->region = NULL; } - if (desc->clear_fw_region) + if (desc->clear_fw_region && priv->region_start) pil_clear_segment(desc); pil_release_mmap(desc); } From c6f2a0c27a67854d92c090b1dc454c24163e844f Mon Sep 17 00:00:00 2001 From: Ram Chandrasekar Date: Thu, 23 Mar 2017 16:33:58 -0600 Subject: [PATCH 170/210] msm: thermal-dev: Protect IOCTL from race condition There is a possibility that the thermal ioctl interface can be accessed simultaneously in a multi-threaded environment. In those cases the calls to fetch the frequency and voltage table can result in an undefined behavior due to race condition. Use mutex to protect the IOCTL interface from multi-thread access race condition. Change-Id: I325695f38753a4d4bc732987cf514e8616273aca Signed-off-by: Ram Chandrasekar --- drivers/thermal/msm_thermal-dev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/msm_thermal-dev.c b/drivers/thermal/msm_thermal-dev.c index e6af6b884e99..ead9765666c8 100644 --- a/drivers/thermal/msm_thermal-dev.c +++ b/drivers/thermal/msm_thermal-dev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -35,6 +35,7 @@ static unsigned int freq_table_len[NR_CPUS], freq_table_set[NR_CPUS]; static unsigned int voltage_table_set[NR_CPUS]; static unsigned int *freq_table_ptr[NR_CPUS]; static uint32_t *voltage_table_ptr[NR_CPUS]; +static DEFINE_MUTEX(ioctl_access_mutex); static int msm_thermal_ioctl_open(struct inode *node, struct file *filep) { @@ -291,8 +292,9 @@ static long msm_thermal_ioctl_process(struct file *filep, unsigned int cmd, ret = validate_and_copy(&cmd, &arg, &query); if (ret) - goto process_exit; + return ret; + mutex_lock(&ioctl_access_mutex); switch (cmd) { case MSM_THERMAL_SET_CPU_MAX_FREQUENCY: ret = msm_thermal_set_frequency(query.cpu_freq.cpu_num, @@ -321,6 +323,7 @@ static long msm_thermal_ioctl_process(struct file *filep, unsigned int cmd, goto process_exit; } process_exit: + mutex_unlock(&ioctl_access_mutex); return ret; } From ff26a865c004549c11943c511b239c0664f8f091 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 7 Oct 2016 11:51:15 -0700 Subject: [PATCH 171/210] ion: blacklist %p kptr_restrict Bug: 31494725 Change-Id: I10a0c2aae883dfaa6c235c38689a704064557008 Git-repo: https://android.googlesource.com/kernel/msm.git Git-commit: b57e736e9991b3d0f85c0870b1eff6310a4baa64 [d-cagle@codeaurora.org: Automatic resolve of merge conflicts] Signed-off-by: Dennis Cagle --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 4703d8fecce9..07cb042f1e0b 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -818,7 +818,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) struct ion_handle *handle = rb_entry(n, struct ion_handle, node); - seq_printf(s, "%16.16s: %16zx : %16d : %12p", + seq_printf(s, "%16.16s: %16zx : %16d : %12pK", handle->buffer->heap->name, handle->buffer->size, atomic_read(&handle->ref.refcount), From 95e72ae9281b77abc3ed0cc6a33c17b989241efa Mon Sep 17 00:00:00 2001 From: kunleiz Date: Sun, 26 Mar 2017 20:07:43 +0800 Subject: [PATCH 172/210] ASoC: msm: qdspv2: add mutex to prevent access same memory simultaneously Add mutex protection to avoid simultaneous access the same memory by multiple threads. CRs-Fixed: 2013494 Change-Id: I440ea633ceb7312637c9a3b29d22236166d21a39 Signed-off-by: kunleiz --- .../misc/qcom/qdsp6v2/audio_hwacc_effects.c | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index 089a82788643..e7c28a663b6e 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -148,6 +148,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, case AUDIO_START: { pr_debug("%s: AUDIO_START\n", __func__); + mutex_lock(&effects->lock); + rc = q6asm_open_read_write_v2(effects->ac, FORMAT_LINEAR_PCM, FORMAT_MULTI_CHANNEL_LINEAR_PCM, @@ -159,6 +161,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Open failed for hw accelerated effects:rc=%d\n", __func__, rc); rc = -EINVAL; + mutex_unlock(&effects->lock); goto ioctl_fail; } effects->opened = 1; @@ -175,6 +178,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Write buffer Allocation failed rc = %d\n", __func__, rc); rc = -ENOMEM; + mutex_unlock(&effects->lock); goto ioctl_fail; } atomic_set(&effects->in_count, effects->config.input.num_buf); @@ -185,6 +189,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Read buffer Allocation failed rc = %d\n", __func__, rc); rc = -ENOMEM; + mutex_unlock(&effects->lock); goto readbuf_fail; } atomic_set(&effects->out_count, effects->config.output.num_buf); @@ -199,6 +204,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (rc < 0) { pr_err("%s: pcm read block config failed\n", __func__); rc = -EINVAL; + mutex_unlock(&effects->lock); goto cfg_fail; } pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n", @@ -213,6 +219,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: pcm write format block config failed\n", __func__); rc = -EINVAL; + mutex_unlock(&effects->lock); goto cfg_fail; } @@ -225,6 +232,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, effects->started = 0; pr_err("%s: ASM run state failed\n", __func__); } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_WRITE: { @@ -286,8 +294,11 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, uint32_t idx = 0; uint32_t size = 0; + mutex_lock(&effects->lock); + if (!effects->started) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -304,11 +315,13 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (!rc) { pr_err("%s: read wait_event_timeout\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } if (!atomic_read(&effects->in_count)) { pr_err("%s: pcm stopped in_count 0\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -316,15 +329,18 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (bufptr) { if (!((void *)arg)) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } if ((effects->config.buf_cfg.input_len > size) || copy_to_user((void *)arg, bufptr, effects->config.buf_cfg.input_len)) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } } + mutex_unlock(&effects->lock); break; } default: @@ -456,6 +472,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case AUDIO_SET_EFFECTS_CONFIG: { pr_debug("%s: AUDIO_SET_EFFECTS_CONFIG\n", __func__); + mutex_lock(&effects->lock); memset(&effects->config, 0, sizeof(effects->config)); if (copy_from_user(&effects->config, (void *)arg, sizeof(effects->config))) { @@ -473,6 +490,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, effects->config.input.num_buf, effects->config.input.sample_rate, effects->config.input.num_channels); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_BUF_LEN: { @@ -494,6 +512,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, buf_avail.input_num_avail = atomic_read(&effects->in_count); buf_avail.output_num_avail = atomic_read(&effects->out_count); + mutex_lock(&effects->lock); pr_debug("%s: write buf avail: %d, read buf avail: %d\n", __func__, buf_avail.output_num_avail, buf_avail.input_num_avail); @@ -503,16 +522,20 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, __func__); rc = -EFAULT; } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_PP_PARAMS: { + mutex_lock(&effects->lock); if (copy_from_user(argvalues, (void *)arg, MAX_PP_PARAMS_SZ*sizeof(long))) { pr_err("%s: copy from user for pp params failed\n", __func__); + mutex_unlock(&effects->lock); return -EFAULT; } rc = audio_effects_set_pp_param(effects, argvalues); + mutex_unlock(&effects->lock); break; } default: @@ -578,12 +601,14 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, case AUDIO_SET_EFFECTS_CONFIG32: { struct msm_hwacc_effects_config32 config32; struct msm_hwacc_effects_config *config = &effects->config; + mutex_lock(&effects->lock); memset(&effects->config, 0, sizeof(effects->config)); if (copy_from_user(&config32, (void *)arg, sizeof(config32))) { pr_err("%s: copy to user for AUDIO_SET_EFFECTS_CONFIG failed\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); break; } config->input.buf_size = config32.input.buf_size; @@ -620,16 +645,19 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, effects->config.input.num_buf, effects->config.input.sample_rate, effects->config.input.num_channels); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_BUF_LEN32: { struct msm_hwacc_buf_cfg32 buf_cfg32; struct msm_hwacc_effects_config *config = &effects->config; + mutex_lock(&effects->lock); if (copy_from_user(&buf_cfg32, (void *)arg, sizeof(buf_cfg32))) { pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); break; } config->buf_cfg.input_len = buf_cfg32.input_len; @@ -637,6 +665,7 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, pr_debug("%s: write buf len: %d, read buf len: %d\n", __func__, effects->config.buf_cfg.output_len, effects->config.buf_cfg.input_len); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_GET_BUF_AVAIL32: { @@ -644,6 +673,7 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, memset(&buf_avail, 0, sizeof(buf_avail)); + mutex_lock(&effects->lock); buf_avail.input_num_avail = atomic_read(&effects->in_count); buf_avail.output_num_avail = atomic_read(&effects->out_count); pr_debug("%s: write buf avail: %d, read buf avail: %d\n", @@ -655,22 +685,26 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, __func__); rc = -EFAULT; } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_PP_PARAMS32: { long argvalues[MAX_PP_PARAMS_SZ] = {0}; int argvalues32[MAX_PP_PARAMS_SZ] = {0}; + mutex_lock(&effects->lock); if (copy_from_user(argvalues32, (void *)arg, MAX_PP_PARAMS_SZ*sizeof(int))) { pr_err("%s: copy from user failed for pp params\n", __func__); + mutex_unlock(&effects->lock); return -EFAULT; } for (i = 0; i < MAX_PP_PARAMS_SZ; i++) argvalues[i] = argvalues32[i]; rc = audio_effects_set_pp_param(effects, argvalues); + mutex_unlock(&effects->lock); break; } case AUDIO_START32: { From e8e651a6abd1c768636da3d7399a1bab8bcdc0d6 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Sat, 25 Mar 2017 17:36:30 +0530 Subject: [PATCH 173/210] soc: qcom: pil: Explicitly clear the subsystem loading address Explicitly clear the subsystem loading address in case of any memory failure. It will help to avoid any platform dependency. Change-Id: I3be8f6318d68f02c02e637fc34f4a868e9fafa45 Signed-off-by: Gaurav Kohli Signed-off-by: Srinivasarao P --- drivers/soc/qcom/peripheral-loader.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index c8b1b8307516..12d329e37bd9 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -382,6 +382,8 @@ static int pil_alloc_region(struct pil_priv *priv, phys_addr_t min_addr, if (region == NULL) { pil_err(priv->desc, "Failed to allocate relocatable region of size %zx\n", size); + priv->region_start = 0; + priv->region_end = 0; return -ENOMEM; } From e2c680c3068ee5f259878eda2cace69b501b508e Mon Sep 17 00:00:00 2001 From: Abdulla Anam Date: Wed, 22 Mar 2017 14:00:10 +0530 Subject: [PATCH 174/210] msm: vidc: Protect debug_buffer access in core_info_read with lock. Serialize core_info_read with lock so that multiple concurrent threads do not cause the write to overflow. Also have the bound check to avoid overflow in write_str function. CRs-Fixed: 2013361 Change-Id: Ia18a4b94cafd69af1d367861f2499fc202f18e9f Signed-off-by: Abdulla Anam Signed-off-by: Sanjay Singh --- .../media/platform/msm/vidc/msm_v4l2_vidc.c | 5 ++- .../media/platform/msm/vidc/msm_vidc_debug.c | 37 ++++++++++++++++--- .../media/platform/msm/vidc/msm_vidc_debug.h | 3 +- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index c43c64c04e6d..d4aa7bc48b0d 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -792,6 +792,8 @@ static int __init msm_vidc_init(void) if (rc) { dprintk(VIDC_ERR, "Failed to register platform driver\n"); + msm_vidc_debugfs_deinit_drv(); + debugfs_remove_recursive(vidc_driver->debugfs_root); kfree(vidc_driver); vidc_driver = NULL; } @@ -802,6 +804,7 @@ static int __init msm_vidc_init(void) static void __exit msm_vidc_exit(void) { platform_driver_unregister(&msm_vidc_driver); + msm_vidc_debugfs_deinit_drv(); debugfs_remove_recursive(vidc_driver->debugfs_root); kfree(vidc_driver); vidc_driver = NULL; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c index 65eed16a5919..f666fbfdb4b2 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -32,6 +32,7 @@ u32 msm_vidc_firmware_unload_delay = 15000; int msm_vidc_thermal_mitigation_disabled = 0x0; struct debug_buffer { + struct mutex lock; char ptr[MAX_DBG_BUF_SIZE]; char *curr; u32 filled_size; @@ -58,8 +59,12 @@ static u32 write_str(struct debug_buffer *buffer, const char *fmt, ...) { va_list args; u32 size; + + char *curr = buffer->curr; + char *end = buffer->ptr + MAX_DBG_BUF_SIZE; + va_start(args, fmt); - size = vscnprintf(buffer->curr, MAX_DBG_BUF_SIZE - 1, fmt, args); + size = vscnprintf(curr, end - curr, fmt, args); va_end(args); buffer->curr += size; buffer->filled_size += size; @@ -73,12 +78,15 @@ static ssize_t core_info_read(struct file *file, char __user *buf, struct hfi_device *hdev; struct hal_fw_info fw_info; int i = 0, rc = 0; + ssize_t len = 0; if (!core || !core->device) { dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); return 0; } hdev = core->device; + + mutex_lock(&dbg_buf.lock); INIT_DBG_BUF(dbg_buf); write_str(&dbg_buf, "===============================\n"); write_str(&dbg_buf, "CORE %d: 0x%pK\n", core->id, core); @@ -102,8 +110,11 @@ err_fw_info: completion_done(&core->completions[SYS_MSG_INDEX(i)]) ? "pending" : "done"); } - return simple_read_from_buffer(buf, count, ppos, + len = simple_read_from_buffer(buf, count, ppos, dbg_buf.ptr, dbg_buf.filled_size); + + mutex_unlock(&dbg_buf.lock); + return len; } static const struct file_operations core_info_fops = { @@ -140,7 +151,10 @@ static const struct file_operations ssr_fops = { struct dentry *msm_vidc_debugfs_init_drv(void) { - struct dentry *dir = debugfs_create_dir("msm_vidc", NULL); + struct dentry *dir = NULL; + + mutex_init(&dbg_buf.lock); + dir = debugfs_create_dir("msm_vidc", NULL); if (IS_ERR_OR_NULL(dir)) { dir = NULL; goto failed_create_dir; @@ -246,6 +260,7 @@ struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core, dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n"); goto failed_create_dir; } + if (!debugfs_create_file("info", S_IRUGO, dir, core, &core_info_fops)) { dprintk(VIDC_ERR, "debugfs_create_file: fail\n"); goto failed_create_dir; @@ -299,10 +314,14 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, { struct msm_vidc_inst *inst = file->private_data; int i, j; + ssize_t len = 0; + if (!inst) { dprintk(VIDC_ERR, "Invalid params, core: %pK\n", inst); return 0; } + + mutex_lock(&dbg_buf.lock); INIT_DBG_BUF(dbg_buf); write_str(&dbg_buf, "===============================\n"); write_str(&dbg_buf, "INSTANCE: 0x%pK (%s)\n", inst, @@ -359,9 +378,10 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, write_str(&dbg_buf, "FBD Count: %d\n", inst->count.fbd); publish_unreleased_reference(inst); - - return simple_read_from_buffer(buf, count, ppos, + len = simple_read_from_buffer(buf, count, ppos, dbg_buf.ptr, dbg_buf.filled_size); + mutex_unlock(&dbg_buf.lock); + return len; } static const struct file_operations inst_info_fops = { @@ -442,3 +462,8 @@ void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, } } +void msm_vidc_debugfs_deinit_drv(void) +{ + mutex_destroy(&dbg_buf.lock); +} + diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h index d4df108cf0c7..2743f64fcd7f 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2017 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 @@ -125,6 +125,7 @@ struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, struct dentry *parent); void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, enum msm_vidc_debugfs_event e); +void msm_vidc_debugfs_deinit_drv(void); static inline void tic(struct msm_vidc_inst *i, enum profiling_points p, char *b) From 145f222b043911bc2914764627c32bc25124f59b Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Thu, 28 Apr 2016 18:36:38 -0700 Subject: [PATCH 175/210] msm: mdss: match pixclock calculation for videomode and fb var When multiple panel timings are available and enumerating videomode list, pixclock is calculated using htotal, vtotal and refresh rate. But fb var struct is populated with actual pixclock value calculated by DSI. This pixclock mismatch would cause issues, when usermode does GET_VSCREENINFO/PUT_VSCREENINFO. Fix by using the same pixclock calculation for both structures. Change-Id: I42bfc40b5904ec80f20b296e3b4610ca3b2c5ee0 [veeras@codeaurora.org: Resolved conflicts in mdss_fb.c] Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Sandeep Panda Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdss_fb.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 5478edfde6ad..f52237632975 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -3009,6 +3009,7 @@ static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var, static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, struct fb_var_screeninfo *var) { + u32 frame_rate; struct mdss_panel_data *pdata = container_of(pinfo, struct mdss_panel_data, panel_info); @@ -3020,7 +3021,21 @@ static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, var->right_margin = pinfo->lcdc.h_front_porch; var->left_margin = pinfo->lcdc.h_back_porch; var->hsync_len = pinfo->lcdc.h_pulse_width; - var->pixclock = pinfo->clk_rate; + + frame_rate = mdss_panel_get_framerate(pinfo); + if (frame_rate) { + unsigned long clk_rate, h_total, v_total; + + h_total = var->xres + var->left_margin + + var->right_margin + var->hsync_len; + v_total = var->yres + var->lower_margin + + var->upper_margin + var->vsync_len; + clk_rate = h_total * v_total * frame_rate; + var->pixclock = KHZ2PICOS(clk_rate / 1000); + } else if (pinfo->clk_rate) { + var->pixclock = KHZ2PICOS( + (unsigned long int) pinfo->clk_rate / 1000); + } } /** From d8475b0415515748b61ddad1a549109624dd7db1 Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Mon, 27 Mar 2017 15:00:17 +0530 Subject: [PATCH 176/210] soc: qcom: socinfo: Protect current_image using semaphore lock. Variable current_image can be modified by multiple threads. This change will protect current_image getting modified by multiple threads. Change-Id: I33df463311b24f73b1ba124d388731a72bd13263 CRs-Fixed: 2016485 Signed-off-by: Swetha Chikkaboraiah --- drivers/soc/qcom/socinfo.c | 40 +++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 838c6dd895fb..82d6da524773 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2015, 2017, 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 @@ -44,6 +44,7 @@ #define SMEM_IMAGE_VERSION_OEM_OFFSET 96 #define SMEM_IMAGE_VERSION_PARTITION_APPS 10 +static DECLARE_RWSEM(current_image_rwsem); enum { HW_PLATFORM_UNKNOWN = 0, HW_PLATFORM_SURF = 1, @@ -811,7 +812,9 @@ msm_get_image_version(struct device *dev, __func__); return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown"); } + down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s\n", string_address); } @@ -824,15 +827,20 @@ msm_set_image_version(struct device *dev, { char *store_address; - if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + down_read(¤t_image_rwsem); + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(¤t_image_rwsem); return count; + } store_address = socinfo_get_image_version_base_address(); if (IS_ERR_OR_NULL(store_address)) { pr_err("%s : Failed to get image version base address", __func__); + up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf); return count; } @@ -851,7 +859,9 @@ msm_get_image_variant(struct device *dev, return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "Unknown"); } + down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n", string_address); @@ -865,15 +875,20 @@ msm_set_image_variant(struct device *dev, { char *store_address; - if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + down_read(¤t_image_rwsem); + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(¤t_image_rwsem); return count; + } store_address = socinfo_get_image_version_base_address(); if (IS_ERR_OR_NULL(store_address)) { pr_err("%s : Failed to get image version base address", __func__); + up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf); return count; @@ -892,7 +907,9 @@ msm_get_image_crm_version(struct device *dev, __func__); return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown"); } + down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); string_address += SMEM_IMAGE_VERSION_OEM_OFFSET; return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n", string_address); @@ -906,15 +923,20 @@ msm_set_image_crm_version(struct device *dev, { char *store_address; - if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + down_read(¤t_image_rwsem); + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(¤t_image_rwsem); return count; + } store_address = socinfo_get_image_version_base_address(); if (IS_ERR_OR_NULL(store_address)) { pr_err("%s : Failed to get image version base address", __func__); + up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); store_address += SMEM_IMAGE_VERSION_OEM_OFFSET; snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf); return count; @@ -925,8 +947,14 @@ msm_get_image_number(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", + int ret; + + down_read(¤t_image_rwsem); + ret = snprintf(buf, PAGE_SIZE, "%d\n", current_image); + up_read(¤t_image_rwsem); + return ret; + } static ssize_t @@ -938,10 +966,12 @@ msm_select_image(struct device *dev, struct device_attribute *attr, ret = kstrtoint(buf, 10, &digit); if (ret) return ret; + down_write(¤t_image_rwsem); if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT) current_image = digit; else current_image = 0; + up_write(¤t_image_rwsem); return count; } From 51644dbd2394c3c80b61a7c79f12d8293e11813d Mon Sep 17 00:00:00 2001 From: Dilip Kota Date: Mon, 21 Mar 2016 11:28:51 +0530 Subject: [PATCH 177/210] slim-msm: Synchronize SSR callbacks Subsystem will restart within short timeframe. Synchronise subsytem up/down callback notifications to avoid functionality failures. Use mutex locks to achieve synchronization. Change-Id: I5881c7d468507bb8402a2e9f8178b9c31e57e8a5 Signed-off-by: Dilip Kota --- drivers/slimbus/slim-msm-ngd.c | 5 +++++ drivers/slimbus/slim-msm.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index 5c2c9a6e4ee4..8c3a184b6649 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -1446,11 +1446,13 @@ static void ngd_adsp_down(struct msm_slim_ctrl *dev) struct slim_controller *ctrl = &dev->ctrl; struct slim_device *sbdev; + mutex_lock(&dev->ssr_lock); ngd_slim_enable(dev, false); /* device up should be called again after SSR */ list_for_each_entry(sbdev, &ctrl->devs, dev_list) slim_report_absent(sbdev); SLIM_INFO(dev, "SLIM ADSP SSR (DOWN) done\n"); + mutex_unlock(&dev->ssr_lock); } static void ngd_adsp_up(struct work_struct *work) @@ -1459,7 +1461,9 @@ static void ngd_adsp_up(struct work_struct *work) container_of(work, struct msm_slim_qmi, ssr_up); struct msm_slim_ctrl *dev = container_of(qmi, struct msm_slim_ctrl, qmi); + mutex_lock(&dev->ssr_lock); ngd_slim_enable(dev, true); + mutex_unlock(&dev->ssr_lock); } static ssize_t show_mask(struct device *device, struct device_attribute *attr, @@ -1623,6 +1627,7 @@ static int ngd_slim_probe(struct platform_device *pdev) init_completion(&dev->reconf); init_completion(&dev->ctrl_up); mutex_init(&dev->tx_lock); + mutex_init(&dev->ssr_lock); spin_lock_init(&dev->tx_buf_lock); spin_lock_init(&dev->rx_lock); dev->ee = 1; diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h index dbb125dc9a62..0b4c4d33f79a 100644 --- a/drivers/slimbus/slim-msm.h +++ b/drivers/slimbus/slim-msm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -284,6 +284,7 @@ struct msm_slim_ctrl { struct clk *rclk; struct clk *hclk; struct mutex tx_lock; + struct mutex ssr_lock; spinlock_t tx_buf_lock; u8 pgdla; enum msm_slim_msgq use_rx_msgqs; From 367fab472d0fcdd7027a282752c431f6e8bb0ace Mon Sep 17 00:00:00 2001 From: Alexy Joseph Date: Fri, 3 Mar 2017 18:50:21 -0800 Subject: [PATCH 178/210] ASoC: qdsp6v2: Remove Eagle code Eagle driver is not in use any more. Remove the code and associated calls to it. CRs-Fixed: 1103106 Change-Id: Ice5333861beda9538f0783b70b3267523d16fd2b Signed-off-by: Alexy Joseph --- .../misc/qcom/qdsp6v2/audio_hwacc_effects.c | 65 +- include/sound/msm-dts-eagle.h | 148 -- include/sound/q6adm-v2.h | 3 +- sound/soc/msm/qdsp6v2/Makefile | 1 - sound/soc/msm/qdsp6v2/audio_cal_utils.c | 4 - .../soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c | 31 +- sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 76 - sound/soc/msm/qdsp6v2/msm-dts-eagle.c | 1655 ----------------- sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c | 4 +- .../soc/msm/qdsp6v2/msm-pcm-routing-devdep.c | 41 +- sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 11 - sound/soc/msm/qdsp6v2/q6adm.c | 260 +-- sound/soc/msm/qdsp6v2/q6asm.c | 229 +-- sound/soc/msm/qdsp6v2/q6core.c | 113 +- 14 files changed, 21 insertions(+), 2620 deletions(-) delete mode 100644 include/sound/msm-dts-eagle.h delete mode 100644 sound/soc/msm/qdsp6v2/msm-dts-eagle.c diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index 089a82788643..2b5a78de4b02 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -17,7 +17,6 @@ #include "q6audio_common.h" #include "audio_utils_aio.h" #include -#include #define MAX_CHANNELS_SUPPORTED 8 #define WAIT_TIMEDOUT_DURATION_SECS 1 @@ -53,31 +52,11 @@ static void audio_effects_init_pp(struct audio_client *ac) pr_err("%s: audio client null to init pp\n", __func__); return; } - switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume1 Param failed ret=%d\n", - __func__, ret); - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_2); - if (ret < 0) - pr_err("%s: Send SoftVolume2 Param failed ret=%d\n", - __func__, ret); - - msm_dts_eagle_init_master_module(ac); - - break; - default: - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume Param failed ret=%d\n", - __func__, ret); - break; - } + ret = q6asm_set_softvolume_v2(ac, &softvol, + SOFT_VOLUME_INSTANCE_1); + if (ret < 0) + pr_err("%s: Send SoftVolume Param failed ret=%d\n", + __func__, ret); } static void audio_effects_deinit_pp(struct audio_client *ac) @@ -86,13 +65,6 @@ static void audio_effects_deinit_pp(struct audio_client *ac) pr_err("%s: audio client null to deinit pp\n", __func__); return; } - switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - msm_dts_eagle_deinit_master_module(ac); - break; - default: - break; - } } static void audio_effects_event_handler(uint32_t opcode, uint32_t token, @@ -412,33 +384,6 @@ static long audio_effects_set_pp_param(struct q6audio_effects *effects, &(effects->audio_effects.topo_switch_vol), (long *)&values[1], SOFT_VOLUME_INSTANCE_2); break; - case DTS_EAGLE_MODULE_ENABLE: - pr_debug("%s: DTS_EAGLE_MODULE_ENABLE\n", __func__); - if (msm_audio_effects_is_effmodule_supp_in_top( - effects_module, effects->ac->topology)) { - /* - * HPX->OFF: first disable HPX and then - * enable SA+ - * HPX->ON: first disable SA+ and then - * enable HPX - */ - bool hpx_state = (bool)values[1]; - if (hpx_state) - msm_audio_effects_enable_extn(effects->ac, - &(effects->audio_effects), - false); - msm_dts_eagle_enable_asm(effects->ac, - hpx_state, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - msm_dts_eagle_enable_asm(effects->ac, - hpx_state, - AUDPROC_MODULE_ID_DTS_HPX_POSTMIX); - if (!hpx_state) - msm_audio_effects_enable_extn(effects->ac, - &(effects->audio_effects), - true); - } - break; default: pr_err("%s: Invalid effects config module\n", __func__); rc = -EINVAL; diff --git a/include/sound/msm-dts-eagle.h b/include/sound/msm-dts-eagle.h deleted file mode 100644 index 2ef01136b7ce..000000000000 --- a/include/sound/msm-dts-eagle.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (c) 2014, 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. - */ - -#ifndef __MSM_DTS_EAGLE_H__ -#define __MSM_DTS_EAGLE_H__ - -#include -#include -#include -#include - -#ifdef CONFIG_COMPAT -enum { - DTS_EAGLE_IOCTL_GET_CACHE_SIZE32 = _IOR(0xF2, 0, __s32), - DTS_EAGLE_IOCTL_SET_CACHE_SIZE32 = _IOW(0xF2, 1, __s32), - DTS_EAGLE_IOCTL_GET_PARAM32 = _IOR(0xF2, 2, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_PARAM32 = _IOW(0xF2, 3, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32 = - _IOW(0xF2, 4, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32 = - _IOW(0xF2, 5, compat_uptr_t), - DTS_EAGLE_IOCTL_GET_LICENSE32 = - _IOR(0xF2, 6, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_LICENSE32 = - _IOW(0xF2, 7, compat_uptr_t), - DTS_EAGLE_IOCTL_SEND_LICENSE32 = _IOW(0xF2, 8, __s32), - DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32 = _IOW(0xF2, 9, - compat_uptr_t), -}; -#endif - -#ifdef CONFIG_DTS_EAGLE -void msm_dts_ion_memmap(struct param_outband *po_); -int msm_dts_eagle_enable_asm(struct audio_client *ac, u32 enable, int module); -int msm_dts_eagle_enable_adm(int port_id, int copp_idx, u32 enable); -void msm_dts_eagle_add_controls(struct snd_soc_platform *platform); -int msm_dts_eagle_set_stream_gain(struct audio_client *ac, - int lgain, int rgain); -int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get, struct audio_client *ac, - struct param_outband *po); -int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get); -int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg); -int msm_dts_eagle_is_hpx_on(void); -int msm_dts_eagle_init_pre(struct audio_client *ac); -int msm_dts_eagle_deinit_pre(struct audio_client *ac); -int msm_dts_eagle_init_post(int port_id, int copp_id); -int msm_dts_eagle_deinit_post(int port_id, int topology); -int msm_dts_eagle_init_master_module(struct audio_client *ac); -int msm_dts_eagle_deinit_master_module(struct audio_client *ac); -int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime); -void msm_dts_eagle_pcm_free(struct snd_pcm *pcm); -int msm_dts_eagle_compat_ioctl(unsigned int cmd, unsigned long arg); -#else -static inline void msm_dts_ion_memmap(struct param_outband *po_) -{ - pr_debug("%s\n", __func__); -} -static inline int msm_dts_eagle_enable_asm(struct audio_client *ac, - u32 enable, int module) -{ - return 0; -} -static inline int msm_dts_eagle_enable_adm(int port_id, int copp_idx, - u32 enable) -{ - return 0; -} -static inline void msm_dts_eagle_add_controls(struct snd_soc_platform *platform) -{ -} -static inline int msm_dts_eagle_set_stream_gain(struct audio_client *ac, - int lgain, int rgain) -{ - pr_debug("%s\n", __func__); - return 0; -} -static inline int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, - char *buf, bool for_pre, bool get, - struct audio_client *ac, - struct param_outband *po) -{ - return 0; -} -static inline int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, - char *buf, bool for_pre, bool get) -{ - return 0; -} -static inline int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) -{ - return -EPERM; -} -static inline int msm_dts_eagle_is_hpx_on(void) -{ - return 0; -} -static inline int msm_dts_eagle_init_pre(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_pre(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_init_post(int port_id, int coppid) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_post(int port_id, int topology) -{ - return 0; -} -static inline int msm_dts_eagle_init_master_module(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_master_module(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime) -{ - pr_debug("%s\n", __func__); - return 0; -} -static inline void msm_dts_eagle_pcm_free(struct snd_pcm *pcm) -{ - pr_debug("%s\n", __func__); -} -static inline int msm_dts_eagle_compat_ioctl(unsigned int cmd, - unsigned long arg) -{ - return 0; -} -#endif - -#endif diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index d3a4da8e4563..19b6309e2c1e 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -34,7 +34,6 @@ enum { ADM_AUDVOL_CAL, ADM_RTAC_INFO_CAL, ADM_RTAC_APR_CAL, - ADM_DTS_EAGLE, ADM_SRS_TRUMEDIA, ADM_MAX_CAL_TYPES }; diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile index 53e520216843..facf765bc31b 100644 --- a/sound/soc/msm/qdsp6v2/Makefile +++ b/sound/soc/msm/qdsp6v2/Makefile @@ -9,7 +9,6 @@ snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \ obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \ msm-dai-stub-v2.o obj-$(CONFIG_SND_HWDEP) += msm-pcm-routing-devdep.o -obj-$(CONFIG_DTS_EAGLE) += msm-dts-eagle.o obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o obj-$(CONFIG_DOLBY_DS2) += msm-ds2-dap-config.o obj-$(CONFIG_DTS_SRS_TM) += msm-dts-srs-tm-config.o diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c index 0827a4d7d0cc..67ca2bcd0a6b 100644 --- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c +++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c @@ -136,8 +136,6 @@ size_t get_cal_info_size(int32_t cal_type) case ULP_LSM_CAL_TYPE: size = sizeof(struct audio_cal_info_lsm); break; - case DTS_EAGLE_CAL_TYPE: - size = 0; case AUDIO_CORE_METAINFO_CAL_TYPE: size = sizeof(struct audio_cal_info_metainfo); break; @@ -263,8 +261,6 @@ size_t get_user_cal_type_size(int32_t cal_type) case ULP_LSM_CAL_TYPE: size = sizeof(struct audio_cal_type_lsm); break; - case DTS_EAGLE_CAL_TYPE: - size = 0; case AUDIO_CORE_METAINFO_CAL_TYPE: size = sizeof(struct audio_cal_type_metainfo); break; diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c index 1c08842c7840..e312a879b86a 100644 --- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -15,7 +15,6 @@ #include #include #include -#include #include #define MAX_ENABLE_CMD_SIZE 32 @@ -49,26 +48,6 @@ bool msm_audio_effects_is_effmodule_supp_in_top(int effect_module, case EQ_MODULE: switch (topology) { case ASM_STREAM_POSTPROC_TOPO_ID_SA_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - return true; - default: - return false; - } - case DTS_EAGLE_MODULE: - switch (topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - return true; - default: - return false; - } - case SOFT_VOLUME2_MODULE: - case DTS_EAGLE_MODULE_ENABLE: - switch (topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: return true; default: return false; @@ -276,7 +255,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -747,7 +726,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -883,7 +862,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -1223,7 +1202,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 544fc2fad6f5..132795703165 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -43,8 +43,6 @@ #include #include #include -#include - #include "msm-pcm-routing-v2.h" #include "audio_ocmem.h" @@ -83,15 +81,6 @@ const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0, #define MAX_NUMBER_OF_STREAMS 2 -/* - * Max size for getting DTS EAGLE Param through kcontrol - * Safe for both 32 and 64 bit platforms - * 64 = size of kcontrol value array on 64 bit platform - * 4 = size of parameters Eagle expects before cast to 64 bits - * 40 = size of dts_eagle_param_desc + module_id cast to 64 bits - */ -#define DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA ((64 * 4) - 40) - struct msm_compr_gapless_state { bool set_next_stream_id; int32_t stream_opened[MAX_NUMBER_OF_STREAMS]; @@ -310,11 +299,6 @@ static int msm_compr_set_volume(struct snd_compr_stream *cstream, if (rc < 0) pr_err("%s: Send vol gain command failed rc=%d\n", __func__, rc); - else - if (msm_dts_eagle_set_stream_gain(prtd->audio_client, - volume_l, volume_r)) - pr_debug("%s: DTS_EAGLE send stream gain failed\n", - __func__); return rc; } @@ -925,26 +909,6 @@ static int msm_compr_init_pp_params(struct snd_compr_stream *cstream, }; switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: /* HPX + SA+ topology */ - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume Param failed ret=%d\n", - __func__, ret); - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_2); - if (ret < 0) - pr_err("%s: Send SoftVolume2 Param failed ret=%d\n", - __func__, ret); - /* - * HPX module init is trigerred from HAL using ioctl - * DTS_EAGLE_MODULE_ENABLE when stream starts - */ - break; - case ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX: /* HPX topology */ - break; default: ret = q6asm_set_softvolume_v2(ac, &softvol, SOFT_VOLUME_INSTANCE_1); @@ -2443,23 +2407,6 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol, &(audio_effects->equalizer), values); break; - case DTS_EAGLE_MODULE: - pr_debug("%s: DTS_EAGLE_MODULE\n", __func__); - if (!msm_audio_effects_is_effmodule_supp_in_top(effects_module, - prtd->audio_client->topology)) - return 0; - msm_dts_eagle_handle_asm(NULL, (void *)values, true, - false, prtd->audio_client, NULL); - break; - case DTS_EAGLE_MODULE_ENABLE: - pr_debug("%s: DTS_EAGLE_MODULE_ENABLE\n", __func__); - if (msm_audio_effects_is_effmodule_supp_in_top(effects_module, - prtd->audio_client->topology)) - msm_dts_eagle_enable_asm(prtd->audio_client, - (bool)values[0], - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - - break; case SOFT_VOLUME_MODULE: pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__); break; @@ -2488,7 +2435,6 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol, struct msm_compr_audio_effects *audio_effects = NULL; struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd = NULL; - long *values = &(ucontrol->value.integer.value[0]); pr_debug("%s\n", __func__); if (fe_id >= MSM_FRONTEND_DAI_MAX) { @@ -2508,28 +2454,6 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol, return -EINVAL; } - switch (audio_effects->query.mod_id) { - case DTS_EAGLE_MODULE: - pr_debug("%s: DTS_EAGLE_MODULE handling queued get\n", - __func__); - values[0] = (long)audio_effects->query.mod_id; - values[1] = (long)audio_effects->query.parm_id; - values[2] = (long)audio_effects->query.size; - values[3] = (long)audio_effects->query.offset; - values[4] = (long)audio_effects->query.device; - if (values[2] > DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA) { - pr_err("%s: DTS_EAGLE_MODULE parameter's requested size (%li) too large (max size is %i)\n", - __func__, values[2], - DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA); - return -EINVAL; - } - msm_dts_eagle_handle_asm(NULL, (void *)&values[1], - true, true, prtd->audio_client, NULL); - break; - default: - pr_err("%s: Invalid effects config module\n", __func__); - return -EINVAL; - } return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c deleted file mode 100644 index 3e76acf9ea09..000000000000 --- a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +++ /dev/null @@ -1,1655 +0,0 @@ -/* Copyright (c) 2014-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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "msm-pcm-routing-v2.h" - -#define ION_MEM_SIZE 131072 -#define DEPC_MAX_SIZE 524288 - -#define MPST AUDPROC_MODULE_ID_DTS_HPX_POSTMIX -#define MPRE AUDPROC_MODULE_ID_DTS_HPX_PREMIX - -#define eagle_vol_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_VOLUME: " fmt "\n", ##__VA_ARGS__) -#define eagle_vol_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_VOLUME: " fmt "\n", ##__VA_ARGS__) -#define eagle_drv_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER: " fmt "\n", ##__VA_ARGS__) -#define eagle_drv_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER: " fmt "\n", ##__VA_ARGS__) -#define eagle_precache_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_SENDCACHE_PRE: " fmt "\n", ##__VA_ARGS__) -#define eagle_precache_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_SENDCACHE_PRE: " fmt "\n", ##__VA_ARGS__) -#define eagle_postcache_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_SENDCACHE_POST: " fmt "\n", ##__VA_ARGS__) -#define eagle_postcache_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_SENDCACHE_POST: " fmt "\n", ##__VA_ARGS__) -#define eagle_ioctl_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_IOCTL: " fmt "\n", ##__VA_ARGS__) -#define eagle_ioctl_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_IOCTL: " fmt "\n", ##__VA_ARGS__) -#define eagle_asm_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_ASM: " fmt "\n", ##__VA_ARGS__) -#define eagle_asm_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_ASM: " fmt "\n", ##__VA_ARGS__) -#define eagle_adm_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_ADM: " fmt "\n", ##__VA_ARGS__) -#define eagle_adm_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_ADM: " fmt "\n", ##__VA_ARGS__) -#define eagle_enable_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_ENABLE: " fmt "\n", ##__VA_ARGS__) -#define eagle_enable_err(fmt, ...) \ - pr_err("DTS_EAGLE_ENABLE: " fmt "\n", ##__VA_ARGS__) -#define eagle_ioctl_info(fmt, ...) \ - pr_err("DTS_EAGLE_IOCTL: " fmt "\n", ##__VA_ARGS__) - -enum { - AUDIO_DEVICE_OUT_EARPIECE = 0, - AUDIO_DEVICE_OUT_SPEAKER, - AUDIO_DEVICE_OUT_WIRED_HEADSET, - AUDIO_DEVICE_OUT_WIRED_HEADPHONE, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, - AUDIO_DEVICE_OUT_AUX_DIGITAL, - AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, - AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, - AUDIO_DEVICE_OUT_USB_ACCESSORY, - AUDIO_DEVICE_OUT_USB_DEVICE, - AUDIO_DEVICE_OUT_REMOTE_SUBMIX, - AUDIO_DEVICE_OUT_ANC_HEADSET, - AUDIO_DEVICE_OUT_ANC_HEADPHONE, - AUDIO_DEVICE_OUT_PROXY, - AUDIO_DEVICE_OUT_FM, - AUDIO_DEVICE_OUT_FM_TX, - - AUDIO_DEVICE_OUT_COUNT -}; - -#define AUDIO_DEVICE_COMBO 0x400000 /* bit 23 */ - -enum { /* cache block */ - CB_0 = 0, - CB_1, - CB_2, - CB_3, - CB_4, - CB_5, - CB_6, - CB_7, - - CB_COUNT -}; - -enum { /* cache block description */ - CBD_DEV_MASK = 0, - CBD_OFFSG, - CBD_CMD0, - CBD_SZ0, - CBD_OFFS1, - CBD_CMD1, - CBD_SZ1, - CBD_OFFS2, - CBD_CMD2, - CBD_SZ2, - CBD_OFFS3, - CBD_CMD3, - CBD_SZ3, - - CBD_COUNT, -}; - -static s32 _fx_logN(s32 x) -{ - s32 t, y = 0xa65af; - if (x < 0x00008000) { - x <<= 16; y -= 0xb1721; } - if (x < 0x00800000) { - x <<= 8; y -= 0x58b91; } - if (x < 0x08000000) { - x <<= 4; y -= 0x2c5c8; } - if (x < 0x20000000) { - x <<= 2; y -= 0x162e4; } - if (x < 0x40000000) { - x <<= 1; y -= 0x0b172; } - t = x + (x >> 1); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x067cd; } - t = x + (x >> 2); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x03920; } - t = x + (x >> 3); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x01e27; } - t = x + (x >> 4); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x00f85; } - t = x + (x >> 5); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x007e1; } - t = x + (x >> 6); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x003f8; } - t = x + (x >> 7); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x001fe; } - x = 0x80000000 - x; - y -= x >> 15; - return y; -} - -static inline void *_getd(struct dts_eagle_param_desc *depd) -{ - return (void *)(((char *)depd) + sizeof(struct dts_eagle_param_desc)); -} - -static int _ref_cnt; -/* dts eagle parameter cache */ -static char *_depc; -static u32 _depc_size; -static s32 _c_bl[CB_COUNT][CBD_COUNT]; -static u32 _device_primary; -static u32 _device_all; -/* ION states */ -static struct ion_client *_ion_client; -static struct ion_handle *_ion_handle; -static struct param_outband _po; -static struct audio_client *_ac_NT; -static struct ion_client *_ion_client_NT; -static struct ion_handle *_ion_handle_NT; -static struct param_outband _po_NT; - -#define SEC_BLOB_MAX_CNT 10 -#define SEC_BLOB_MAX_SIZE 0x4004 /*extra 4 for size*/ -static char *_sec_blob[SEC_BLOB_MAX_CNT]; - -/* multi-copp support */ -static int _cidx[AFE_MAX_PORTS] = {-1}; - -/* volume controls */ -#define VOL_CMD_CNT_MAX 10 -static u32 _vol_cmd_cnt; -static s32 **_vol_cmds; -struct vol_cmds_d { - s32 d[4]; -}; -static struct vol_cmds_d *_vol_cmds_d; -static const s32 _log10_10_inv_x20 = 0x0008af84; - -/* hpx master control */ -static u32 _is_hpx_enabled; -/* flag to identify if slim be to be used */ -static u32 _use_slim_be; - -static void _volume_cmds_free(void) -{ - int i; - for (i = 0; i < _vol_cmd_cnt; i++) - kfree(_vol_cmds[i]); - _vol_cmd_cnt = 0; - kfree(_vol_cmds); - kfree(_vol_cmds_d); - _vol_cmds = NULL; - _vol_cmds_d = NULL; -} - -static s32 _volume_cmds_alloc1(s32 size) -{ - _volume_cmds_free(); - _vol_cmd_cnt = size; - _vol_cmds = kzalloc(_vol_cmd_cnt * sizeof(int *), GFP_KERNEL); - if (_vol_cmds) { - _vol_cmds_d = kzalloc(_vol_cmd_cnt * sizeof(struct vol_cmds_d), - GFP_KERNEL); - } else - _vol_cmd_cnt = 0; - if (_vol_cmds_d) - return 0; - _volume_cmds_free(); - return -ENOMEM; -} - -/* assumes size is equal or less than 0xFFF */ -static s32 _volume_cmds_alloc2(s32 idx, s32 size) -{ - kfree(_vol_cmds[idx]); - _vol_cmds[idx] = kzalloc(size, GFP_KERNEL); - if (_vol_cmds[idx]) - return 0; - _vol_cmds_d[idx].d[0] = 0; - return -ENOMEM; -} - -static void _init_cb_descs(void) -{ - int i; - for (i = 0; i < CB_COUNT; i++) { - _c_bl[i][CBD_DEV_MASK] = 0; - _c_bl[i][CBD_OFFSG] = _c_bl[i][CBD_OFFS1] = - _c_bl[i][CBD_OFFS2] = _c_bl[i][CBD_OFFS3] = - 0xFFFFFFFF; - _c_bl[i][CBD_CMD0] = _c_bl[i][CBD_SZ0] = - _c_bl[i][CBD_CMD1] = _c_bl[i][CBD_SZ1] = - _c_bl[i][CBD_CMD2] = _c_bl[i][CBD_SZ2] = - _c_bl[i][CBD_CMD3] = _c_bl[i][CBD_SZ3] = 0; - } -} - -static u32 _get_dev_mask_for_pid(int pid) -{ - switch (pid) { - case SLIMBUS_0_RX: - case AFE_PORT_ID_PRIMARY_MI2S_RX: - return (1 << AUDIO_DEVICE_OUT_EARPIECE) | - (1 << AUDIO_DEVICE_OUT_SPEAKER) | - (1 << AUDIO_DEVICE_OUT_WIRED_HEADSET) | - (1 << AUDIO_DEVICE_OUT_WIRED_HEADPHONE) | - (1 << AUDIO_DEVICE_OUT_ANC_HEADSET) | - (1 << AUDIO_DEVICE_OUT_ANC_HEADPHONE); - case INT_BT_SCO_RX: - return (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT); - case RT_PROXY_PORT_001_RX: - return (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) | - (1 << AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) | - (1 << AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) | - (1 << AUDIO_DEVICE_OUT_USB_ACCESSORY) | - (1 << AUDIO_DEVICE_OUT_USB_DEVICE) | - (1 << AUDIO_DEVICE_OUT_PROXY); - case HDMI_RX: - return 1 << AUDIO_DEVICE_OUT_AUX_DIGITAL; - case INT_FM_RX: - return 1 << AUDIO_DEVICE_OUT_FM; - case INT_FM_TX: - return 1 << AUDIO_DEVICE_OUT_FM_TX; - default: - return 0; - } -} - -static int _get_pid_from_dev(u32 device) -{ - if (device & (1 << AUDIO_DEVICE_OUT_EARPIECE) || - device & (1 << AUDIO_DEVICE_OUT_SPEAKER) || - device & (1 << AUDIO_DEVICE_OUT_WIRED_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_WIRED_HEADPHONE) || - device & (1 << AUDIO_DEVICE_OUT_ANC_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_ANC_HEADPHONE)) { - if (_use_slim_be) { - return SLIMBUS_0_RX; - } else { - return AFE_PORT_ID_PRIMARY_MI2S_RX; - } - } else if (device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) { - return INT_BT_SCO_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) || - device & (1 << AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_USB_ACCESSORY) || - device & (1 << AUDIO_DEVICE_OUT_USB_DEVICE) || - device & (1 << AUDIO_DEVICE_OUT_PROXY)) { - return RT_PROXY_PORT_001_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_AUX_DIGITAL)) { - return HDMI_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_FM)) { - return INT_FM_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_FM_TX)) { - return INT_FM_TX; - } - return 0; -} - -static s32 _get_cb_for_dev(int device) -{ - s32 i; - if (device & AUDIO_DEVICE_COMBO) { - for (i = 0; i < CB_COUNT; i++) { - if ((_c_bl[i][CBD_DEV_MASK] & device) == device) - return i; - } - } else { - for (i = 0; i < CB_COUNT; i++) { - if ((_c_bl[i][CBD_DEV_MASK] & device) && - !(_c_bl[i][CBD_DEV_MASK] & AUDIO_DEVICE_COMBO)) - return i; - } - } - eagle_drv_err("%s: device %i not found", __func__, device); - return -EINVAL; -} - -static int _is_port_open_and_eagle(int pid) -{ - if (msm_routing_check_backend_enabled(pid)) - return 1; - return 1; -} - -static int _isNTDevice(u32 device) -{ - if (device & - ((1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) | - (1 << AUDIO_DEVICE_OUT_AUX_DIGITAL))) - return 1; - return 0; -} - -static void _reg_ion_mem(void) -{ - int rc; - rc = msm_audio_ion_alloc("DTS_EAGLE", &_ion_client, &_ion_handle, - ION_MEM_SIZE, &_po.paddr, &_po.size, &_po.kvaddr); - if (rc) - eagle_drv_err("%s: msm audio ion alloc failed with %i", - __func__, rc); -} - -static void _unreg_ion_mem(void) -{ - int rc; - rc = msm_audio_ion_free(_ion_client, _ion_handle); - if (rc) - eagle_drv_err("%s: msm audio ion alloc failed with %i", - __func__, rc); -} - -static void _reg_ion_mem_NT(void) -{ - int rc; - eagle_drv_dbg("%s: NT ion mem", __func__); - rc = msm_audio_ion_alloc("DTS_EAGLE", &_ion_client_NT, - &_ion_handle_NT, ION_MEM_SIZE, - &_po_NT.paddr, &_po_NT.size, &_po_NT.kvaddr); - if (rc) { - eagle_drv_err("%s: msm audio ion alloc failed", __func__); - return; - } - rc = q6asm_memory_map(_ac_NT, _po_NT.paddr, - IN, _po_NT.size, 1); - if (rc < 0) { - eagle_drv_err("%s: memory map failed", __func__); - msm_audio_ion_free(_ion_client_NT, _ion_handle_NT); - _ion_client_NT = NULL; - _ion_handle_NT = NULL; - } -} - -static void _unreg_ion_mem_NT(void) -{ - int rc; - rc = q6asm_memory_unmap(_ac_NT, _po_NT.paddr, IN); - if (rc < 0) - eagle_drv_err("%s: mem unmap failed", __func__); - rc = msm_audio_ion_free(_ion_client_NT, _ion_handle_NT); - if (rc < 0) - eagle_drv_err("%s: mem free failed", __func__); - - _ion_client_NT = NULL; - _ion_handle_NT = NULL; -} - -static struct audio_client *_getNTDeviceAC(void) -{ - return _ac_NT; -} - -static void _set_audioclient(struct audio_client *ac) -{ - _ac_NT = ac; - _reg_ion_mem_NT(); -} - -static void _clear_audioclient(void) -{ - _unreg_ion_mem_NT(); - _ac_NT = NULL; -} - - -static int _sendcache_pre(struct audio_client *ac) -{ - uint32_t offset, size; - int32_t cidx, cmd, err = 0; - cidx = _get_cb_for_dev(_device_primary); - if (cidx < 0) { - eagle_precache_err("%s: no cache for primary device %i found", - __func__, _device_primary); - return -EINVAL; - } - offset = _c_bl[cidx][CBD_OFFSG]; - cmd = _c_bl[cidx][CBD_CMD0]; - size = _c_bl[cidx][CBD_SZ0]; - /* check for integer overflow */ - if (offset > (UINT_MAX - size)) - err = -EINVAL; - if ((_depc_size == 0) || !_depc || (size == 0) || - cmd == 0 || ((offset + size) > _depc_size) || (err != 0)) { - eagle_precache_err("%s: primary device %i cache index %i general error - cache size = %u, cache ptr = %pK, offset = %u, size = %u, cmd = %i", - __func__, _device_primary, cidx, _depc_size, _depc, - offset, size, cmd); - return -EINVAL; - } - - if ((offset < (UINT_MAX - 124)) && ((offset + 124) < _depc_size)) - eagle_precache_dbg("%s: first 6 integers %i %i %i %i %i %i (30th %i)", - __func__, *((int *)&_depc[offset]), - *((int *)&_depc[offset+4]), - *((int *)&_depc[offset+8]), - *((int *)&_depc[offset+12]), - *((int *)&_depc[offset+16]), - *((int *)&_depc[offset+20]), - *((int *)&_depc[offset+120])); - eagle_precache_dbg("%s: sending full data block to port, with cache index = %d device mask 0x%X, param = 0x%X, offset = %u, and size = %u", - __func__, cidx, _c_bl[cidx][CBD_DEV_MASK], cmd, offset, size); - - if (q6asm_dts_eagle_set(ac, cmd, size, (void *)&_depc[offset], - NULL, MPRE)) - eagle_precache_err("%s: q6asm_dts_eagle_set failed with id = %d and size = %u", - __func__, cmd, size); - else - eagle_precache_dbg("%s: q6asm_dts_eagle_set succeeded with id = %d and size = %u", - __func__, cmd, size); - return 0; -} - -static int _sendcache_post(int port_id, int copp_idx, int topology) -{ - int cidx = -1, cmd, mask, index, err = 0; - uint32_t offset, size; - - if (port_id == -1) { - cidx = _get_cb_for_dev(_device_primary); - if (cidx < 0) { - eagle_postcache_err("%s: no cache for primary device %i found. Port id was 0x%X", - __func__, _device_primary, port_id); - return -EINVAL; - } - goto NT_MODE_GOTO; - } - - index = adm_validate_and_get_port_index(port_id); - if (index < 0) { - eagle_postcache_err("%s: Invalid port idx %d port_id %#x", - __func__, index, port_id); - return -EINVAL; - } - eagle_postcache_dbg("%s: valid port idx %d for port_id %#x set to %i", - __func__, index, port_id, copp_idx); - _cidx[index] = copp_idx; - - mask = _get_dev_mask_for_pid(port_id); - if (mask & _device_primary) { - cidx = _get_cb_for_dev(_device_primary); - if (cidx < 0) { - eagle_postcache_err("%s: no cache for primary device %i found. Port id was 0x%X", - __func__, _device_primary, port_id); - return -EINVAL; - } - } else if (mask & _device_all) { - cidx = _get_cb_for_dev(_device_all); - if (cidx < 0) { - eagle_postcache_err("%s: no cache for combo device %i found. Port id was 0x%X", - __func__, _device_all, port_id); - return -EINVAL; - } - } else { - eagle_postcache_err("%s: port id 0x%X not for primary or combo device %i", - __func__, port_id, _device_primary); - return -EINVAL; - } - -NT_MODE_GOTO: - offset = _c_bl[cidx][CBD_OFFSG] + _c_bl[cidx][CBD_OFFS2]; - cmd = _c_bl[cidx][CBD_CMD2]; - size = _c_bl[cidx][CBD_SZ2]; - - /* check for integer overflow */ - if (offset > (UINT_MAX - size)) - err = -EINVAL; - if ((_depc_size == 0) || !_depc || (err != 0) || (size == 0) || - (cmd == 0) || (offset + size) > _depc_size) { - eagle_postcache_err("%s: primary device %i cache index %i port_id 0x%X general error - cache size = %u, cache ptr = %pK, offset = %u, size = %u, cmd = %i", - __func__, _device_primary, cidx, port_id, - _depc_size, _depc, offset, size, cmd); - return -EINVAL; - } - - if ((offset < (UINT_MAX - 24)) && ((offset + 24) < _depc_size)) - eagle_postcache_dbg("%s: first 6 integers %i %i %i %i %i %i", - __func__, *((int *)&_depc[offset]), - *((int *)&_depc[offset+4]), - *((int *)&_depc[offset+8]), - *((int *)&_depc[offset+12]), - *((int *)&_depc[offset+16]), - *((int *)&_depc[offset+20])); - eagle_postcache_dbg("%s: sending full data block to port, with cache index = %d device mask 0x%X, port_id = 0x%X, param = 0x%X, offset = %u, and size = %u", - __func__, cidx, _c_bl[cidx][CBD_DEV_MASK], port_id, cmd, - offset, size); - - if (_ac_NT) { - eagle_postcache_dbg("%s: NT Route detected", __func__); - if (q6asm_dts_eagle_set(_getNTDeviceAC(), cmd, size, - (void *)&_depc[offset], - &_po_NT, MPST)) - eagle_postcache_err("%s: q6asm_dts_eagle_set failed with id = 0x%X and size = %u", - __func__, cmd, size); - } else if (adm_dts_eagle_set(port_id, copp_idx, cmd, - (void *)&_depc[offset], size) < 0) - eagle_postcache_err("%s: adm_dts_eagle_set failed with id = 0x%X and size = %u", - __func__, cmd, size); - else - eagle_postcache_dbg("%s: adm_dts_eagle_set succeeded with id = 0x%X and size = %u", - __func__, cmd, size); - return 0; -} - -static int _enable_post_get_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = _is_hpx_enabled; - return 0; -} - -static int _enable_post_put_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int idx = 0, be_index = 0, port_id, topology; - int flag = ucontrol->value.integer.value[0]; - struct msm_pcm_routing_bdai_data msm_bedai; - eagle_drv_dbg("%s: flag %d", __func__, flag); - - _is_hpx_enabled = flag ? true : false; - msm_pcm_routing_acquire_lock(); - /* send cache postmix params when hpx is set On */ - for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) { - msm_pcm_routing_get_bedai_info(be_index, &msm_bedai); - port_id = msm_bedai.port_id; - if (!(((port_id == SLIMBUS_0_RX) || - (port_id == RT_PROXY_PORT_001_RX) || - (port_id == AFE_PORT_ID_PRIMARY_MI2S_RX)) && - msm_bedai.active)) - continue; - for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { - topology = adm_get_topology_for_port_copp_idx( - port_id, idx); - if (topology == - ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) { - msm_dts_eagle_enable_adm(port_id, idx, - _is_hpx_enabled); - } - } - } - msm_pcm_routing_release_lock(); - return 0; -} - -static const struct snd_kcontrol_new _hpx_enabled_controls[] = { - SOC_SINGLE_EXT("Set HPX OnOff", SND_SOC_NOPM, 0, 1, 0, - _enable_post_get_control, _enable_post_put_control) -}; - -static int _be_post_get_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = _use_slim_be; - return 0; -} - -static int _be_post_put_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - _use_slim_be = ucontrol->value.integer.value[0]; - eagle_drv_dbg(" valuse of _use_slim_be == %d", _use_slim_be); - return 0; -} - -static const struct snd_kcontrol_new _hpx_be_controls[] = { - SOC_SINGLE_EXT("Set HPX ActiveBe", SND_SOC_NOPM, 0, 1, 0, - _be_post_get_control, _be_post_put_control) -}; -/** - * msm_dts_ion_memmap() - helper function to map ION memory - * @po_: Out of band memory structure used as memory. - * - * Assign already allocated ION memory for mapping it to dsp. - * - * Return: No return value. - */ -void msm_dts_ion_memmap(struct param_outband *po_) -{ - po_->size = ION_MEM_SIZE; - po_->kvaddr = _po.kvaddr; - po_->paddr = _po.paddr; -} - -/** - * msm_dts_eagle_enable_asm() - Enable/disable dts module - * @ac: Enable/disable module in ASM session associated with this audio client. - * @enable: Enable/disable the dts module. - * @module: module id. - * - * Enable/disable specified dts module id in asm. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_enable_asm(struct audio_client *ac, u32 enable, int module) -{ - int ret = 0; - eagle_enable_dbg("%s: enable = %i on module %i", - __func__, enable, module); - _is_hpx_enabled = enable; - ret = q6asm_dts_eagle_set(ac, AUDPROC_PARAM_ID_ENABLE, - sizeof(enable), &enable, - NULL, module); - if (_is_hpx_enabled) { - if (module == MPRE) - _sendcache_pre(ac); - else if (module == MPST) - _sendcache_post(-1, 0, 0); - } - return ret; -} - -/** - * msm_dts_eagle_enable_adm() - Enable/disable dts module in adm - * @port_id: Send enable/disable param to this port id. - * @copp_idx: Send enable/disable param to the relevant copp. - * @enable: Enable/disable the dts module. - * - * Enable/disable dts module in adm. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_enable_adm(int port_id, int copp_idx, u32 enable) -{ - int ret = 0; - eagle_enable_dbg("%s: enable = %i", __func__, enable); - _is_hpx_enabled = enable; - ret = adm_dts_eagle_set(port_id, copp_idx, AUDPROC_PARAM_ID_ENABLE, - (char *)&enable, sizeof(enable)); - if (_is_hpx_enabled) - _sendcache_post(port_id, copp_idx, MPST); - return ret; -} - -/** - * msm_dts_eagle_add_controls() - Add mixer control to Enable/Disable DTS HPX - * @platform: Add mixer controls to this platform. - * - * Add mixer control to Enable/Disable DTS HPX module in ADM. - * - * Return: No return value. - */ -void msm_dts_eagle_add_controls(struct snd_soc_platform *platform) -{ - snd_soc_add_platform_controls(platform, _hpx_enabled_controls, - ARRAY_SIZE(_hpx_enabled_controls)); - snd_soc_add_platform_controls(platform, _hpx_be_controls, - ARRAY_SIZE(_hpx_be_controls)); - -} - -/** - * msm_dts_eagle_set_stream_gain() - Set stream gain to DTS Premix module - * @ac: Set stream gain to ASM session associated with this audio client. - * @lgain: Left gain value. - * @rgain: Right gain value. - * - * Set stream gain to DTS Premix module in ASM. - * - * Return: failure or success. - */ -int msm_dts_eagle_set_stream_gain(struct audio_client *ac, int lgain, int rgain) -{ - u32 i, val; - s32 idx, err = 0; - - eagle_vol_dbg("%s: - entry: vol_cmd_cnt = %u, lgain = %i, rgain = %i", - __func__, _vol_cmd_cnt, lgain, rgain); - - if (_depc_size == 0) { - eagle_vol_dbg("%s: driver cache not initialized", __func__); - return -EINVAL; - } - - for (i = 0; i < _vol_cmd_cnt; i++) { - if (_vol_cmds_d[i].d[0] & 0x8000) { - idx = (sizeof(struct dts_eagle_param_desc)/sizeof(int)) - + (_vol_cmds_d[i].d[0] & 0x3FF); - val = _fx_logN(((s32)(lgain+rgain)) << 2); - val = ((long long)val * _log10_10_inv_x20) >> 16; - _vol_cmds[i][idx] = (s32)clamp((int)(((long long)val * - _vol_cmds_d[i].d[1]) >> 16), - _vol_cmds_d[i].d[2], - _vol_cmds_d[i].d[3]); - eagle_vol_dbg("%s: loop %u cmd desc found %i, idx = %i. volume info: lgain = %i, rgain = %i, volume = %i (scale %i, min %i, max %i)", - __func__, i, _vol_cmds_d[i].d[0], idx, lgain, - rgain, _vol_cmds[i][idx], _vol_cmds_d[i].d[1], - _vol_cmds_d[i].d[2], _vol_cmds_d[i].d[3]); - } - idx = _get_cb_for_dev(_device_primary); - if (idx < 0) { - eagle_vol_err("%s: no cache for primary device %i found", - __func__, _device_primary); - return -EINVAL; - } - val = _c_bl[idx][CBD_OFFSG] + _vol_cmds[i][2]; - /* check for integer overflow */ - if (val > (UINT_MAX - _vol_cmds[i][1])) - err = -EINVAL; - if ((err != 0) || ((val + _vol_cmds[i][1]) > _depc_size)) { - eagle_vol_err("%s: volume size (%u) + offset (%i) out of bounds %i", - __func__, val, _vol_cmds[i][1], _depc_size); - return -EINVAL; - } - memcpy((void *)&_depc[val], &_vol_cmds[i][4], _vol_cmds[i][1]); - if (q6asm_dts_eagle_set(ac, _vol_cmds[i][0], - _vol_cmds[i][1], (void *)&_depc[val], NULL, MPRE)) - eagle_vol_err("%s: loop %u - volume set failed with id 0x%X, size %i, offset %i, cmd_desc %i, scale %i, min %i, max %i, data(...) %i", - __func__, i, _vol_cmds[i][0], _vol_cmds[i][1], - _vol_cmds[i][2], _vol_cmds_d[i].d[0], - _vol_cmds_d[i].d[1], _vol_cmds_d[i].d[2], - _vol_cmds_d[i].d[3], _vol_cmds[i][4]); - else - eagle_vol_dbg("%s: loop %u - volume set succeeded with id 0x%X, size %i, offset %i, cmd_desc %i, scale %i, min %i, max %i, data(...) %i", - __func__, i, _vol_cmds[i][0], _vol_cmds[i][1], - _vol_cmds[i][2], _vol_cmds_d[i].d[0], - _vol_cmds_d[i].d[1], _vol_cmds_d[i].d[2], - _vol_cmds_d[i].d[3], _vol_cmds[i][4]); - } - return 0; -} - -/** - * msm_dts_eagle_handle_asm() - Set or Get params from ASM - * @depd: DTS Eagle Params structure. - * @buf: Buffer to get queried param value. - * @for_pre: For premix module or postmix module. - * @get: Getting param from DSP or setting param. - * @ac: Set/Get from ASM session associated with this audio client. - * @po: Out of band memory to set or get postmix params. - * - * Set or Get params from modules in ASM session. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get, struct audio_client *ac, - struct param_outband *po) -{ - struct dts_eagle_param_desc depd_ = {0}; - s32 ret = 0, isALSA = 0, err = 0, i, mod = for_pre ? MPRE : MPST; - u32 offset; - - eagle_asm_dbg("%s: set/get asm", __func__); - - /* special handling for ALSA route, to accommodate 64 bit platforms */ - if (depd == NULL) { - long *arg_ = (long *)buf; - depd = &depd_; - depd->id = (u32)*arg_++; - depd->size = (u32)*arg_++; - depd->offset = (s32)*arg_++; - depd->device = (u32)*arg_++; - buf = (char *)arg_; - isALSA = 1; - } - - if (depd->size & 1) { - eagle_asm_err("%s: parameter size %u is not a multiple of 2", - __func__, depd->size); - return -EINVAL; - } - - if (get) { - void *buf_, *buf_m = NULL; - eagle_asm_dbg("%s: get requested", __func__); - if (depd->offset == -1) { - eagle_asm_dbg("%s: get from dsp requested", __func__); - if (depd->size > 0 && depd->size <= DEPC_MAX_SIZE) { - buf_ = buf_m = vzalloc(depd->size); - } else { - eagle_asm_err("%s: get size %u invalid", - __func__, depd->size); - return -EINVAL; - } - if (!buf_m) { - eagle_asm_err("%s: out of memory", __func__); - return -ENOMEM; - } else if (q6asm_dts_eagle_get(ac, depd->id, - depd->size, buf_m, - po, mod) < 0) { - eagle_asm_err("%s: asm get failed", __func__); - ret = -EFAULT; - goto DTS_EAGLE_IOCTL_GET_PARAM_PRE_EXIT; - } - eagle_asm_dbg("%s: get result: param id 0x%x value %d size %u", - __func__, depd->id, *(int *)buf_m, depd->size); - } else { - s32 tgt = _get_cb_for_dev(depd->device); - if (tgt < 0) { - eagle_asm_err("%s: no cache for device %u found", - __func__, depd->device); - return -EINVAL; - } - offset = _c_bl[tgt][CBD_OFFSG] + depd->offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd->size)) - err = -EINVAL; - if ((err != 0) || (offset + depd->size) > _depc_size) { - eagle_asm_err("%s: invalid size %u and/or offset %u", - __func__, depd->size, offset); - return -EINVAL; - } - buf_ = (u32 *)&_depc[offset]; - } - if (isALSA) { - if (depd->size == 2) { - *(long *)buf = (long)*(__u16 *)buf_; - eagle_asm_dbg("%s: asm out 16 bit value %li", - __func__, *(long *)buf); - } else { - s32 *pbuf = (s32 *)buf_; - long *bufl = (long *)buf; - for (i = 0; i < (depd->size >> 2); i++) { - *bufl++ = (long)*pbuf++; - eagle_asm_dbg("%s: asm out value %li", - __func__, *(bufl-1)); - } - } - } else { - memcpy(buf, buf_, depd->size); - } -DTS_EAGLE_IOCTL_GET_PARAM_PRE_EXIT: - vfree(buf_m); - return (int)ret; - } else { - s32 tgt = _get_cb_for_dev(depd->device); - if (tgt < 0) { - eagle_asm_err("%s: no cache for device %u found", - __func__, depd->device); - return -EINVAL; - } - offset = _c_bl[tgt][CBD_OFFSG] + depd->offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd->size)) - err = -EINVAL; - if ((err != 0) || ((offset + depd->size) > _depc_size)) { - eagle_asm_err("%s: invalid size %u and/or offset %u for parameter (cache is size %u)", - __func__, depd->size, offset, _depc_size); - return -EINVAL; - } - if (isALSA) { - if (depd->size == 2) { - *(__u16 *)&_depc[offset] = (__u16)*(long *)buf; - eagle_asm_dbg("%s: asm in 16 bit value %li", - __func__, *(long *)buf); - } else { - s32 *pbuf = (s32 *)&_depc[offset]; - long *bufl = (long *)buf; - for (i = 0; i < (depd->size >> 2); i++) { - *pbuf++ = (s32)*bufl++; - eagle_asm_dbg("%s: asm in value %i", - __func__, *(pbuf-1)); - } - } - } else { - memcpy(&_depc[offset], buf, depd->size); - } - eagle_asm_dbg("%s: param info: param = 0x%X, size = %u, offset = %i, device = %u, cache block %i, global offset = %u, first bytes as integer = %i", - __func__, depd->id, depd->size, depd->offset, - depd->device, - tgt, offset, *(int *)&_depc[offset]); - if (q6asm_dts_eagle_set(ac, depd->id, depd->size, - (void *)&_depc[offset], po, mod)) - eagle_asm_err("%s: q6asm_dts_eagle_set failed with id = 0x%X, size = %u, offset = %d", - __func__, depd->id, depd->size, depd->offset); - else - eagle_asm_dbg("%s: q6asm_dts_eagle_set succeeded with id = 0x%X, size = %u, offset = %d", - __func__, depd->id, depd->size, depd->offset); - } - return (int)ret; -} - -/** - * msm_dts_eagle_handle_adm() - Set or Get params from ADM - * @depd: DTS Eagle Params structure used to set or get. - * @buf: Buffer to get queried param value in NT mode. - * @for_pre: For premix module or postmix module. - * @get: Getting param from DSP or setting param. - * - * Set or Get params from modules in ADM session. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get) -{ - u32 pid = _get_pid_from_dev(depd->device), cidx; - s32 ret = 0; - - eagle_adm_dbg("%s: set/get adm", __func__); - - if (_isNTDevice(depd->device)) { - eagle_adm_dbg("%s: NT Route detected", __func__); - ret = msm_dts_eagle_handle_asm(depd, buf, for_pre, get, - _getNTDeviceAC(), &_po_NT); - if (ret < 0) - eagle_adm_err("%s: NT Route set failed with id = 0x%X, size = %u, offset = %i, device = %u", - __func__, depd->id, depd->size, depd->offset, - depd->device); - } else if (get) { - cidx = adm_validate_and_get_port_index(pid); - eagle_adm_dbg("%s: get from qdsp requested (port id 0x%X)", - __func__, pid); - if (adm_dts_eagle_get(pid, _cidx[cidx], depd->id, - buf, depd->size) < 0) { - eagle_adm_err("%s: get from qdsp via adm with port id 0x%X failed", - __func__, pid); - return -EFAULT; - } - } else if (_is_port_open_and_eagle(pid)) { - cidx = adm_validate_and_get_port_index(pid); - eagle_adm_dbg("%s: adm_dts_eagle_set called with id = 0x%X, size = %u, offset = %i, device = %u, port id = %u, copp index = %u", - __func__, depd->id, depd->size, depd->offset, - depd->device, pid, cidx); - ret = adm_dts_eagle_set(pid, _cidx[cidx], depd->id, - (void *)buf, depd->size); - if (ret < 0) - eagle_adm_err("%s: adm_dts_eagle_set failed", __func__); - else - eagle_adm_dbg("%s: adm_dts_eagle_set succeeded", - __func__); - } else { - ret = -EINVAL; - eagle_adm_dbg("%s: port id 0x%X not active or not Eagle", - __func__, pid); - } - return (int)ret; -} - -/** - * msm_dts_eagle_ioctl() - ioctl handler function - * @cmd: cmd to handle. - * @arg: argument to the cmd. - * - * Handle DTS Eagle ioctl cmds. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) -{ - s32 ret = 0; - switch (cmd) { - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE: { - eagle_ioctl_info("%s: called with control 0x%X (get param cache size)", - __func__, cmd); - if (copy_to_user((void *)arg, &_depc_size, - sizeof(_depc_size))) { - eagle_ioctl_err("%s: error writing size", __func__); - return -EFAULT; - } - break; - } - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE: { - u32 size = 0; - eagle_ioctl_info("%s: called with control 0x%X (allocate param cache)", - __func__, cmd); - if (copy_from_user((void *)&size, (void *)arg, sizeof(size))) { - eagle_ioctl_err("%s: error copying size (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &size, sizeof(size)); - return -EFAULT; - } else if (size > DEPC_MAX_SIZE) { - eagle_ioctl_err("%s: cache size %u not allowed (min 0, max %u)", - __func__, size, DEPC_MAX_SIZE); - return -EINVAL; - } - if (_depc) { - eagle_ioctl_dbg("%s: previous param cache of size %u freed", - __func__, _depc_size); - _depc_size = 0; - vfree(_depc); - _depc = NULL; - } - if (size) - _depc = vzalloc(size); - else - eagle_ioctl_dbg("%s: %u bytes requested for param cache, nothing allocated", - __func__, size); - if (_depc) { - eagle_ioctl_dbg("%s: %u bytes allocated for param cache", - __func__, size); - _depc_size = size; - } else { - eagle_ioctl_err("%s: error allocating param cache (vzalloc failed on %u bytes)", - __func__, size); - _depc_size = 0; - return -ENOMEM; - } - break; - } - case DTS_EAGLE_IOCTL_GET_PARAM: { - struct dts_eagle_param_desc depd; - s32 for_pre = 0, get_from_core = 0, err = 0; - u32 offset; - void *buf, *buf_m = NULL; - eagle_ioctl_info("%s: control 0x%X (get param)", - __func__, cmd); - if (copy_from_user((void *)&depd, (void *)arg, sizeof(depd))) { - eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &depd, sizeof(depd)); - return -EFAULT; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_PRE) { - eagle_ioctl_dbg("%s: using for premix", __func__); - for_pre = 1; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_GETFROMCORE) { - eagle_ioctl_dbg("%s: 'get from core' requested", - __func__); - get_from_core = 1; - depd.offset = -1; - } - depd.device &= DTS_EAGLE_FLAG_IOCTL_MASK; - if (depd.offset == -1) { - if (depd.size > 0 && depd.size <= DEPC_MAX_SIZE) { - buf = buf_m = vzalloc(depd.size); - } else { - eagle_ioctl_err("%s: get size %u invalid", - __func__, depd.size); - return -EINVAL; - } - if (!buf_m) { - eagle_ioctl_err("%s: out of memory", __func__); - return -ENOMEM; - } - if (get_from_core) - ret = core_dts_eagle_get(depd.id, depd.size, - buf); - else - ret = msm_dts_eagle_handle_adm(&depd, buf, - for_pre, true); - } else { - s32 cb = _get_cb_for_dev(depd.device); - if (cb < 0) { - eagle_ioctl_err("%s: no cache for device %u found", - __func__, depd.device); - return -EINVAL; - } - offset = _c_bl[cb][CBD_OFFSG] + depd.offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd.size)) - err = -EINVAL; - if ((err != 0) || - ((offset + depd.size) > _depc_size)) { - eagle_ioctl_err("%s: invalid size %u and/or offset %u", - __func__, depd.size, offset); - return -EINVAL; - } - buf = (void *)&_depc[offset]; - } - if (ret < 0) - eagle_ioctl_err("%s: error %i getting data", __func__, - ret); - else if (copy_to_user((void *)(((char *)arg)+sizeof(depd)), - buf, depd.size)) { - eagle_ioctl_err("%s: error copying get data", __func__); - ret = -EFAULT; - } - vfree(buf_m); - break; - } - case DTS_EAGLE_IOCTL_SET_PARAM: { - struct dts_eagle_param_desc depd; - s32 just_set_cache = 0, for_pre = 0, err = 0; - u32 offset; - s32 tgt; - eagle_ioctl_info("%s: control 0x%X (set param)", - __func__, cmd); - if (copy_from_user((void *)&depd, (void *)arg, sizeof(depd))) { - eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &depd, sizeof(depd)); - return -EFAULT; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_PRE) { - eagle_ioctl_dbg("%s: using for premix", __func__); - for_pre = 1; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_JUSTSETCACHE) { - eagle_ioctl_dbg("%s: 'just set cache' requested", - __func__); - just_set_cache = 1; - } - depd.device &= DTS_EAGLE_FLAG_IOCTL_MASK; - tgt = _get_cb_for_dev(depd.device); - if (tgt < 0) { - eagle_ioctl_err("%s: no cache for device %u found", - __func__, depd.device); - return -EINVAL; - } - offset = _c_bl[tgt][CBD_OFFSG] + depd.offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd.size)) - err = -EINVAL; - if ((err != 0) || ((offset + depd.size) > _depc_size)) { - eagle_ioctl_err("%s: invalid size %u and/or offset %u for parameter (target cache block %i with offset %i, global cache is size %u)", - __func__, depd.size, offset, tgt, - _c_bl[tgt][CBD_OFFSG], _depc_size); - return -EINVAL; - } - if (copy_from_user((void *)&_depc[offset], - (void *)(((char *)arg)+sizeof(depd)), - depd.size)) { - eagle_ioctl_err("%s: error copying param to cache (src:%pK, tgt:%pK, size:%u)", - __func__, ((char *)arg)+sizeof(depd), - &_depc[offset], depd.size); - return -EFAULT; - } - eagle_ioctl_dbg("%s: param info: param = 0x%X, size = %u, offset = %i, device = %u, cache block %i, global offset = %u, first bytes as integer = %i", - __func__, depd.id, depd.size, depd.offset, - depd.device, tgt, offset, *(int *)&_depc[offset]); - if (!just_set_cache) { - ret = msm_dts_eagle_handle_adm(&depd, &_depc[offset], - for_pre, false); - } - break; - } - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK: { - u32 b_[CBD_COUNT+1], *b = &b_[1], cb; - eagle_ioctl_info("%s: with control 0x%X (set param cache block)", - __func__, cmd); - if (copy_from_user((void *)b_, (void *)arg, sizeof(b_))) { - eagle_ioctl_err("%s: error copying cache block data (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, b_, sizeof(b_)); - return -EFAULT; - } - cb = b_[0]; - if (cb >= CB_COUNT) { - eagle_ioctl_err("%s: cache block %u out of range (max %u)", - __func__, cb, CB_COUNT-1); - return -EINVAL; - } - eagle_ioctl_dbg("%s: cache block %i set: devices 0x%X, global offset %i, offsets 1:%u 2:%u 3:%u, cmds/sizes 0:0x%X %u 1:0x%X %u 2:0x%X %u 3:0x%X %u", - __func__, cb, _c_bl[cb][CBD_DEV_MASK], _c_bl[cb][CBD_OFFSG], - _c_bl[cb][CBD_OFFS1], _c_bl[cb][CBD_OFFS2], - _c_bl[cb][CBD_OFFS3], _c_bl[cb][CBD_CMD0], _c_bl[cb][CBD_SZ0], - _c_bl[cb][CBD_CMD1], _c_bl[cb][CBD_SZ1], _c_bl[cb][CBD_CMD2], - _c_bl[cb][CBD_SZ2], _c_bl[cb][CBD_CMD3], _c_bl[cb][CBD_SZ3]); - if ((b[CBD_OFFSG]+b[CBD_OFFS1]+b[CBD_SZ1]) > _depc_size || - (b[CBD_OFFSG]+b[CBD_OFFS2]+b[CBD_SZ2]) > _depc_size || - (b[CBD_OFFSG]+b[CBD_OFFS3]+b[CBD_SZ3]) > _depc_size) { - eagle_ioctl_err("%s: cache block bounds out of range", - __func__); - return -EINVAL; - } - memcpy(_c_bl[cb], b, sizeof(_c_bl[cb])); - break; - } - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE: { - u32 data[2]; - eagle_ioctl_dbg("%s: with control 0x%X (set active device)", - __func__, cmd); - if (copy_from_user((void *)data, (void *)arg, sizeof(data))) { - eagle_ioctl_err("%s: error copying active device data (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, data, sizeof(data)); - return -EFAULT; - } - if (data[1] != 0) { - _device_primary = data[0]; - eagle_ioctl_dbg("%s: primary device %i", __func__, - data[0]); - } else { - _device_all = data[0]; - eagle_ioctl_dbg("%s: all devices 0x%X", __func__, - data[0]); - } - break; - } - case DTS_EAGLE_IOCTL_GET_LICENSE: { - u32 target = 0, size = 0; - s32 size_only; - eagle_ioctl_dbg("%s: with control 0x%X (get license)", - __func__, cmd); - if (copy_from_user((void *)&target, (void *)arg, - sizeof(target))) { - eagle_ioctl_err("%s: error reading license index. (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &target, sizeof(target)); - return -EFAULT; - } - size_only = target & (1<<31) ? 1 : 0; - target &= 0x7FFFFFFF; - if (target >= SEC_BLOB_MAX_CNT) { - eagle_ioctl_err("%s: license index %u out of bounds (max index is %i)", - __func__, target, SEC_BLOB_MAX_CNT); - return -EINVAL; - } - if (_sec_blob[target] == NULL) { - eagle_ioctl_err("%s: license index %u never initialized", - __func__, target); - return -EINVAL; - } - size = ((u32 *)_sec_blob[target])[0]; - if ((size == 0) || (size > SEC_BLOB_MAX_SIZE)) { - eagle_ioctl_err("%s: license size %u for index %u invalid (min size is 1, max size is %u)", - __func__, size, target, SEC_BLOB_MAX_SIZE); - return -EINVAL; - } - if (size_only) { - eagle_ioctl_dbg("%s: reporting size of license data only", - __func__); - if (copy_to_user((void *)(((char *)arg)+sizeof(target)), - (void *)&size, sizeof(size))) { - eagle_ioctl_err("%s: error copying license size", - __func__); - return -EFAULT; - } - } else if (copy_to_user((void *)(((char *)arg)+sizeof(target)), - (void *)&(((s32 *)_sec_blob[target])[1]), size)) { - eagle_ioctl_err("%s: error copying license data", - __func__); - return -EFAULT; - } else - eagle_ioctl_info("%s: license file %u bytes long from license index %u returned to user", - __func__, size, target); - break; - } - case DTS_EAGLE_IOCTL_SET_LICENSE: { - u32 target[2] = {0, 0}; - eagle_ioctl_dbg("%s: control 0x%X (set license)", __func__, - cmd); - if (copy_from_user((void *)target, (void *)arg, - sizeof(target))) { - eagle_ioctl_err("%s: error reading license index (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, target, sizeof(target)); - return -EFAULT; - } - if (target[0] >= SEC_BLOB_MAX_CNT) { - eagle_ioctl_err("%s: license index %u out of bounds (max index is %u)", - __func__, target[0], SEC_BLOB_MAX_CNT-1); - return -EINVAL; - } - if (target[1] == 0) { - eagle_ioctl_dbg("%s: request to free license index %u", - __func__, target[0]); - kfree(_sec_blob[target[0]]); - _sec_blob[target[0]] = NULL; - break; - } - if ((target[1] == 0) || (target[1] >= SEC_BLOB_MAX_SIZE)) { - eagle_ioctl_err("%s: license size %u for index %u invalid (min size is 1, max size is %u)", - __func__, target[1], target[0], - SEC_BLOB_MAX_SIZE); - return -EINVAL; - } - if (_sec_blob[target[0]] != NULL) { - if (((u32 *)_sec_blob[target[0]])[1] != target[1]) { - eagle_ioctl_dbg("%s: request new size for already allocated license index %u", - __func__, target[0]); - kfree(_sec_blob[target[0]]); - _sec_blob[target[0]] = NULL; - } - } - eagle_ioctl_dbg("%s: allocating %u bytes for license index %u", - __func__, target[1], target[0]); - _sec_blob[target[0]] = kzalloc(target[1] + 4, GFP_KERNEL); - if (!_sec_blob[target[0]]) { - eagle_ioctl_err("%s: error allocating license index %u (kzalloc failed on %u bytes)", - __func__, target[0], target[1]); - return -ENOMEM; - } - ((u32 *)_sec_blob[target[0]])[0] = target[1]; - if (copy_from_user( - (void *)&(((u32 *)_sec_blob[target[0]])[1]), - (void *)(((char *)arg)+sizeof(target)), - target[1])) { - eagle_ioctl_err("%s: error copying license to index %u, size %u (src:%pK, tgt:%pK, size:%u)", - __func__, target[0], target[1], - ((char *)arg)+sizeof(target), - &(((u32 *)_sec_blob[target[0]])[1]), - target[1]); - return -EFAULT; - } else - eagle_ioctl_info("%s: license file %u bytes long copied to index license index %u", - __func__, target[1], target[0]); - break; - } - case DTS_EAGLE_IOCTL_SEND_LICENSE: { - u32 target = 0; - eagle_ioctl_dbg("%s: control 0x%X (send license)", __func__, - cmd); - if (copy_from_user((void *)&target, (void *)arg, - sizeof(target))) { - eagle_ioctl_err("%s: error reading license index (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &target, sizeof(target)); - return -EFAULT; - } - if (target >= SEC_BLOB_MAX_CNT) { - eagle_ioctl_err("%s: license index %u out of bounds (max index is %i)", - __func__, target, SEC_BLOB_MAX_CNT-1); - return -EINVAL; - } - if (!_sec_blob[target] || - ((u32 *)_sec_blob[target])[0] == 0) { - eagle_ioctl_err("%s: license index %u is invalid", - __func__, target); - return -EINVAL; - } - if (core_dts_eagle_set(((s32 *)_sec_blob[target])[0], - (char *)&((s32 *)_sec_blob[target])[1]) < 0) - eagle_ioctl_err("%s: core_dts_eagle_set failed with id = %u", - __func__, target); - else - eagle_ioctl_info("%s: core_dts_eagle_set succeeded with id = %u", - __func__, target); - break; - } - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS: { - s32 spec = 0; - eagle_ioctl_info("%s: control 0x%X (set volume commands)", - __func__, cmd); - if (copy_from_user((void *)&spec, (void *)arg, - sizeof(spec))) { - eagle_ioctl_err("%s: error reading volume command specifier (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &spec, sizeof(spec)); - return -EFAULT; - } - if (spec & 0x80000000) { - u32 idx = (spec & 0x0000F000) >> 12; - s32 size = spec & 0x00000FFF; - eagle_ioctl_dbg("%s: setting volume command %i size: %i", - __func__, idx, size); - if (idx >= _vol_cmd_cnt) { - eagle_ioctl_err("%s: volume command index %u out of bounds (only %u allocated)", - __func__, idx, _vol_cmd_cnt); - return -EINVAL; - } - if (_volume_cmds_alloc2(idx, size) < 0) { - eagle_ioctl_err("%s: error allocating memory for volume controls", - __func__); - return -ENOMEM; - } - if (copy_from_user((void *)&_vol_cmds_d[idx], - (void *)(((char *)arg) + sizeof(int)), - sizeof(struct vol_cmds_d))) { - eagle_ioctl_err("%s: error reading volume command descriptor (src:%pK, tgt:%pK, size:%zu)", - __func__, ((char *)arg) + sizeof(int), - &_vol_cmds_d[idx], - sizeof(struct vol_cmds_d)); - return -EFAULT; - } - eagle_ioctl_dbg("%s: setting volume command %i spec (size %zu): %i %i %i %i", - __func__, idx, sizeof(struct vol_cmds_d), - _vol_cmds_d[idx].d[0], _vol_cmds_d[idx].d[1], - _vol_cmds_d[idx].d[2], _vol_cmds_d[idx].d[3]); - if (copy_from_user((void *)_vol_cmds[idx], - (void *)(((char *)arg) + (sizeof(int) + - sizeof(struct vol_cmds_d))), size)) { - eagle_ioctl_err("%s: error reading volume command string (src:%pK, tgt:%pK, size:%i)", - __func__, ((char *)arg) + (sizeof(int) + - sizeof(struct vol_cmds_d)), - _vol_cmds[idx], size); - return -EFAULT; - } - } else { - eagle_ioctl_dbg("%s: setting volume command size", - __func__); - if (spec < 0 || spec > VOL_CMD_CNT_MAX) { - eagle_ioctl_err("%s: volume command count %i out of bounds (min 0, max %i)", - __func__, spec, VOL_CMD_CNT_MAX); - return -EINVAL; - } else if (spec == 0) { - eagle_ioctl_dbg("%s: request to free volume commands", - __func__); - _volume_cmds_free(); - break; - } - eagle_ioctl_dbg("%s: setting volume command size requested = %i", - __func__, spec); - if (_volume_cmds_alloc1(spec) < 0) { - eagle_ioctl_err("%s: error allocating memory for volume controls", - __func__); - return -ENOMEM; - } - } - break; - } - default: { - eagle_ioctl_err("%s: control 0x%X (invalid control)", - __func__, cmd); - ret = -EINVAL; - } - } - return (int)ret; -} - -/** - * msm_dts_eagle_compat_ioctl() - To handle 32bit to 64bit ioctl compatibility - * @cmd: cmd to handle. - * @arg: argument to the cmd. - * - * Handle DTS Eagle ioctl cmds from 32bit userspace. - * - * Return: Return failure if any. - */ -#ifdef CONFIG_COMPAT -int msm_dts_eagle_compat_ioctl(unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE32: - cmd = DTS_EAGLE_IOCTL_GET_CACHE_SIZE; - break; - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE32: - cmd = DTS_EAGLE_IOCTL_SET_CACHE_SIZE; - break; - case DTS_EAGLE_IOCTL_GET_PARAM32: - cmd = DTS_EAGLE_IOCTL_GET_PARAM; - break; - case DTS_EAGLE_IOCTL_SET_PARAM32: - cmd = DTS_EAGLE_IOCTL_SET_PARAM; - break; - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32: - cmd = DTS_EAGLE_IOCTL_SET_CACHE_BLOCK; - break; - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32: - cmd = DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE; - break; - case DTS_EAGLE_IOCTL_GET_LICENSE32: - cmd = DTS_EAGLE_IOCTL_GET_LICENSE; - break; - case DTS_EAGLE_IOCTL_SET_LICENSE32: - cmd = DTS_EAGLE_IOCTL_SET_LICENSE; - break; - case DTS_EAGLE_IOCTL_SEND_LICENSE32: - cmd = DTS_EAGLE_IOCTL_SEND_LICENSE; - break; - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32: - cmd = DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS; - break; - default: - break; - } - return msm_dts_eagle_ioctl(cmd, arg); -} -#endif -/** - * msm_dts_eagle_init_pre() - Initialize DTS premix module - * @ac: Initialize premix module in the ASM session. - * - * Initialize DTS premix module on provided ASM session - * - * Return: Return failure if any. - */ -int msm_dts_eagle_init_pre(struct audio_client *ac) -{ - return msm_dts_eagle_enable_asm(ac, _is_hpx_enabled, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); -} - -/** - * msm_dts_eagle_deinit_pre() - Deinitialize DTS premix module - * @ac: Deinitialize premix module in the ASM session. - * - * Deinitialize DTS premix module on provided ASM session - * - * Return: Currently does nothing so 0. - */ -int msm_dts_eagle_deinit_pre(struct audio_client *ac) -{ - return 0; -} - -/** - * msm_dts_eagle_init_post() - Initialize DTS postmix module - * @port_id: Port id for the ADM session. - * @copp_idx: Copp idx for the ADM session. - * - * Initialize DTS postmix module on ADM session - * - * Return: Return failure if any. - */ -int msm_dts_eagle_init_post(int port_id, int copp_idx) -{ - return msm_dts_eagle_enable_adm(port_id, copp_idx, _is_hpx_enabled); -} - -/** - * msm_dts_eagle_deinit_post() - Deinitialize DTS postmix module - * @port_id: Port id for the ADM session. - * @topology: Topology in use. - * - * Deinitialize DTS postmix module on ADM session - * - * Return: Currently does nothing so 0. - */ -int msm_dts_eagle_deinit_post(int port_id, int topology) -{ - return 0; -} - -/** - * msm_dts_eagle_init_master_module() - Initialize both DTS modules - * @ac: Initialize modules in the ASM session. - * - * Initialize DTS modules on ASM session - * - * Return: Success. - */ -int msm_dts_eagle_init_master_module(struct audio_client *ac) -{ - _set_audioclient(ac); - msm_dts_eagle_enable_asm(ac, _is_hpx_enabled, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - msm_dts_eagle_enable_asm(ac, _is_hpx_enabled, - AUDPROC_MODULE_ID_DTS_HPX_POSTMIX); - return 0; -} - -/** - * msm_dts_eagle_deinit_master_module() - Deinitialize both DTS modules - * @ac: Deinitialize modules in the ASM session. - * - * Deinitialize DTS modules on ASM session - * - * Return: Success. - */ -int msm_dts_eagle_deinit_master_module(struct audio_client *ac) -{ - msm_dts_eagle_deinit_pre(ac); - msm_dts_eagle_deinit_post(-1, 0); - _clear_audioclient(); - return 0; -} - -/** - * msm_dts_eagle_is_hpx_on() - Check if HPX effects are On - * - * Check if HPX effects are On - * - * Return: On/Off. - */ -int msm_dts_eagle_is_hpx_on(void) -{ - return _is_hpx_enabled; -} - -/** - * msm_dts_eagle_pcm_new() - Create hwdep node - * @runtime: snd_soc_pcm_runtime structure. - * - * Create hwdep node - * - * Return: Success. - */ -int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime) -{ - if (!_ref_cnt++) { - _init_cb_descs(); - _reg_ion_mem(); - } - return 0; -} - -/** - * msm_dts_eagle_pcm_free() - remove hwdep node - * @runtime: snd_soc_pcm_runtime structure. - * - * Remove hwdep node - * - * Return: void. - */ -void msm_dts_eagle_pcm_free(struct snd_pcm *pcm) -{ - if (!--_ref_cnt) - _unreg_ion_mem(); - vfree(_depc); -} - -MODULE_DESCRIPTION("DTS EAGLE platform driver"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c index 7c35d19bb610..8fc49b29000c 100644 --- a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2016-2017, 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 @@ -19,7 +20,6 @@ #include #include #include -#include #include "msm-dts-srs-tm-config.h" #include "msm-pcm-routing-v2.h" diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c index e80b6fb9cf8d..fb44bb71043b 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2017 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 @@ -14,8 +14,6 @@ #include #include #include -#include - #include "msm-pcm-routing-devdep.h" #include "msm-ds2-dap-config.h" @@ -53,23 +51,6 @@ static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER: ret = msm_ds2_dap_ioctl(hw, file, cmd, argp); break; - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE: - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE: - case DTS_EAGLE_IOCTL_GET_PARAM: - case DTS_EAGLE_IOCTL_SET_PARAM: - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK: - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE: - case DTS_EAGLE_IOCTL_GET_LICENSE: - case DTS_EAGLE_IOCTL_SET_LICENSE: - case DTS_EAGLE_IOCTL_SEND_LICENSE: - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS: - ret = msm_dts_eagle_ioctl(cmd, arg); - if (ret == -EPERM) { - pr_err("%s called with invalid control 0x%X\n", - __func__, cmd); - ret = -EINVAL; - } - break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; @@ -81,7 +62,6 @@ static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, void msm_pcm_routing_hwdep_free(struct snd_pcm *pcm) { pr_debug("%s\n", __func__); - msm_dts_eagle_pcm_free(pcm); } #ifdef CONFIG_COMPAT @@ -105,23 +85,6 @@ static int msm_pcm_routing_hwdep_compat_ioctl(struct snd_hwdep *hw, case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER32: ret = msm_ds2_dap_compat_ioctl(hw, file, cmd, argp); break; - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE32: - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE32: - case DTS_EAGLE_IOCTL_GET_PARAM32: - case DTS_EAGLE_IOCTL_SET_PARAM32: - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32: - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32: - case DTS_EAGLE_IOCTL_GET_LICENSE32: - case DTS_EAGLE_IOCTL_SET_LICENSE32: - case DTS_EAGLE_IOCTL_SEND_LICENSE32: - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32: - ret = msm_dts_eagle_compat_ioctl(cmd, arg); - if (ret == -EPERM) { - pr_err("%s called with invalid control 0x%X\n", - __func__, cmd); - ret = -EINVAL; - } - break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; @@ -167,7 +130,7 @@ int msm_pcm_routing_hwdep_new(struct snd_soc_pcm_runtime *runtime, #ifdef CONFIG_COMPAT hwdep->ops.ioctl_compat = msm_pcm_routing_hwdep_compat_ioctl; #endif - return msm_dts_eagle_pcm_new(runtime); + return rc; } #endif diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 92ea7d6f6666..abc4e5a17d14 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -155,10 +154,6 @@ static void msm_pcm_routing_cfg_pp(int port_id, int copp_idx, int topology, __func__, topology, port_id, rc); } break; - case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX: - pr_debug("%s: DTS_EAGLE_COPP_TOPOLOGY_ID\n", __func__); - msm_dts_eagle_init_post(port_id, copp_idx); - break; case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE: pr_debug("%s: TOPOLOGY_ID_AUDIOSPHERE\n", __func__); msm_qti_pp_asphere_init(port_id, copp_idx); @@ -190,10 +185,6 @@ static void msm_pcm_routing_deinit_pp(int port_id, int topology) msm_dolby_dap_deinit(port_id); } break; - case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX: - pr_debug("%s: DTS_EAGLE_COPP_TOPOLOGY_ID\n", __func__); - msm_dts_eagle_deinit_post(port_id, topology); - break; case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE: pr_debug("%s: TOPOLOGY_ID_AUDIOSPHERE\n", __func__); msm_qti_pp_asphere_deinit(port_id); @@ -6621,8 +6612,6 @@ static int msm_routing_probe(struct snd_soc_platform *platform) device_pp_params_mixer_controls, ARRAY_SIZE(device_pp_params_mixer_controls)); - msm_dts_eagle_add_controls(platform); - snd_soc_add_platform_controls(platform, msm_source_tracking_controls, ARRAY_SIZE(msm_source_tracking_controls)); diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index a9d23e75ee15..a58545fef3a8 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "msm-dts-srs-tm-config.h" #include @@ -250,222 +249,6 @@ static int adm_get_next_available_copp(int port_idx) return idx; } -int adm_dts_eagle_set(int port_id, int copp_idx, int param_id, - void *data, uint32_t size) -{ - struct adm_cmd_set_pp_params_v5 admp; - int p_idx, ret = 0, *ob_params; - - pr_debug("DTS_EAGLE_ADM: %s - port id %i, copp idx %i, param id 0x%X size %u\n", - __func__, port_id, copp_idx, param_id, size); - - port_id = afe_convert_virtual_to_portid(port_id); - p_idx = adm_validate_and_get_port_index(port_id); - pr_debug("DTS_EAGLE_ADM: %s - after lookup, port id %i, port idx %i\n", - __func__, port_id, p_idx); - - if (p_idx < 0) { - pr_err("DTS_EAGLE_ADM: %s: invalid port index 0x%x, port id 0x%x\n", - __func__, p_idx, port_id); - return -EINVAL; - } - - if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { - pr_err("DTS_EAGLE_ADM: %s: Invalid copp_idx: %d\n", __func__, - copp_idx); - return -EINVAL; - } - - ob_params = (int *)this_adm.outband_memmap.kvaddr; - if (ob_params == NULL) { - pr_err("DTS_EAGLE_ADM: %s - NULL memmap. Non Eagle topology selected?\n", - __func__); - ret = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - ret = -EINVAL; - if ((ret < 0) || - (size + APR_CMD_OB_HDR_SZ > this_adm.outband_memmap.size)) { - pr_err("DTS_EAGLE_ADM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, this_adm.outband_memmap.size, - size + APR_CMD_OB_HDR_SZ); - ret = -EINVAL; - goto fail_cmd; - } - *ob_params++ = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - *ob_params++ = param_id; - *ob_params++ = size; - memcpy(ob_params, data, size); - - admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - admp.hdr.pkt_size = sizeof(admp); - admp.hdr.src_svc = APR_SVC_ADM; - admp.hdr.src_domain = APR_DOMAIN_APPS; - admp.hdr.src_port = port_id; - admp.hdr.dest_svc = APR_SVC_ADM; - admp.hdr.dest_domain = APR_DOMAIN_ADSP; - admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]); - admp.hdr.token = p_idx << 16 | copp_idx; - admp.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5; - admp.payload_addr_lsw = lower_32_bits(this_adm.outband_memmap.paddr); - admp.payload_addr_msw = populate_upper_32_bits( - this_adm.outband_memmap.paddr); - admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[ - ADM_DTS_EAGLE]); - admp.payload_size = size + sizeof(struct adm_param_data_v5); - - pr_debug("DTS_EAGLE_ADM: %s - Command was sent now check Q6 - port id = %d, size %d, module id %x, param id %x.\n", - __func__, admp.hdr.dest_port, - admp.payload_size, AUDPROC_MODULE_ID_DTS_HPX_POSTMIX, - param_id); - atomic_set(&this_adm.copp.stat[p_idx][copp_idx], 0); - atomic_set(&this_adm.copp.cmd_err_code[p_idx][copp_idx], 0); - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp); - if (ret < 0) { - pr_err("DTS_EAGLE_ADM: %s - ADM enable for port %d failed\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } - ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx], - atomic_read(&this_adm.copp.stat[p_idx][copp_idx]), - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("DTS_EAGLE_ADM: %s - set params timed out port = %d\n", - __func__, port_id); - ret = -EINVAL; - } else if (atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]))); - ret = adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx])); - } else { - ret = 0; - } - -fail_cmd: - return ret; -} - -int adm_dts_eagle_get(int port_id, int copp_idx, int param_id, - void *data, uint32_t size) -{ - struct adm_cmd_get_pp_params_v5 admp; - int p_idx, ret = 0, *ob_params; - uint32_t orig_size = size; - pr_debug("DTS_EAGLE_ADM: %s - port id %i, copp idx %i, param id 0x%X\n", - __func__, port_id, copp_idx, param_id); - - port_id = afe_convert_virtual_to_portid(port_id); - p_idx = adm_validate_and_get_port_index(port_id); - if (p_idx < 0) { - pr_err("DTS_EAGLE_ADM: %s - invalid port index %i, port id %i, copp idx %i\n", - __func__, p_idx, port_id, copp_idx); - return -EINVAL; - } - - if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { - pr_err("DTS_EAGLE_ADM: %s: Invalid copp_idx: %d\n", __func__, - copp_idx); - return -EINVAL; - } - - if ((size == 0) || !data) { - pr_err("DTS_EAGLE_ADM: %s - invalid size %u or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - size = (size+3) & 0xFFFFFFFC; - - ob_params = (int *)(this_adm.outband_memmap.kvaddr); - if (ob_params == NULL) { - pr_err("DTS_EAGLE_ADM: %s - NULL memmap. Non Eagle topology selected?", - __func__); - ret = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - ret = -EINVAL; - if ((ret < 0) || - (size + APR_CMD_OB_HDR_SZ > this_adm.outband_memmap.size)) { - pr_err("DTS_EAGLE_ADM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, this_adm.outband_memmap.size, - size + APR_CMD_OB_HDR_SZ); - ret = -EINVAL; - goto fail_cmd; - } - *ob_params++ = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - *ob_params++ = param_id; - *ob_params++ = size; - - admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - admp.hdr.pkt_size = sizeof(admp); - admp.hdr.src_svc = APR_SVC_ADM; - admp.hdr.src_domain = APR_DOMAIN_APPS; - admp.hdr.src_port = port_id; - admp.hdr.dest_svc = APR_SVC_ADM; - admp.hdr.dest_domain = APR_DOMAIN_ADSP; - admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]); - admp.hdr.token = p_idx << 16 | copp_idx; - admp.hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5; - admp.data_payload_addr_lsw = - lower_32_bits(this_adm.outband_memmap.paddr); - admp.data_payload_addr_msw = - populate_upper_32_bits( - this_adm.outband_memmap.paddr); - admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[ - ADM_DTS_EAGLE]); - admp.module_id = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - admp.param_id = param_id; - admp.param_max_size = size + sizeof(struct adm_param_data_v5); - admp.reserved = 0; - - atomic_set(&this_adm.copp.stat[p_idx][copp_idx], 0); - atomic_set(&this_adm.copp.cmd_err_code[p_idx][copp_idx], 0); - - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp); - if (ret < 0) { - pr_err("DTS_EAGLE_ADM: %s - Failed to get EAGLE Params on port %d\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } - ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx], - atomic_read(&this_adm.copp.stat[p_idx][copp_idx]), - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("DTS_EAGLE_ADM: %s - EAGLE get params timed out port = %d\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } else if (atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]))); - ret = adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx])); - goto fail_cmd; - } - - memcpy(data, ob_params, orig_size); - ret = 0; -fail_cmd: - return ret; -} - int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id, void *srs_params) { @@ -2265,13 +2048,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, __func__, port_id, path, rate, channel_mode, perf_mode, topology); - /* For DTS EAGLE only, force 24 bit */ - if ((topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) && - (perf_mode == LEGACY_PCM_MODE)) { - bit_width = 24; - pr_debug("%s: Force open adm in 24-bit for DTS HPX topology 0x%x\n", - __func__, topology); - } port_id = q6audio_convert_virtual_to_portid(port_id); port_idx = adm_validate_and_get_port_index(port_id); if (port_idx < 0) { @@ -2298,8 +2074,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, flags = ADM_LOW_LATENCY_DEVICE_SESSION; if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) || (topology == DS2_ADM_COPP_TOPOLOGY_ID) || - (topology == SRS_TRUMEDIA_TOPOLOGY_ID) || - (topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX)) + (topology == SRS_TRUMEDIA_TOPOLOGY_ID)) topology = DEFAULT_COPP_TOPOLOGY; } else { if (path == ADM_PATH_COMPRESSED_RX) @@ -2367,20 +2142,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, (uint32_t)this_adm.outband_memmap.size); } } - if ((topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) && - (perf_mode == LEGACY_PCM_MODE)) { - int res = 0; - atomic_set(&this_adm.mem_map_index, ADM_DTS_EAGLE); - msm_dts_ion_memmap(&this_adm.outband_memmap); - res = adm_memory_map_regions( - &this_adm.outband_memmap.paddr, - 0, - (uint32_t *)&this_adm.outband_memmap.size, - 1); - if (res < 0) - pr_err("%s: DTS_EAGLE mmap did not work!", - __func__); - } open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); @@ -2660,21 +2421,6 @@ int adm_close(int port_id, int perf_mode, int copp_idx) } } - if ((perf_mode == LEGACY_PCM_MODE) && - (this_adm.outband_memmap.paddr != 0) && - (atomic_read( - &this_adm.copp.topology[port_idx][copp_idx]) == - ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX)) { - atomic_set(&this_adm.mem_map_index, ADM_DTS_EAGLE); - ret = adm_memory_unmap_regions(); - if (ret < 0) { - pr_err("%s: adm mem unmmap err %d", - __func__, ret); - } else { - atomic_set(&this_adm.mem_map_handles - [ADM_DTS_EAGLE], 0); - } - } if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) && (this_adm.sourceTrackingData.memmap.paddr != 0)) { @@ -3061,10 +2807,6 @@ static int adm_init_cal_data(void) {NULL, NULL, NULL, NULL, NULL, NULL} }, {NULL, NULL, cal_utils_match_buf_num} }, - {{DTS_EAGLE_CAL_TYPE, - {NULL, NULL, NULL, NULL, NULL, NULL} }, - {NULL, NULL, cal_utils_match_buf_num} }, - {{SRS_TRUMEDIA_CAL_TYPE, {NULL, NULL, NULL, NULL, NULL, NULL} }, {NULL, NULL, cal_utils_match_buf_num} } diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 7246c944c8a5..d7fb514f309f 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Author: Brian Swetland * * This software is licensed under the terms of the GNU General Public @@ -41,8 +41,8 @@ #include #include #include -#include #include +#include #define TRUE 0x01 #define FALSE 0x00 @@ -2147,9 +2147,6 @@ static int __q6asm_open_read(struct audio_client *ac, open.src_endpointype = ASM_END_POINT_DEVICE_MATRIX; open.preprocopo_id = q6asm_get_asm_topology(); - if ((open.preprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.preprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS)) - open.preprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE; open.bits_per_sample = bits_per_sample; open.mode_flags = 0x0; @@ -2387,16 +2384,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, open.bits_per_sample = bits_per_sample; open.postprocopo_id = q6asm_get_asm_topology(); - if ((ac->perf_mode != LEGACY_PCM_MODE) && - ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS))) + if (ac->perf_mode != LEGACY_PCM_MODE) open.postprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE; - /* For DTS EAGLE only, force 24 bit */ - if ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS)) - open.bits_per_sample = 24; - pr_debug("%s: perf_mode %d asm_topology 0x%x bps %d\n", __func__, ac->perf_mode, open.postprocopo_id, open.bits_per_sample); @@ -2596,10 +2586,6 @@ static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format, topology : open.postprocopo_id; ac->topology = open.postprocopo_id; - /* For DTS EAGLE only, force 24 bit */ - if ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER)) - open.bits_per_sample = 24; switch (wr_format) { case FORMAT_LINEAR_PCM: @@ -5499,215 +5485,6 @@ fail_cmd: return rc; } -int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size, - void *data, struct param_outband *po, int m_id) -{ - int rc = 0, *ob_params = NULL; - uint32_t sz = sizeof(struct asm_dts_eagle_param) + (po ? 0 : size); - struct asm_dts_eagle_param *ad; - - if (!ac || ac->apr == NULL || (size == 0) || !data) { - pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - ad = kzalloc(sz, GFP_KERNEL); - if (!ad) { - pr_err("DTS_EAGLE_ASM - %s: error allocating mem of size %u\n", - __func__, sz); - return -ENOMEM; - } - pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", - __func__, ac, param_id, size, data, m_id); - q6asm_add_hdr_async(ac, &ad->hdr, sz, 1); - ad->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; - ad->param.data_payload_addr_lsw = 0; - ad->param.data_payload_addr_msw = 0; - - ad->param.mem_map_handle = 0; - ad->param.data_payload_size = size + - sizeof(struct asm_stream_param_data_v2); - ad->data.module_id = m_id; - ad->data.param_id = param_id; - ad->data.param_size = size; - ad->data.reserved = 0; - atomic_set(&ac->cmd_state, 1); - - if (po) { - struct list_head *ptr, *next; - struct asm_buffer_node *node; - pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", - __func__, po->kvaddr, &po->paddr); - ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); - ad->param.data_payload_addr_msw = populate_upper_32_bits( - po->paddr); - list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { - node = list_entry(ptr, struct asm_buffer_node, list); - if (node->buf_phys_addr == po->paddr) { - ad->param.mem_map_handle = node->mmap_hdl; - break; - } - } - if (ad->param.mem_map_handle == 0) { - pr_err("DTS_EAGLE_ASM - %s: mem map handle not found\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - rc = -EINVAL; - if ((rc < 0) || (size + APR_CMD_OB_HDR_SZ > po->size)) { - pr_err("DTS_EAGLE_ASM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, po->size, size + APR_CMD_OB_HDR_SZ); - rc = -EINVAL; - goto fail_cmd; - } - ob_params = (int *)po->kvaddr; - *ob_params++ = m_id; - *ob_params++ = param_id; - *ob_params++ = size; - memcpy(ob_params, data, size); - } else { - pr_debug("DTS_EAGLE_ASM - %s: using in band\n", __func__); - memcpy(((char *)ad) + sizeof(struct asm_dts_eagle_param), - data, size); - } - rc = apr_send_pkt(ac->apr, (uint32_t *)ad); - if (rc < 0) { - pr_err("DTS_EAGLE_ASM - %s: set-params send failed paramid[0x%x]\n", - __func__, ad->data.param_id); - rc = -EINVAL; - goto fail_cmd; - } - - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) <= 0), 1*HZ); - if (!rc) { - pr_err("DTS_EAGLE_ASM - %s: timeout, set-params paramid[0x%x]\n", - __func__, ad->data.param_id); - rc = -EINVAL; - goto fail_cmd; - } - rc = 0; -fail_cmd: - kfree(ad); - return rc; -} - -int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size, - void *data, struct param_outband *po, int m_id) -{ - struct asm_dts_eagle_param_get *ad; - int rc = 0, *ob_params = NULL; - uint32_t sz = sizeof(struct asm_dts_eagle_param) + APR_CMD_GET_HDR_SZ + - (po ? 0 : size); - - if (!ac || ac->apr == NULL || (size == 0) || !data) { - pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK\n", - __func__, size, data); - return -EINVAL; - } - ad = kzalloc(sz, GFP_KERNEL); - if (!ad) { - pr_err("DTS_EAGLE_ASM - %s: error allocating memory of size %u\n", - __func__, sz); - return -ENOMEM; - } - pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", - __func__, ac, param_id, size, data, m_id); - q6asm_add_hdr(ac, &ad->hdr, sz, TRUE); - ad->hdr.opcode = ASM_STREAM_CMD_GET_PP_PARAMS_V2; - ad->param.data_payload_addr_lsw = 0; - ad->param.data_payload_addr_msw = 0; - ad->param.mem_map_handle = 0; - ad->param.module_id = m_id; - ad->param.param_id = param_id; - ad->param.param_max_size = size + APR_CMD_GET_HDR_SZ; - ad->param.reserved = 0; - atomic_set(&ac->cmd_state, 1); - - generic_get_data = kzalloc(size + sizeof(struct generic_get_data_), - GFP_KERNEL); - if (!generic_get_data) { - pr_err("DTS_EAGLE_ASM - %s: error allocating mem of size %u\n", - __func__, size); - rc = -ENOMEM; - goto fail_cmd; - } - - if (po) { - struct list_head *ptr, *next; - struct asm_buffer_node *node; - pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", - __func__, po->kvaddr, &po->paddr); - ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); - ad->param.data_payload_addr_msw = populate_upper_32_bits( - po->paddr); - list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { - node = list_entry(ptr, struct asm_buffer_node, list); - if (node->buf_phys_addr == po->paddr) { - ad->param.mem_map_handle = node->mmap_hdl; - break; - } - } - if (ad->param.mem_map_handle == 0) { - pr_err("DTS_EAGLE_ASM - %s: mem map handle not found\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - rc = -EINVAL; - if ((rc < 0) || (size + APR_CMD_OB_HDR_SZ > po->size)) { - pr_err("DTS_EAGLE_ASM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, po->size, size + APR_CMD_OB_HDR_SZ); - rc = -EINVAL; - goto fail_cmd; - } - ob_params = (int *)po->kvaddr; - *ob_params++ = m_id; - *ob_params++ = param_id; - *ob_params++ = size; - generic_get_data->is_inband = 0; - } else { - pr_debug("DTS_EAGLE_ASM - %s: using in band\n", __func__); - generic_get_data->is_inband = 1; - } - - rc = apr_send_pkt(ac->apr, (uint32_t *)ad); - if (rc < 0) { - pr_err("DTS_EAGLE_ASM - %s: Commmand 0x%x failed\n", __func__, - ad->hdr.opcode); - goto fail_cmd; - } - - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) <= 0), 1*HZ); - if (!rc) { - pr_err("DTS_EAGLE_ASM - %s: timeout in get\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - - if (generic_get_data->valid) { - rc = 0; - memcpy(data, po ? ob_params : generic_get_data->ints, size); - } else { - rc = -EINVAL; - pr_err("DTS_EAGLE_ASM - %s: EAGLE get params problem getting data - check callback error value\n", - __func__); - } -fail_cmd: - kfree(ad); - kfree(generic_get_data); - generic_get_data = NULL; - return rc; -} - static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance) { struct asm_volume_ctrl_master_gain vol; diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c index c149c0257a18..4948bef90c95 100644 --- a/sound/soc/msm/qdsp6v2/q6core.c +++ b/sound/soc/msm/qdsp6v2/q6core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -187,7 +187,7 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) generic_get_data->valid = 1; generic_get_data->size_in_ints = data->payload_size/sizeof(int); - pr_debug("DTS_EAGLE_CORE callback size = %i\n", + pr_debug("callback size = %i\n", data->payload_size); memcpy(generic_get_data->ints, data->payload, data->payload_size); @@ -420,115 +420,6 @@ fail_cmd: return ret; } -int core_dts_eagle_set(int size, char *data) -{ - struct adsp_dts_eagle *payload = NULL; - int rc = 0, size_aligned4byte; - - pr_debug("DTS_EAGLE_CORE - %s\n", __func__); - if (size <= 0 || !data) { - pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - size_aligned4byte = (size+3) & 0xFFFFFFFC; - ocm_core_open(); - if (q6core_lcl.core_handle_q) { - payload = kzalloc(sizeof(struct adsp_dts_eagle) + - size_aligned4byte, GFP_KERNEL); - if (!payload) { - pr_err("DTS_EAGLE_CORE - %s: out of memory (aligned size %i).\n", - __func__, size_aligned4byte); - return -ENOMEM; - } - payload->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT, - APR_HDR_LEN(APR_HDR_SIZE), - APR_PKT_VER); - payload->hdr.pkt_size = sizeof(struct adsp_dts_eagle) + - size_aligned4byte; - payload->hdr.src_port = 0; - payload->hdr.dest_port = 0; - payload->hdr.token = 0; - payload->hdr.opcode = ADSP_CMD_SET_DTS_EAGLE_DATA_ID; - payload->id = DTS_EAGLE_LICENSE_ID; - payload->overwrite = 1; - payload->size = size; - memcpy(payload->data, data, size); - rc = apr_send_pkt(q6core_lcl.core_handle_q, - (uint32_t *)payload); - if (rc < 0) { - pr_err("DTS_EAGLE_CORE - %s: failed op[0x%x]rc[%d]\n", - __func__, payload->hdr.opcode, rc); - } - kfree(payload); - } - return rc; -} - -int core_dts_eagle_get(int id, int size, char *data) -{ - struct apr_hdr ah; - int rc = 0; - - pr_debug("DTS_EAGLE_CORE - %s\n", __func__); - if (size <= 0 || !data) { - pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - ocm_core_open(); - if (q6core_lcl.core_handle_q) { - ah.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - ah.pkt_size = sizeof(struct apr_hdr); - ah.src_port = 0; - ah.dest_port = 0; - ah.token = 0; - ah.opcode = id; - - q6core_lcl.bus_bw_resp_received = 0; - generic_get_data = kzalloc(sizeof(struct generic_get_data_) - + size, GFP_KERNEL); - if (!generic_get_data) { - pr_err("DTS_EAGLE_CORE - %s: error allocating memory of size %i\n", - __func__, size); - return -ENOMEM; - } - - rc = apr_send_pkt(q6core_lcl.core_handle_q, - (uint32_t *)&ah); - if (rc < 0) { - pr_err("DTS_EAGLE_CORE - %s: failed op[0x%x]rc[%d]\n", - __func__, ah.opcode, rc); - goto fail_cmd_2; - } - - rc = wait_event_timeout(q6core_lcl.bus_bw_req_wait, - (q6core_lcl.bus_bw_resp_received == 1), - msecs_to_jiffies(TIMEOUT_MS)); - if (!rc) { - pr_err("DTS_EAGLE_CORE - %s: EAGLE get params timed out\n", - __func__); - rc = -EINVAL; - goto fail_cmd_2; - } - if (generic_get_data->valid) { - rc = 0; - memcpy(data, generic_get_data->ints, size); - } else { - rc = -EINVAL; - pr_err("DTS_EAGLE_CORE - %s: EAGLE get params problem getting data - check callback error value\n", - __func__); - } - } - -fail_cmd_2: - kfree(generic_get_data); - generic_get_data = NULL; - return rc; -} - uint32_t core_set_dolby_manufacturer_id(int manufacturer_id) { struct adsp_dolby_manufacturer_id payload; From c40969772e4c111cf992a734e510ea54a18308f5 Mon Sep 17 00:00:00 2001 From: Prasad Malisetty Date: Tue, 11 Apr 2017 23:03:43 +0530 Subject: [PATCH 179/210] mhi: core: remove unused dbgfs function Remove unused debug function that trigger MSI Change-Id: Ib747e579c732ece892f8695f2fdfbf107012c9c8 CRs-Fixed: 1116611 Signed-off-by: Prasad Malisetty --- drivers/platform/msm/mhi/mhi_sys.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index d57ac8c0e211..9603b6a91dbc 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -188,22 +188,6 @@ static const struct file_operations mhi_dbgfs_ev_fops = { .write = NULL, }; -static ssize_t mhi_dbgfs_trigger_msi(struct file *fp, const char __user *buf, - size_t count, loff_t *offp) -{ - u32 msi_nr = 0; - void *irq_ctxt = &((mhi_devices.device_list[0]).pcie_device->dev); - if (copy_from_user(&msi_nr, buf, sizeof(msi_nr))) - return -ENOMEM; - mhi_msi_handlr(msi_nr, irq_ctxt); - return 0; -} - -static const struct file_operations mhi_dbgfs_trigger_msi_fops = { - .read = NULL, - .write = mhi_dbgfs_trigger_msi, -}; - static ssize_t mhi_dbgfs_state_read(struct file *fp, char __user *buf, size_t count, loff_t *offp) { @@ -303,7 +287,6 @@ int mhi_init_debugfs(struct mhi_device_ctxt *mhi_dev_ctxt) { struct dentry *mhi_chan_stats; struct dentry *mhi_state_stats; - struct dentry *mhi_msi_trigger; struct dentry *mhi_ev_stats; mhi_dev_ctxt->mhi_parent_folder = debugfs_create_dir("mhi", NULL); @@ -332,21 +315,12 @@ int mhi_init_debugfs(struct mhi_device_ctxt *mhi_dev_ctxt) &mhi_dbgfs_state_fops); if (mhi_state_stats == NULL) goto clean_ev_stats; - mhi_msi_trigger = debugfs_create_file("mhi_msi_trigger", - 0444, - mhi_dev_ctxt->mhi_parent_folder, - mhi_dev_ctxt, - &mhi_dbgfs_trigger_msi_fops); - if (mhi_msi_trigger == NULL) - goto clean_state; mhi_dev_ctxt->chan_info = kmalloc(MHI_LOG_SIZE, GFP_KERNEL); if (mhi_dev_ctxt->chan_info == NULL) goto clean_all; return 0; clean_all: - debugfs_remove(mhi_msi_trigger); -clean_state: debugfs_remove(mhi_state_stats); clean_ev_stats: debugfs_remove(mhi_ev_stats); From 34309b0fc4770c071fda494f424cdc6eef7cca42 Mon Sep 17 00:00:00 2001 From: Dilip Kota Date: Mon, 21 Mar 2016 11:28:51 +0530 Subject: [PATCH 180/210] slim-msm: Synchronize SSR callbacks Subsystem will restart within short timeframe. Synchronise subsytem up/down callback notifications to avoid functionality failures. Use mutex locks to achieve synchronization. Change-Id: I5881c7d468507bb8402a2e9f8178b9c31e57e8a5 Signed-off-by: Dilip Kota --- drivers/slimbus/slim-msm-ngd.c | 5 +++++ drivers/slimbus/slim-msm.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index 5c2c9a6e4ee4..8c3a184b6649 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -1446,11 +1446,13 @@ static void ngd_adsp_down(struct msm_slim_ctrl *dev) struct slim_controller *ctrl = &dev->ctrl; struct slim_device *sbdev; + mutex_lock(&dev->ssr_lock); ngd_slim_enable(dev, false); /* device up should be called again after SSR */ list_for_each_entry(sbdev, &ctrl->devs, dev_list) slim_report_absent(sbdev); SLIM_INFO(dev, "SLIM ADSP SSR (DOWN) done\n"); + mutex_unlock(&dev->ssr_lock); } static void ngd_adsp_up(struct work_struct *work) @@ -1459,7 +1461,9 @@ static void ngd_adsp_up(struct work_struct *work) container_of(work, struct msm_slim_qmi, ssr_up); struct msm_slim_ctrl *dev = container_of(qmi, struct msm_slim_ctrl, qmi); + mutex_lock(&dev->ssr_lock); ngd_slim_enable(dev, true); + mutex_unlock(&dev->ssr_lock); } static ssize_t show_mask(struct device *device, struct device_attribute *attr, @@ -1623,6 +1627,7 @@ static int ngd_slim_probe(struct platform_device *pdev) init_completion(&dev->reconf); init_completion(&dev->ctrl_up); mutex_init(&dev->tx_lock); + mutex_init(&dev->ssr_lock); spin_lock_init(&dev->tx_buf_lock); spin_lock_init(&dev->rx_lock); dev->ee = 1; diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h index dbb125dc9a62..0b4c4d33f79a 100644 --- a/drivers/slimbus/slim-msm.h +++ b/drivers/slimbus/slim-msm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -284,6 +284,7 @@ struct msm_slim_ctrl { struct clk *rclk; struct clk *hclk; struct mutex tx_lock; + struct mutex ssr_lock; spinlock_t tx_buf_lock; u8 pgdla; enum msm_slim_msgq use_rx_msgqs; From 88436891728a473872da930126d4d259d4a39d4b Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 181/210] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; From 9f90f7549a36101d2094c12d8e3af9ad41f958ec Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Thu, 20 Apr 2017 12:36:10 +0530 Subject: [PATCH 182/210] msm: kgsl: Fix kgsl memory allocation and free race condition When allocating userspace memory keep reference to memory allocation till it is completely initialized and info is sent back to userspace. Change-Id: Id72c82bf98c094ecbd4722813c732a998dcbb188 Signed-off-by: Tarun Karra Signed-off-by: Sunil Khatri --- drivers/gpu/msm/kgsl.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index a76750605ee1..91cf080dcfa6 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2017, 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 @@ -230,8 +230,11 @@ kgsl_mem_entry_create(void) { struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry) + if (entry) { kref_init(&entry->refcount); + /* put this ref in the caller functions after init */ + kref_get(&entry->refcount); + } return entry; } @@ -2421,6 +2424,9 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, trace_kgsl_mem_map(entry, fd); kgsl_mem_entry_commit_process(private, entry); + + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return 0; unmap: @@ -2693,6 +2699,9 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, trace_kgsl_mem_map(entry, param->fd); kgsl_mem_entry_commit_process(private, entry); + + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return result; error_attach: @@ -3133,6 +3142,9 @@ long kgsl_ioctl_gpuobj_alloc(struct kgsl_device_private *dev_priv, param->mmapsize = kgsl_memdesc_mmapsize(&entry->memdesc); param->id = entry->id; + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); + return 0; } @@ -3156,6 +3168,8 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, param->size = (size_t) entry->memdesc.size; param->flags = (unsigned int) entry->memdesc.flags; + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return 0; } @@ -3179,6 +3193,8 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, kgsl_memdesc_mmapsize(&entry->memdesc); param->gpuaddr = (unsigned long) entry->memdesc.gpuaddr; + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return 0; } From 191fd832a12364a164df1204c61b782a3eb81444 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Sat, 25 Mar 2017 17:36:30 +0530 Subject: [PATCH 183/210] soc: qcom: pil: Explicitly clear the subsystem loading address Explicitly clear the subsystem loading address in case of any memory failure. It will help to avoid any platform dependency. Change-Id: I3be8f6318d68f02c02e637fc34f4a868e9fafa45 Signed-off-by: Gaurav Kohli Signed-off-by: Srinivasarao P --- drivers/soc/qcom/peripheral-loader.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index c8b1b8307516..12d329e37bd9 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -382,6 +382,8 @@ static int pil_alloc_region(struct pil_priv *priv, phys_addr_t min_addr, if (region == NULL) { pil_err(priv->desc, "Failed to allocate relocatable region of size %zx\n", size); + priv->region_start = 0; + priv->region_end = 0; return -ENOMEM; } From caa0f24dcf4bbb36a82e4aa0431ac1643331043b Mon Sep 17 00:00:00 2001 From: Vasantha Balla Date: Tue, 28 Mar 2017 16:04:06 +0530 Subject: [PATCH 184/210] msm-vidc: Allocate bus vote data during initialization Dynamic reallocation of vote_data memory can cause double free problem if multiple instances try to reallocate simultaneously. So allocate this memory statically. Change-Id: Ib5ff08c600a4b69a38b519688bbc153de9f50090 Signed-off-by: Vasantha Balla --- .../platform/msm/vidc/msm_vidc_internal.h | 1 + drivers/media/platform/msm/vidc/venus_hfi.c | 25 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index b7095df13ec3..3c4eda615181 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -43,6 +43,7 @@ #define DEFAULT_WIDTH 1920 #define MIN_SUPPORTED_WIDTH 32 #define MIN_SUPPORTED_HEIGHT 32 +#define MAX_SUPPORTED_INSTANCES_COUNT 13 /* Maintains the number of FTB's between each FBD over a window */ #define DCVS_FTB_WINDOW 32 diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 7b6dc0974f26..751b20ec3dd3 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -933,15 +933,12 @@ static int venus_hfi_vote_active_buses(void *dev, return -EINVAL; } - /* (Re-)alloc memory to store the new votes (in case we internally - * re-vote after power collapse, which is transparent to client) */ - cached_vote_data = krealloc(device->bus_load.vote_data, num_data * - sizeof(*cached_vote_data), GFP_KERNEL); - if (!cached_vote_data) { - dprintk(VIDC_ERR, "Can't alloc memory to cache bus votes\n"); - rc = -ENOMEM; - goto err_no_mem; - } + cached_vote_data = device->bus_load.vote_data; + if (!cached_vote_data) { + dprintk(VIDC_ERR,"Invalid bus load vote data\n"); + rc = -ENOMEM; + goto err_no_mem; + } /* Alloc & init the load table */ num_bus = device->res->bus_set.count; @@ -4135,9 +4132,15 @@ static int venus_hfi_init_bus(struct venus_hfi_device *device) dprintk(VIDC_DBG, "Registered bus client %s\n", name); } - device->bus_load.vote_data = NULL; - device->bus_load.vote_data_count = 0; + device->bus_load.vote_data = (struct vidc_bus_vote_data *) + kzalloc(sizeof(struct vidc_bus_vote_data)*MAX_SUPPORTED_INSTANCES_COUNT, GFP_KERNEL); + if (device->bus_load.vote_data == NULL) { + dprintk(VIDC_ERR,"Failed to allocate memory for vote_data\n"); + rc = -ENOMEM; + goto err_init_bus; + } + device->bus_load.vote_data_count = 0; return rc; err_init_bus: venus_hfi_deinit_bus(device); From 5eeb6039039786292e57992d642d09983af574b5 Mon Sep 17 00:00:00 2001 From: Divya Ojha Date: Thu, 30 Mar 2017 10:25:15 +0530 Subject: [PATCH 185/210] drivers: qcom: ultrasound: check concurrent device open operations Make opened device count atomic variable to avoid probable race condition. Race condition leads to memory leak and list corruption. Change-Id: I4da98f27d36f616bc8fa7b1a848c20cc7eea04e5 Signed-off-by: Divya Ojha --- drivers/misc/qcom/qdsp6v2/ultrasound/usf.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c index 9270dbcbb1e9..454d11a5b177 100644 --- a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +++ b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, 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 @@ -172,7 +172,7 @@ static const int s_button_map[] = { }; /* The opened devices container */ -static int s_opened_devs[MAX_DEVS_NUMBER]; +static atomic_t s_opened_devs[MAX_DEVS_NUMBER]; #define USF_NAME_PREFIX "usf_" #define USF_NAME_PREFIX_SIZE 4 @@ -2297,14 +2297,11 @@ static uint16_t add_opened_dev(int minor) uint16_t ind = 0; for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) { - if (minor == s_opened_devs[ind]) { + if (minor == atomic_cmpxchg(&s_opened_devs[ind], 0, minor)) { pr_err("%s: device %d is already opened\n", __func__, minor); return USF_UNDEF_DEV_ID; - } - - if (s_opened_devs[ind] == 0) { - s_opened_devs[ind] = minor; + } else { pr_debug("%s: device %d is added; ind=%d\n", __func__, minor, ind); return ind; @@ -2359,7 +2356,7 @@ static int usf_release(struct inode *inode, struct file *file) usf_disable(&usf->usf_tx); usf_disable(&usf->usf_rx); - s_opened_devs[usf->dev_ind] = 0; + atomic_set(&s_opened_devs[usf->dev_ind], 0); mutex_unlock(&usf->mutex); mutex_destroy(&usf->mutex); From feec8bca7de9ba2ca3c3a90beeeee586ebb1a80a Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena Date: Mon, 3 Apr 2017 13:21:58 +0530 Subject: [PATCH 186/210] msm: ipa: Fix memory leak in ipa driver Free the memory pointed by msg pointer if copy_to_user fails. Change-Id: I628e089d844a3e1818a1a550e77ac10f33640ac9 Acked-by: Mohammed Javid Signed-off-by: Utkarsh Saxena --- drivers/platform/msm/ipa/ipa_intf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_intf.c b/drivers/platform/msm/ipa/ipa_intf.c index 18924a773d05..8eb96763be92 100644 --- a/drivers/platform/msm/ipa/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_intf.c @@ -553,6 +553,8 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count, mutex_unlock(&ipa_ctx->msg_lock); if (copy_to_user(buf, &msg->meta, sizeof(struct ipa_msg_meta))) { + kfree(msg); + msg = NULL; ret = -EFAULT; break; } @@ -561,6 +563,8 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count, if (msg->buff) { if (copy_to_user(buf, msg->buff, msg->meta.msg_len)) { + kfree(msg); + msg = NULL; ret = -EFAULT; break; } From 2a2f0b7463f4de9ca225769204ff62c71760709c Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Thu, 6 Apr 2017 16:15:48 -0700 Subject: [PATCH 187/210] ashmem: remove cache maintenance support The cache maintenance routines in ashmem were causing several security issues. Since they are not being used anymore by any drivers, its well to remove them entirely. CRs-Fixed: 1107034, 2001129, 2007786 Change-Id: I955e33d90b888d58db5cf6bb490905283374425b Signed-off-by: Sudarshan Rajagopalan --- drivers/staging/android/ashmem.c | 41 -------------------------------- include/uapi/linux/ashmem.h | 3 --- 2 files changed, 44 deletions(-) diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index ee79ac8d90d6..f13aab21da4a 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -32,7 +32,6 @@ #include #include #include -#include #include "ashmem.h" @@ -659,37 +658,6 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd, return ret; } -static int ashmem_cache_op(struct ashmem_area *asma, - void (*cache_func)(const void *vstart, const void *vend)) -{ - int ret = 0; - struct vm_area_struct *vma; - if (!asma->vm_start) - return -EINVAL; - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, asma->vm_start); - if (!vma) { - ret = -EINVAL; - goto done; - } - if (vma->vm_file != asma->file) { - ret = -EINVAL; - goto done; - } - if ((asma->vm_start + asma->size) > vma->vm_end) { - ret = -EINVAL; - goto done; - } - cache_func((void *)asma->vm_start, - (void *)(asma->vm_start + asma->size)); -done: - up_read(¤t->mm->mmap_sem); - if (ret) - asma->vm_start = 0; - return ret; -} - static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ashmem_area *asma = file->private_data; @@ -735,15 +703,6 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ashmem_shrink(&ashmem_shrinker, &sc); } break; - case ASHMEM_CACHE_FLUSH_RANGE: - ret = ashmem_cache_op(asma, &dmac_flush_range); - break; - case ASHMEM_CACHE_CLEAN_RANGE: - ret = ashmem_cache_op(asma, &dmac_clean_range); - break; - case ASHMEM_CACHE_INV_RANGE: - ret = ashmem_cache_op(asma, &dmac_inv_range); - break; } return ret; diff --git a/include/uapi/linux/ashmem.h b/include/uapi/linux/ashmem.h index 7ec977f432a6..7797439756c1 100644 --- a/include/uapi/linux/ashmem.h +++ b/include/uapi/linux/ashmem.h @@ -34,8 +34,5 @@ struct ashmem_pin { #define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin) #define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9) #define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10) -#define ASHMEM_CACHE_FLUSH_RANGE _IO(__ASHMEMIOC, 11) -#define ASHMEM_CACHE_CLEAN_RANGE _IO(__ASHMEMIOC, 12) -#define ASHMEM_CACHE_INV_RANGE _IO(__ASHMEMIOC, 13) #endif /* _UAPI_LINUX_ASHMEM_H */ From 9e07fc42423b15a9e1b58fa930958d7d8e98f884 Mon Sep 17 00:00:00 2001 From: AnilKumar Chimata Date: Mon, 13 Mar 2017 16:13:47 +0530 Subject: [PATCH 188/210] crypto: msm: Fix buffer overflow issue In multi-threaded environment diglen variable could be modified by multiple threads at the same time. Buffer overflow might happen in current thread if another thread changes the diglen variable. So add mutex locks to avoid this issue. Change-Id: I62c63c55c028dedb1dd0eec862851bd8e818a5d3 Signed-off-by: AnilKumar Chimata --- drivers/crypto/msm/qcedev.c | 51 +++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 2ccb7bab6994..8cf19a4b3cdc 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -77,6 +77,7 @@ static uint8_t _std_init_vector_sha256_uint8[] = { static DEFINE_MUTEX(send_cmd_lock); static DEFINE_MUTEX(qcedev_sent_bw_req); +static DEFINE_MUTEX(hash_access_lock); static void qcedev_ce_high_bw_req(struct qcedev_control *podev, bool high_bw_req) @@ -1665,12 +1666,18 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) (void __user *)arg, sizeof(struct qcedev_sha_op_req))) return -EFAULT; - if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) + mutex_lock(&hash_access_lock); + if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) { + mutex_unlock(&hash_access_lock); return -EINVAL; + } qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA; err = qcedev_hash_init(&qcedev_areq, handle, &sg_src); - if (err) + if (err) { + mutex_unlock(&hash_access_lock); return err; + } + mutex_unlock(&hash_access_lock); if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, sizeof(struct qcedev_sha_op_req))) return -EFAULT; @@ -1688,32 +1695,42 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) (void __user *)arg, sizeof(struct qcedev_sha_op_req))) return -EFAULT; - if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) + mutex_lock(&hash_access_lock); + if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) { + mutex_unlock(&hash_access_lock); return -EINVAL; + } qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA; if (qcedev_areq.sha_op_req.alg == QCEDEV_ALG_AES_CMAC) { err = qcedev_hash_cmac(&qcedev_areq, handle, &sg_src); - if (err) + if (err) { + mutex_unlock(&hash_access_lock); return err; + } } else { if (handle->sha_ctxt.init_done == false) { pr_err("%s Init was not called\n", __func__); + mutex_unlock(&hash_access_lock); return -EINVAL; } err = qcedev_hash_update(&qcedev_areq, handle, &sg_src); - if (err) + if (err) { + mutex_unlock(&hash_access_lock); return err; + } } if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) { pr_err("Invalid sha_ctxt.diglen %d\n", handle->sha_ctxt.diglen); + mutex_unlock(&hash_access_lock); return -EINVAL; } memcpy(&qcedev_areq.sha_op_req.digest[0], &handle->sha_ctxt.digest[0], handle->sha_ctxt.diglen); + mutex_unlock(&hash_access_lock); if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, sizeof(struct qcedev_sha_op_req))) return -EFAULT; @@ -1730,16 +1747,22 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) (void __user *)arg, sizeof(struct qcedev_sha_op_req))) return -EFAULT; - if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) + mutex_lock(&hash_access_lock); + if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) { + mutex_unlock(&hash_access_lock); return -EINVAL; + } qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA; err = qcedev_hash_final(&qcedev_areq, handle); - if (err) + if (err) { + mutex_unlock(&hash_access_lock); return err; + } qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen; memcpy(&qcedev_areq.sha_op_req.digest[0], &handle->sha_ctxt.digest[0], handle->sha_ctxt.diglen); + mutex_unlock(&hash_access_lock); if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, sizeof(struct qcedev_sha_op_req))) return -EFAULT; @@ -1754,20 +1777,28 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) (void __user *)arg, sizeof(struct qcedev_sha_op_req))) return -EFAULT; - if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) + mutex_lock(&hash_access_lock); + if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) { + mutex_unlock(&hash_access_lock); return -EINVAL; + } qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA; qcedev_hash_init(&qcedev_areq, handle, &sg_src); err = qcedev_hash_update(&qcedev_areq, handle, &sg_src); - if (err) + if (err) { + mutex_unlock(&hash_access_lock); return err; + } err = qcedev_hash_final(&qcedev_areq, handle); - if (err) + if (err) { + mutex_unlock(&hash_access_lock); return err; + } qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen; memcpy(&qcedev_areq.sha_op_req.digest[0], &handle->sha_ctxt.digest[0], handle->sha_ctxt.diglen); + mutex_unlock(&hash_access_lock); if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, sizeof(struct qcedev_sha_op_req))) return -EFAULT; From 45b4f654b9c67f2f4d56d6b55eb8680e782ddab8 Mon Sep 17 00:00:00 2001 From: Harsh Sahu Date: Thu, 13 Apr 2017 15:38:46 -0700 Subject: [PATCH 189/210] msm: mdss: fix race condition during mdp debugfs release Fix race condition in the release of the mdp debugfs functions panel_debug_base_release and mdss_debug_base_release by adding the lock for unpreempted freeing of the buffer so that multiple concurrent processes cannot affect the release which can possibly lead to use-after-free operation on the buffer. Change-Id: I9586081b65ae2eb0e7f6e30c606ee748ae9ef7e8 Signed-off-by: Harsh Sahu --- drivers/video/msm/mdss/mdss_debug.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index 3886183326a5..e61218acff0f 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -57,11 +57,13 @@ static int panel_debug_base_open(struct inode *inode, struct file *file) static int panel_debug_base_release(struct inode *inode, struct file *file) { struct mdss_debug_base *dbg = file->private_data; + mutex_lock(&mdss_debug_lock); if (dbg && dbg->buf) { kfree(dbg->buf); dbg->buf_len = 0; dbg->buf = NULL; } + mutex_unlock(&mdss_debug_lock); return 0; } @@ -379,11 +381,13 @@ static int mdss_debug_base_open(struct inode *inode, struct file *file) static int mdss_debug_base_release(struct inode *inode, struct file *file) { struct mdss_debug_base *dbg = file->private_data; + mutex_lock(&mdss_debug_lock); if (dbg && dbg->buf) { kfree(dbg->buf); dbg->buf_len = 0; dbg->buf = NULL; } + mutex_unlock(&mdss_debug_lock); return 0; } From 2fa3c21819bde1f8727b955f85d493f85211a0c8 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Tue, 21 Feb 2017 11:35:37 -0800 Subject: [PATCH 190/210] crypto: msm: check invalid src and dst vbuf in qcedev.c src and dst vbuf address and length are provided from userspace, and they are invalid if vbuf address is NULL but length is not zero. Add additional checks in qcedev_check_cipher_params to prevent it. Change-Id: Iadc1a0c1c5b2f7a56acd03a23c08e45b5a671b19 Signed-off-by: Zhen Kong --- drivers/crypto/msm/qcedev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 8cf19a4b3cdc..59a654dff2e7 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1518,6 +1518,11 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, } /* Check for sum of all dst length is equal to data_len */ for (i = 0, total = 0; i < req->entries; i++) { + if (!req->vbuf.dst[i].vaddr && req->vbuf.dst[i].len) { + pr_err("%s: NULL req dst vbuf[%d] with length %d\n", + __func__, i, req->vbuf.dst[i].len); + goto error; + } if (req->vbuf.dst[i].len >= U32_MAX - total) { pr_err("%s: Integer overflow on total req dst vbuf length\n", __func__); @@ -1532,6 +1537,11 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, } /* Check for sum of all src length is equal to data_len */ for (i = 0, total = 0; i < req->entries; i++) { + if (!req->vbuf.src[i].vaddr && req->vbuf.src[i].len) { + pr_err("%s: NULL req src vbuf[%d] with length %d\n", + __func__, i, req->vbuf.src[i].len); + goto error; + } if (req->vbuf.src[i].len > U32_MAX - total) { pr_err("%s: Integer overflow on total req src vbuf length\n", __func__); From 04b086de99439ffbb3b4e502b5beb03b46d5c4db Mon Sep 17 00:00:00 2001 From: Siba Prasad Date: Thu, 2 Feb 2017 17:18:40 +0530 Subject: [PATCH 191/210] mmc: card: block: check the user controlled parameters to avoid overflow According to specs, some commands require a delay after issuing the command. idata->ic struct is received from user in mmc_blk_ioctl_cmd(). So idata->ic.postsleep_min_us, idata->ic.postsleep_max_us are user controlled. If the min and max values are set such as max < min, then operation in the function do_usleep_range will overflow. For avoiding this, put a condition for checking max < min. If the condition is true, then print the error message with respective values and return error. Change-Id: I76828b58aa46fc4e195da4ae0babb02a7abf6bbe Signed-off-by: Siba Prasad --- drivers/mmc/card/block.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index f297b85d2420..c903633f3904 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -701,6 +701,14 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, cmd.arg = idata->ic.arg; cmd.flags = idata->ic.flags; + if (idata->ic.postsleep_max_us < idata->ic.postsleep_min_us) { + pr_err("%s: min value: %u must not be greater than max value: %u\n", + __func__, idata->ic.postsleep_min_us, + idata->ic.postsleep_max_us); + WARN_ON(1); + return -EPERM; + } + if (idata->buf_bytes) { data.sg = &sg; data.sg_len = 1; From 81cf5b0c4d21b06de437f290d27cf060b54a1235 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Tue, 4 Apr 2017 13:07:03 -0700 Subject: [PATCH 192/210] soc: qcom: remove debugfs interface from ssr As debugfs interface is intended to test the respective ssr, remove from the driver to make sure it won't be available by default. CRs-Fixed: 2025661 Change-Id: I6af9a8333c8028611f889cc2f9b0beb37ef12c9b Signed-off-by: Satya Durga Srinivasu Prabhala --- drivers/soc/qcom/subsystem_restart.c | 101 +-------------------------- include/soc/qcom/subsystem_restart.h | 3 +- 2 files changed, 4 insertions(+), 100 deletions(-) diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index 57c7138eb622..0675ddf1d5f3 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -146,7 +145,6 @@ struct restart_log { * @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.) * @restart_order: order of other devices this devices restarts with * @crash_count: number of times the device has crashed - * @dentry: debugfs directory for this device * @do_ramdump_on_put: ramdump on subsystem_put() if true * @err_ready: completion variable to record error ready from subsystem * @crashed: indicates if subsystem has crashed @@ -168,9 +166,6 @@ struct subsys_device { int restart_level; int crash_count; struct subsys_soc_restart_order *restart_order; -#ifdef CONFIG_DEBUG_FS - struct dentry *dentry; -#endif bool do_ramdump_on_put; struct cdev char_dev; dev_t dev_no; @@ -344,10 +339,11 @@ static struct device_attribute subsys_attrs[] = { __ATTR_NULL, }; -static struct bus_type subsys_bus_type = { +struct bus_type subsys_bus_type = { .name = "msm_subsys", .dev_attrs = subsys_attrs, }; +EXPORT_SYMBOL(subsys_bus_type); static DEFINE_IDA(subsys_ida); @@ -1106,87 +1102,6 @@ void notify_proxy_unvote(struct device *device) notify_each_subsys_device(&dev, 1, SUBSYS_PROXY_UNVOTE, NULL); } -#ifdef CONFIG_DEBUG_FS -static ssize_t subsys_debugfs_read(struct file *filp, char __user *ubuf, - size_t cnt, loff_t *ppos) -{ - int r; - char buf[40]; - struct subsys_device *subsys = filp->private_data; - - r = snprintf(buf, sizeof(buf), "%d\n", subsys->count); - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} - -static ssize_t subsys_debugfs_write(struct file *filp, - const char __user *ubuf, size_t cnt, loff_t *ppos) -{ - struct subsys_device *subsys = filp->private_data; - char buf[10]; - char *cmp; - - cnt = min(cnt, sizeof(buf) - 1); - if (copy_from_user(&buf, ubuf, cnt)) - return -EFAULT; - buf[cnt] = '\0'; - cmp = strstrip(buf); - - if (!strcmp(cmp, "restart")) { - if (subsystem_restart_dev(subsys)) - return -EIO; - } else if (!strcmp(cmp, "get")) { - if (subsystem_get(subsys->desc->name)) - return -EIO; - } else if (!strcmp(cmp, "put")) { - subsystem_put(subsys); - } else { - return -EINVAL; - } - - return cnt; -} - -static const struct file_operations subsys_debugfs_fops = { - .open = simple_open, - .read = subsys_debugfs_read, - .write = subsys_debugfs_write, -}; - -static struct dentry *subsys_base_dir; - -static int __init subsys_debugfs_init(void) -{ - subsys_base_dir = debugfs_create_dir("msm_subsys", NULL); - return !subsys_base_dir ? -ENOMEM : 0; -} - -static void subsys_debugfs_exit(void) -{ - debugfs_remove_recursive(subsys_base_dir); -} - -static int subsys_debugfs_add(struct subsys_device *subsys) -{ - if (!subsys_base_dir) - return -ENOMEM; - - subsys->dentry = debugfs_create_file(subsys->desc->name, - S_IRUGO | S_IWUSR, subsys_base_dir, - subsys, &subsys_debugfs_fops); - return !subsys->dentry ? -ENOMEM : 0; -} - -static void subsys_debugfs_remove(struct subsys_device *subsys) -{ - debugfs_remove(subsys->dentry); -} -#else -static int __init subsys_debugfs_init(void) { return 0; }; -static void subsys_debugfs_exit(void) { } -static int subsys_debugfs_add(struct subsys_device *subsys) { return 0; } -static void subsys_debugfs_remove(struct subsys_device *subsys) { } -#endif - static int subsys_device_open(struct inode *inode, struct file *file) { struct subsys_device *device, *subsys_dev = 0; @@ -1601,10 +1516,6 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) mutex_init(&subsys->track.lock); - ret = subsys_debugfs_add(subsys); - if (ret) - goto err_debugfs; - ret = device_register(&subsys->dev); if (ret) { device_unregister(&subsys->dev); @@ -1656,8 +1567,6 @@ err_setup_irqs: if (ofnode) subsys_remove_restart_order(ofnode); err_register: - subsys_debugfs_remove(subsys); -err_debugfs: mutex_destroy(&subsys->track.lock); ida_simple_remove(&subsys_ida, subsys->id); err_ida: @@ -1690,7 +1599,6 @@ void subsys_unregister(struct subsys_device *subsys) WARN_ON(subsys->count); device_unregister(&subsys->dev); mutex_unlock(&subsys->track.lock); - subsys_debugfs_remove(subsys); subsys_char_device_remove(subsys); sysmon_notifier_unregister(subsys->desc); put_device(&subsys->dev); @@ -1728,9 +1636,6 @@ static int __init subsys_restart_init(void) ret = bus_register(&subsys_bus_type); if (ret) goto err_bus; - ret = subsys_debugfs_init(); - if (ret) - goto err_debugfs; char_class = class_create(THIS_MODULE, "subsys"); if (IS_ERR(char_class)) { @@ -1749,8 +1654,6 @@ static int __init subsys_restart_init(void) err_soc: class_destroy(char_class); err_class: - subsys_debugfs_exit(); -err_debugfs: bus_unregister(&subsys_bus_type); err_bus: destroy_workqueue(ssr_wq); diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h index 4d93c70a10cd..57bbafe7cbd5 100644 --- a/include/soc/qcom/subsystem_restart.h +++ b/include/soc/qcom/subsystem_restart.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017, 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 @@ -18,6 +18,7 @@ #include struct subsys_device; +extern struct bus_type subsys_bus_type; enum { RESET_SOC = 0, From 51b754d7418250c50e4543cc506aa830271545b4 Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Mon, 17 Apr 2017 14:29:57 +0530 Subject: [PATCH 193/210] wcnss: fix the potential memory leak and heap overflow The wcnss platform driver update the wlan calibration data by the user space wlan daemon. The wlan user space daemon store the updated wlan calibration data reported by wlan firmware in user space and write it back to the wcnss platform calibration data buffer for the calibration data download and update. During the wlan calibration data store and retrieve operation there are some potential race condition which leads to memory leak and buffer overflow during the context switch. Fix the above issue by adding protection code and avoid usage of global pointer during the device file read and write operation. CRs-Fixed: 2015858 Change-Id: Ib5b57eb86dcb4e6ed799b5222d06396eaabfaad3 Signed-off-by: Sarada Prasanna Garnayak --- drivers/net/wireless/wcnss/wcnss_wlan.c | 89 +++++++++++++++---------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index c4c00d737aa6..e0d964d896d3 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2015, 2017, 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 @@ -400,7 +400,6 @@ static struct { int user_cal_available; u32 user_cal_rcvd; int user_cal_exp_size; - int device_opened; int iris_xo_mode_set; int fw_vbatt_state; char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE]; @@ -3280,14 +3279,6 @@ static int wcnss_node_open(struct inode *inode, struct file *file) return -EFAULT; } - mutex_lock(&penv->dev_lock); - penv->user_cal_rcvd = 0; - penv->user_cal_read = 0; - penv->user_cal_available = false; - penv->user_cal_data = NULL; - penv->device_opened = 1; - mutex_unlock(&penv->dev_lock); - return rc; } @@ -3296,7 +3287,7 @@ static ssize_t wcnss_wlan_read(struct file *fp, char __user { int rc = 0; - if (!penv || !penv->device_opened) + if (!penv) return -EFAULT; rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd @@ -3333,55 +3324,66 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user *user_buffer, size_t count, loff_t *position) { int rc = 0; - u32 size = 0; + char *cal_data = NULL; - if (!penv || !penv->device_opened || penv->user_cal_available) + if (!penv || penv->user_cal_available) return -EFAULT; - if (penv->user_cal_rcvd == 0 && count >= 4 - && !penv->user_cal_data) { - rc = copy_from_user((void *)&size, user_buffer, 4); - if (!size || size > MAX_CALIBRATED_DATA_SIZE) { - pr_err(DEVICE " invalid size to write %d\n", size); + if (!penv->user_cal_rcvd && count >= 4 && !penv->user_cal_exp_size) { + mutex_lock(&penv->dev_lock); + rc = copy_from_user((void *)&penv->user_cal_exp_size, + user_buffer, 4); + if (!penv->user_cal_exp_size || + penv->user_cal_exp_size > MAX_CALIBRATED_DATA_SIZE) { + pr_err(DEVICE " invalid size to write %d\n", + penv->user_cal_exp_size); + penv->user_cal_exp_size = 0; + mutex_unlock(&penv->dev_lock); return -EFAULT; } - - rc += count; - count -= 4; - penv->user_cal_exp_size = size; - penv->user_cal_data = kmalloc(size, GFP_KERNEL); - if (penv->user_cal_data == NULL) { - pr_err(DEVICE " no memory to write\n"); - return -ENOMEM; - } - if (0 == count) - goto exit; - - } else if (penv->user_cal_rcvd == 0 && count < 4) + mutex_unlock(&penv->dev_lock); + return count; + } else if (!penv->user_cal_rcvd && count < 4) { return -EFAULT; + } + mutex_lock(&penv->dev_lock); if ((UINT32_MAX - count < penv->user_cal_rcvd) || (penv->user_cal_exp_size < count + penv->user_cal_rcvd)) { pr_err(DEVICE " invalid size to write %zu\n", count + penv->user_cal_rcvd); - rc = -ENOMEM; - goto exit; + mutex_unlock(&penv->dev_lock); + return -ENOMEM; } - rc = copy_from_user((void *)penv->user_cal_data + - penv->user_cal_rcvd, user_buffer, count); - if (0 == rc) { + + cal_data = kmalloc(count, GFP_KERNEL); + if (!cal_data) { + mutex_unlock(&penv->dev_lock); + return -ENOMEM; + } + + rc = copy_from_user(cal_data, user_buffer, count); + if (!rc) { + memcpy(penv->user_cal_data + penv->user_cal_rcvd, + cal_data, count); penv->user_cal_rcvd += count; rc += count; } + + kfree(cal_data); if (penv->user_cal_rcvd == penv->user_cal_exp_size) { penv->user_cal_available = true; pr_info_ratelimited("wcnss: user cal written"); } + mutex_unlock(&penv->dev_lock); -exit: return rc; } +static int wcnss_node_release(struct inode *inode, struct file *file) +{ + return 0; +} static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, void *ss_handle) @@ -3440,6 +3442,7 @@ static const struct file_operations wcnss_node_fops = { .open = wcnss_node_open, .read = wcnss_wlan_read, .write = wcnss_wlan_write, + .release = wcnss_node_release, }; static struct miscdevice wcnss_misc = { @@ -3467,6 +3470,13 @@ wcnss_wlan_probe(struct platform_device *pdev) } penv->pdev = pdev; + penv->user_cal_data = + devm_kzalloc(&pdev->dev, MAX_CALIBRATED_DATA_SIZE, GFP_KERNEL); + if (!penv->user_cal_data) { + dev_err(&pdev->dev, "Failed to alloc memory for cal data.\n"); + return -ENOMEM; + } + /* register sysfs entries */ ret = wcnss_create_sysfs(&pdev->dev); if (ret) { @@ -3487,6 +3497,11 @@ wcnss_wlan_probe(struct platform_device *pdev) mutex_init(&penv->pm_qos_mutex); init_waitqueue_head(&penv->read_wait); + penv->user_cal_rcvd = 0; + penv->user_cal_read = 0; + penv->user_cal_exp_size = 0; + penv->user_cal_available = false; + /* Since we were built into the kernel we'll be called as part * of kernel initialization. We don't know if userspace * applications are available to service PIL at this time From a4b9ac6bafc779a79578c8964e91660ccaef83e6 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Thu, 6 Apr 2017 18:28:31 +0530 Subject: [PATCH 194/210] msm: kgsl: Fix the race between context create and destroy Hold the context lock before updating the context id in param->drawctxt_id to avoid race condition between context creation and context destroy. Change-Id: Ic26d3e5b68078c02d15c38080b1a262ea4b1f7fe Signed-off-by: Sunil Khatri --- drivers/gpu/msm/kgsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 91cf080dcfa6..576d0c1f1a56 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1811,9 +1811,9 @@ long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv, /* Commit the pointer to the context in context_idr */ write_lock(&device->context_lock); idr_replace(&device->context_idr, context, context->id); + param->drawctxt_id = context->id; write_unlock(&device->context_lock); - param->drawctxt_id = context->id; done: return result; } From 45e8d79d639d3ab8dbe88334f5fc3b4aa7973c1f Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Fri, 14 Apr 2017 19:23:05 -0700 Subject: [PATCH 195/210] msm : rmnet_ipa: fix memory overflow issue Fix the security issue where mux channel name might not be null-terminated causing memory access overflow in ipa wan driver. Change-Id: I3ef440b62cf3861464fb60c1e7f65f2be5e39ed0 Acked-by: Shihuan Liu Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/rmnet_ipa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c index c274ee1adacb..dc6ce0eed812 100644 --- a/drivers/platform/msm/ipa/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/rmnet_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -1359,6 +1359,8 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) memcpy(mux_channel[rmnet_index].vchannel_name, extend_ioctl_data.u.rmnet_mux_val.vchannel_name, sizeof(mux_channel[rmnet_index].vchannel_name)); + mux_channel[rmnet_index].vchannel_name[ + IFNAMSIZ - 1] = '\0'; IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n", mux_channel[rmnet_index].vchannel_name, mux_channel[rmnet_index].mux_id, From 8f32f01f572ccb2572f6e96bdf140e262dac53af Mon Sep 17 00:00:00 2001 From: Kishor PK Date: Thu, 30 Mar 2017 14:23:37 +0530 Subject: [PATCH 196/210] soc: qcom: pil: Avoid possible buffer overflow during Modem boot Buffer overflow can occur if MBA firmware size exceeds 1MB. So validate size before copying the firmware. CRs-Fixed: 2001803 Change-Id: I070ddf85fbc47df072e7258369272366262ebf46 Signed-off-by: Kishor PK Signed-off-by: Srinivasarao P --- drivers/soc/qcom/pil-msa.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c index d410e0dfb34d..982283d171f3 100644 --- a/drivers/soc/qcom/pil-msa.c +++ b/drivers/soc/qcom/pil-msa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -560,7 +560,15 @@ int pil_mss_reset_load_mba(struct pil_desc *pil) goto err_mba_data; } count = fw->size; - memcpy(mba_virt, data, count); + if (count <= SZ_1M) { + /* Ensures memcpy is done for max 1MB fw size */ + memcpy(mba_virt, data, count); + } else { + dev_err(pil->dev, "%s fw image loading into memory is failed due to fw size overflow\n", + __func__); + ret = -EINVAL; + goto err_mba_data; + } wmb(); /* Load modem debug policy */ From 533ee96a2800d25b36cd1014a200aaac789f33f3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 30 Dec 2015 08:51:12 -0500 Subject: [PATCH 197/210] udp: properly support MSG_PEEK with truncated buffers Backport of this upstream commit into stable kernels : 89c22d8c3b27 ("net: Fix skb csum races when peeking") exposed a bug in udp stack vs MSG_PEEK support, when user provides a buffer smaller than skb payload. In this case, skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); returns -EFAULT. This bug does not happen in upstream kernels since Al Viro did a great job to replace this into : skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); This variant is safe vs short buffers. For the time being, instead reverting Herbert Xu patch and add back skb->ip_summed invalid changes, simply store the result of udp_lib_checksum_complete() so that we avoid computing the checksum a second time, and avoid the problematic skb_copy_and_csum_datagram_iovec() call. This patch can be applied on recent kernels as it avoids a double checksumming, then backported to stable kernels as a bug fix. Signed-off-by: Eric Dumazet Acked-by: Herbert Xu Signed-off-by: David S. Miller [d-cagle@codeaurora.org: Resolve trivial merge conflicts] Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git Git-commit: 197c949e7798fbf28cfadc69d9ca0c2abbf93191 Change-Id: I70f19a362f627bd2d9d8e10e31bbcdb4b0600792 Signed-off-by: Dennis Cagle --- net/ipv4/udp.c | 6 ++++-- net/ipv6/udp.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 463710f8a66d..23d991a1754e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1215,6 +1215,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, int peeked, off = 0; int err; int is_udplite = IS_UDPLITE(sk); + bool checksum_valid = false; bool slow; if (flags & MSG_ERRQUEUE) @@ -1240,11 +1241,12 @@ try_again: */ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { - if (udp_lib_checksum_complete(skb)) + checksum_valid = !udp_lib_checksum_complete(skb); + if (!checksum_valid) goto csum_copy_err; } - if (skb_csum_unnecessary(skb)) + if (checksum_valid || skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); else { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 2adb06986852..d689b25e9510 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -370,6 +370,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, int peeked, off = 0; int err; int is_udplite = IS_UDPLITE(sk); + bool checksum_valid = false; int is_udp4; bool slow; @@ -401,11 +402,12 @@ try_again: */ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { - if (udp_lib_checksum_complete(skb)) + checksum_valid = !udp_lib_checksum_complete(skb); + if (!checksum_valid) goto csum_copy_err; } - if (skb_csum_unnecessary(skb)) + if (checksum_valid || skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); else { From 1f2697689256bf1f4663adf4d6543beb2a779733 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 19 Sep 2016 17:39:09 +0200 Subject: [PATCH 198/210] posix_acl: Clear SGID bit when setting file permissions When file permissions are modified via chmod(2) and the user is not in the owning group or capable of CAP_FSETID, the setgid bit is cleared in inode_change_ok(). Setting a POSIX ACL via setxattr(2) sets the file permissions as well as the new ACL, but doesn't clear the setgid bit in a similar way; this allows to bypass the check in chmod(2). Fix that. References: CVE-2016-7097 Reviewed-by: Christoph Hellwig Reviewed-by: Jeff Layton Signed-off-by: Jan Kara Signed-off-by: Andreas Gruenbacher Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/ linux.git Git-commit: 073931017b49d9458aa351605b43a7e34598caef Change-Id: Idf7cd8d0fb030fedeabd46254e4c4a9c08bce8b5 [d-cagle@codeaurora.org: Resolve merge conflicts and style] Signed-off-by: Dennis Cagle [stummala@codeaurora.org: Resolve merge conflicts on existing files and skip files fs/ceph/acl.c, fs/hfsplus/posix_acl.c and fs/jfs/acl.c from original change as those files are not present/fix is not applicable on 3.10 kernel] Signed-off-by: Sahitya Tummala --- fs/9p/acl.c | 41 +++++++++++++++++---------------------- fs/btrfs/acl.c | 7 +++---- fs/ext2/acl.c | 13 +++++-------- fs/ext4/acl.c | 13 +++++-------- fs/f2fs/acl.c | 7 +++---- fs/gfs2/acl.c | 5 +++-- fs/jffs2/acl.c | 9 ++++----- fs/ocfs2/acl.c | 8 ++++---- fs/posix_acl.c | 31 +++++++++++++++++++++++++++++ fs/reiserfs/xattr_acl.c | 9 +++------ fs/xfs/xfs_acl.c | 5 +++-- include/linux/posix_acl.h | 3 +++ 12 files changed, 85 insertions(+), 66 deletions(-) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 7af425f53bee..f29d1f00a4d8 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -320,32 +320,27 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - umode_t mode = inode->i_mode; - retval = posix_acl_equiv_mode(acl, &mode); - if (retval < 0) + struct iattr iattr; + + retval = posix_acl_update_mode(inode, + &iattr.ia_mode, &acl); + if (retval) goto err_out; - else { - struct iattr iattr; - if (retval == 0) { - /* - * ACL can be represented - * by the mode bits. So don't - * update ACL. - */ - acl = NULL; - value = NULL; - size = 0; - } - /* Updte the mode bits */ - iattr.ia_mode = ((mode & S_IALLUGO) | - (inode->i_mode & ~S_IALLUGO)); - iattr.ia_valid = ATTR_MODE; - /* FIXME should we update ctime ? - * What is the following setxattr update the - * mode ? + if (!acl) { + /* + * ACL can be represented + * by the mode bits. So don't + * update ACL. */ - v9fs_vfs_setattr_dotl(dentry, &iattr); + value = NULL; + size = 0; } + iattr.ia_valid = ATTR_MODE; + /* FIXME should we update ctime ? + * What is the following setxattr update the + * mode ? + */ + v9fs_vfs_setattr_dotl(dentry, &iattr); } break; case ACL_TYPE_DEFAULT: diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 0890c83643e9..1fc4626beccb 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -118,11 +118,10 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - ret = posix_acl_equiv_mode(acl, &inode->i_mode); - if (ret < 0) + ret = posix_acl_update_mode(inode, + &inode->i_mode, &acl); + if (ret) return ret; - if (ret == 0) - acl = NULL; } ret = 0; break; diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 110b6b371a4e..36ad07b03e06 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -206,15 +206,12 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); + if (error) return error; - else { - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); - if (error == 0) - acl = NULL; - } + inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); } break; diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 39a54a0e9fe4..9bbdc3847681 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -211,15 +211,12 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); + if (error) return error; - else { - inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); - if (error == 0) - acl = NULL; - } + inode->i_ctime = ext4_current_time(inode); + ext4_mark_inode_dirty(handle, inode); } break; diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index 44abc2f286e0..059375a0d4fa 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -223,12 +223,11 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) case ACL_TYPE_ACCESS: name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); + if (error) return error; set_acl_inode(fi, inode->i_mode); - if (error == 0) - acl = NULL; } break; diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index f69ac0af5496..688dcbfaaf71 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -267,8 +267,9 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, goto out_release; if (type == ACL_TYPE_ACCESS) { - umode_t mode = inode->i_mode; - error = posix_acl_equiv_mode(acl, &mode); + umode_t mode; + + error = posix_acl_update_mode(inode, &mode, &acl); if (error <= 0) { posix_acl_release(acl); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 223283c30111..9335b8d3cf52 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -243,9 +243,10 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) case ACL_TYPE_ACCESS: xprefix = JFFS2_XPREFIX_ACL_ACCESS; if (acl) { - umode_t mode = inode->i_mode; - rc = posix_acl_equiv_mode(acl, &mode); - if (rc < 0) + umode_t mode; + + rc = posix_acl_update_mode(inode, &mode, &acl); + if (rc) return rc; if (inode->i_mode != mode) { struct iattr attr; @@ -257,8 +258,6 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) if (rc < 0) return rc; } - if (rc == 0) - acl = NULL; } break; case ACL_TYPE_DEFAULT: diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 8a404576fb26..713f87d3f1e6 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -274,9 +274,10 @@ static int ocfs2_set_acl(handle_t *handle, case ACL_TYPE_ACCESS: name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - umode_t mode = inode->i_mode; - ret = posix_acl_equiv_mode(acl, &mode); - if (ret < 0) + umode_t mode; + + ret = posix_acl_update_mode(inode, &mode, &acl); + if (ret) return ret; else { if (ret == 0) @@ -286,7 +287,6 @@ static int ocfs2_set_acl(handle_t *handle, handle, mode); if (ret) return ret; - } } break; diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 3542f1f814e2..2bc32c0b30ca 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -424,3 +424,34 @@ posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) return err; } EXPORT_SYMBOL(posix_acl_chmod); + +/** + * posix_acl_update_mode - update mode in set_acl + * + * Update the file mode when setting an ACL: compute the new file permission + * bits based on the ACL. In addition, if the ACL is equivalent to the new + * file mode, set *acl to NULL to indicate that no ACL should be set. + * + * As with chmod, clear the setgit bit if the caller is not in the owning group + * or capable of CAP_FSETID (see inode_change_ok). + * + * Called from set_acl inode operations. + */ +int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, + struct posix_acl **acl) +{ + umode_t mode = inode->i_mode; + int error; + + error = posix_acl_equiv_mode(*acl, &mode); + if (error < 0) + return error; + if (error == 0) + *acl = NULL; + if (!in_group_p(inode->i_gid) && + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) + mode &= ~S_ISGID; + *mode_p = mode; + return 0; +} +EXPORT_SYMBOL(posix_acl_update_mode); diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 6c8767fdfc6a..df5ad5574810 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -286,13 +286,10 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); - if (error < 0) + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); + if (error) return error; - else { - if (error == 0) - acl = NULL; - } } break; case ACL_TYPE_DEFAULT: diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 306d883d89bc..2a60773831fc 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -388,8 +388,9 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, goto out_release; if (type == ACL_TYPE_ACCESS) { - umode_t mode = inode->i_mode; - error = posix_acl_equiv_mode(acl, &mode); + umode_t mode; + + error = posix_acl_update_mode(inode, &mode, &acl); if (error <= 0) { posix_acl_release(acl); diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 7931efe71175..94d2f4282a24 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -95,6 +95,9 @@ extern struct posix_acl *get_posix_acl(struct inode *, int); extern int set_posix_acl(struct inode *, int, struct posix_acl *); #ifdef CONFIG_FS_POSIX_ACL +extern int posix_acl_update_mode(struct inode *, umode_t *, + struct posix_acl **); + static inline struct posix_acl **acl_by_type(struct inode *inode, int type) { switch (type) { From d96aa409f88b7ab0db7b56be1b78d21696e95058 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Fri, 3 Feb 2017 20:37:06 -0800 Subject: [PATCH 199/210] ANDROID: ion: Protect kref from userspace manipulation This separates the kref for ion handles into two components. Userspace requests through the ioctl will hold at most one reference to the internally used kref. All additional requests will increment a separate counter, and the original reference is only put once that counter hits 0. This protects the kernel from a poorly behaving userspace. Bug: 34276203 Change-Id: Ibc36bc4405788ed0fea7337b541cad3be2b934c0 Signed-off-by: Daniel Rosenberg Git-repo: https://android.googlesource.com/kernel/msm/ Git-commit: 20abfcc16884a5af973a5e91dd013ddd789c44f4 [d-cagle@codeaurora.org: Resolve style issues] Signed-off-by: Dennis Cagle --- drivers/staging/android/ion/ion.c | 84 ++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 07cb042f1e0b..8fa3a8479cf6 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -113,6 +113,7 @@ struct ion_client { */ struct ion_handle { struct kref ref; + unsigned int user_ref_count; struct ion_client *client; struct ion_buffer *buffer; struct rb_node node; @@ -434,6 +435,49 @@ int ion_handle_put(struct ion_handle *handle) return ret; } +/* Must hold the client lock */ +static void user_ion_handle_get(struct ion_handle *handle) +{ + if (handle->user_ref_count++ == 0) + kref_get(&handle->ref); +} + +/* Must hold the client lock */ +static struct ion_handle *user_ion_handle_get_check_overflow( + struct ion_handle *handle) +{ + if (handle->user_ref_count + 1 == 0) + return ERR_PTR(-EOVERFLOW); + user_ion_handle_get(handle); + return handle; +} + +/* passes a kref to the user ref count. + * We know we're holding a kref to the object before and + * after this call, so no need to reverify handle. */ +static struct ion_handle *pass_to_user(struct ion_handle *handle) +{ + struct ion_client *client = handle->client; + struct ion_handle *ret; + + mutex_lock(&client->lock); + ret = user_ion_handle_get_check_overflow(handle); + ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); + return ret; +} + +/* Must hold the client lock */ +static int user_ion_handle_put_nolock(struct ion_handle *handle) +{ + int ret; + + if (--handle->user_ref_count == 0) + ret = ion_handle_put_nolock(handle); + + return ret; +} + static struct ion_handle *ion_handle_lookup(struct ion_client *client, struct ion_buffer *buffer) { @@ -645,6 +689,25 @@ static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle ion_handle_put_nolock(handle); } +static void user_ion_free_nolock(struct ion_client *client, + struct ion_handle *handle) +{ + bool valid_handle; + + BUG_ON(client != handle->client); + + valid_handle = ion_handle_validate(client, handle); + if (!valid_handle) { + WARN(1, "%s: invalid handle passed to free.\n", __func__); + return; + } + if (!handle->user_ref_count > 0) { + WARN(1, "%s: User does not have access!\n", __func__); + return; + } + user_ion_handle_put_nolock(handle); +} + void ion_free(struct ion_client *client, struct ion_handle *handle) { BUG_ON(client != handle->client); @@ -1511,7 +1574,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) data.allocation.flags, true); if (IS_ERR(handle)) return PTR_ERR(handle); - + pass_to_user(handle); data.allocation.handle = handle->id; cleanup_handle = handle; @@ -1527,7 +1590,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) mutex_unlock(&client->lock); return PTR_ERR(handle); } - ion_free_nolock(client, handle); + user_ion_free_nolock(client, handle); ion_handle_put_nolock(handle); mutex_unlock(&client->lock); break; @@ -1551,10 +1614,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ion_handle *handle; handle = ion_import_dma_buf(client, data.fd.fd); - if (IS_ERR(handle)) + if (IS_ERR(handle)) { ret = PTR_ERR(handle); - else - data.handle.handle = handle->id; + } else { + handle = pass_to_user(handle); + if (IS_ERR(handle)) + ret = PTR_ERR(handle); + else + data.handle.handle = handle->id; + } break; } case ION_IOC_SYNC: @@ -1586,8 +1654,10 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (dir & _IOC_READ) { if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { if (cleanup_handle) { - ion_free(client, cleanup_handle); - ion_handle_put(cleanup_handle); + mutex_lock(&client->lock); + user_ion_free_nolock(client, cleanup_handle); + ion_handle_put_nolock(cleanup_handle); + mutex_unlock(&client->lock); } return -EFAULT; } From 8681f9e793a656ce874922d111b3d77a0e999781 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 13 Dec 2016 10:33:34 -0800 Subject: [PATCH 200/210] FROMLIST: 9p: fix a potential acl leak (https://lkml.org/lkml/2016/12/13/579) posix_acl_update_mode() could possibly clear 'acl', if so we leak the memory pointed by 'acl'. Save this pointer before calling posix_acl_update_mode() and release the memory if 'acl' really gets cleared. Reported-by: Mark Salyzyn Reviewed-by: Jan Kara Reviewed-by: Greg Kurz Cc: Eric Van Hensbergen Cc: Ron Minnich Cc: Latchesar Ionkov Signed-off-by: Cong Wang Bug: 32458736 Change-Id: Ia78da401e6fd1bfd569653bd2cd0ebd3f9c737a0 Git-repo: https://android.googlesource.com/kernel/msm/ Git-commit: 7c780387c931f63fe67830c817f65c1272512bb1 Signed-off-by: Dennis Cagle --- fs/9p/acl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index f29d1f00a4d8..6b951d1140dd 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -321,6 +321,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, name = POSIX_ACL_XATTR_ACCESS; if (acl) { struct iattr iattr; + struct posix_acl *old_acl = acl; retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); @@ -332,6 +333,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, * by the mode bits. So don't * update ACL. */ + posix_acl_release(old_acl); value = NULL; size = 0; } From ca2f0145c3024db3a8aa27e431901e3eb131fcf8 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 23 Jan 2017 12:56:41 -0800 Subject: [PATCH 201/210] ANDROID: fix acl leaks Fixes regressions associated with commit 073931017b49d9458aa351605b43a7e34598caef Signed-off-by: Mark Salyzyn Bug: 32458736 Change-Id: I6ee127dfdf3594d24ccd8560541ac554c5b05eb6 [stummala@codeaurora.org: Fixed merge conflicts] Signed-off-by: Sahitya Tummala --- fs/gfs2/acl.c | 13 +++++-------- fs/jfs/xattr.c | 8 +++++--- fs/xfs/xfs_acl.c | 13 +++++-------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 688dcbfaaf71..d4b2bbd7cf48 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -268,16 +268,13 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, if (type == ACL_TYPE_ACCESS) { umode_t mode; + struct posix_acl *old_acl = acl; error = posix_acl_update_mode(inode, &mode, &acl); - - if (error <= 0) { - posix_acl_release(acl); - acl = NULL; - - if (error < 0) - return error; - } + if (!acl) + posix_acl_release(old_acl); + if (error) + goto out_release; error = gfs2_set_mode(inode, mode); if (error) diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 42d67f9757bf..7adb97da7b2a 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -693,11 +693,13 @@ static int can_set_system_xattr(struct inode *inode, const char *name, return rc; } if (acl) { - rc = posix_acl_equiv_mode(acl, &inode->i_mode); - posix_acl_release(acl); + struct posix_acl *old_acl = acl; + + rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); + posix_acl_release(old_acl); if (rc < 0) { printk(KERN_ERR - "posix_acl_equiv_mode returned %d\n", + "posix_acl_update_mode returned %d\n", rc); return rc; } diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 2a60773831fc..0c59d960efe8 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -389,16 +389,13 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, if (type == ACL_TYPE_ACCESS) { umode_t mode; + struct posix_acl *old_acl = acl; error = posix_acl_update_mode(inode, &mode, &acl); - - if (error <= 0) { - posix_acl_release(acl); - acl = NULL; - - if (error < 0) - return error; - } + if (!acl) + posix_acl_release(old_acl); + if (error) + goto out_release; error = xfs_set_mode(inode, mode); if (error) From 01e113c98fa957b65560e73b699ff0030445b6a1 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Mon, 27 Feb 2017 13:41:07 -0800 Subject: [PATCH 202/210] qseecom: add mutex around qseecom_set_client_mem_param Add mutex around qseecom_set_client_mem_param to prevent an ioctl thread modifying and corrupting data which is being processed by another ioctl in the other thread Change-Id: I0cfb8afab4001c2913be693dfe44c761b9568893 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 7821612a1154..dc78b865a59d 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -6723,7 +6723,11 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; } pr_debug("SET_MEM_PARAM: qseecom addr = 0x%pK\n", data); + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); ret = qseecom_set_client_mem_param(data, argp); + atomic_dec(&data->ioctl_count); + mutex_unlock(&app_access_lock); if (ret) pr_err("failed Qqseecom_set_mem_param request: %d\n", ret); From 29e44920446863c64344bad2bef343310c3be408 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 4 Apr 2017 14:27:16 -0700 Subject: [PATCH 203/210] ANDROID: ion: Fix uninitialized variable Fix an uninitialized variable in user_ion_handle_put_nolock Change-Id: Ia634b790661089ad01aca8e5975984435463d148 Signed-off-by: Daniel Rosenberg Bug: 34276203 [d-cagle@codeaurora.org: Add commit message] Signed-off-by: Dennis Cagle --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 8fa3a8479cf6..b25bf15c69d2 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -470,7 +470,7 @@ static struct ion_handle *pass_to_user(struct ion_handle *handle) /* Must hold the client lock */ static int user_ion_handle_put_nolock(struct ion_handle *handle) { - int ret; + int ret = 0; if (--handle->user_ref_count == 0) ret = ion_handle_put_nolock(handle); From e86b6eb9551c5bc1a1c2c03b8d2b59ca7ebdfb05 Mon Sep 17 00:00:00 2001 From: "Se Wang (Patrick) Oh" Date: Mon, 29 Jun 2015 11:43:39 -0700 Subject: [PATCH 204/210] ion: Fix unprotected userspace access After enabling KASan, unprotected userspace access causes a PTE translation fault as it can covers only kernel memory region. Following is the crash error for the reference. Unable to handle kernel paging request at virtual address dfffff901ff64b84 pgd = ffffffc083266000 [dfffff901ff64b84] *pgd=0000000000000000, *pud=0000000000000000 Internal error: Oops: 96000004 [#1] PREEMPT SMP Modules linked in: CPU: 1 PID: 8527 Comm: iveaudiolatency Tainted: G W 3.18.0-g5a4a5d5-07255-g8e80921-dirty #21 Hardware name: Qualcomm Technologies, Inc. MSM 8996 v2 + PMI8994 MTP (DT) task: ffffffc02bfeb600 ti: ffffffc083378000 task.ti: ffffffc083378000 PC is at compat_msm_ion_ioctl+0x23c/0x614 LR is at compat_msm_ion_ioctl+0x1d8/0x614 pc : [] lr : [] pstate: 80000145 sp : ffffffc08337faf0 x29: ffffffc08337faf0 x28: 0000000000000000 x27: ffffffc083378000 x26: 00000000ffb25c20 x25: 00000000e2fa6000 x24: 0000000000000000 x23: 00000000ffb25c18 x22: 0000000000000000 x21: ffffffc08fcaa640 x20: 00000000c0144d00 x19: 00000000ffb25c74 x18: 0000000000000000 x17: 0000000000000000 x16: ffffffc000385a88 x15: 0000000000000000 x14: 00000000f73517c9 x13: 00000000ffb25c30 x12: 0000000000000001 x11: 00000000ffffffff x10: ffffff881066ff3a x9 : 1ffffff81066ff3a x8 : dfffff9000000000 x7 : 0000000000000036 x6 : ffffffc08337f9d4 x5 : 0000000000000003 x4 : 00000000ffb25c30 x3 : ffffffc0012bd334 x2 : 0000000000000001 x1 : 000000001ff64b84 x0 : dfffff9000000000 Process iveaudiolatency (pid: 8527, stack limit = 0xffffffc083378058) Call trace: [] compat_msm_ion_ioctl+0x23c/0x614 [] ion_ioctl+0x4dc/0x680 [] compat_ion_ioctl+0xb98/0xbc0 [] compat_SyS_ioctl+0x288/0x2048 Code: 910022fa d2dff200 d343ff41 f2fbffe0 (38e06820) ---[ end trace 490ef1c3bde7b96c ]--- coresight-tmc 3028000.tmc: TMC aborted Change-Id: I7595bbf5f311182d40f7158654df56dc8bcf672a Signed-off-by: Se Wang (Patrick) Oh --- drivers/staging/android/ion/msm/compat_msm_ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/msm/compat_msm_ion.c b/drivers/staging/android/ion/msm/compat_msm_ion.c index c34b3a7827d2..ddb9fc73a3e4 100644 --- a/drivers/staging/android/ion/msm/compat_msm_ion.c +++ b/drivers/staging/android/ion/msm/compat_msm_ion.c @@ -58,7 +58,7 @@ static int compat_get_ion_flush_data( err |= put_user(i, &data->fd); err |= get_user(u, &data32->vaddr); /* upper bits won't get set, zero them */ - data->vaddr = NULL; + err |= put_user(NULL, &data->vaddr); err |= put_user(u, (compat_uptr_t *)&data->vaddr); err |= get_user(l, &data32->offset); err |= put_user(l, &data->offset); From 774fbff7a84710083e25abb0edfdde5e785543c6 Mon Sep 17 00:00:00 2001 From: kunleiz Date: Fri, 14 Apr 2017 10:28:42 +0800 Subject: [PATCH 205/210] ASoC: msm: qdspv2: add result check when audio process fail A audio_process_event_req is not always to success. Therefore, check the return value for audio_process_event_req, and initializ usr_evt before using it. CRs-Fixed: 2029798 Change-Id: I4adf682575f5f9233a1a1a533f9c6361af8a5bcf Signed-off-by: kunleiz --- drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c index cb7e9c94dded..89ef02bd45af 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c @@ -846,6 +846,7 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, long rc; struct msm_audio_event32 usr_evt_32; struct msm_audio_event usr_evt; + memset(&usr_evt, 0, sizeof(struct msm_audio_event)); if (copy_from_user(&usr_evt_32, arg, sizeof(struct msm_audio_event32))) { @@ -855,6 +856,11 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, usr_evt.timeout_ms = usr_evt_32.timeout_ms; rc = audio_aio_process_event_req_common(audio, &usr_evt); + if (rc < 0) { + pr_err("%s: audio process event failed, rc = %ld", + __func__, rc); + return rc; + } usr_evt_32.event_type = usr_evt.event_type; switch (usr_evt_32.event_type) { From d2a5120067cc6157b6fe346f630b00db73c17297 Mon Sep 17 00:00:00 2001 From: Siba Prasad Date: Fri, 28 Apr 2017 11:50:36 +0530 Subject: [PATCH 206/210] mmc: card: block: check the user controlled parameters to avoid overflow According to specs, some commands require a delay after issuing the command. idata->ic struct is received from user in mmc_blk_ioctl_cmd(). So idata->ic.postsleep_min_us, idata->ic.postsleep_max_us are user controlled. If the min and max values are set such as max < min, then operation in the function do_usleep_range will overflow. For avoiding this, put a condition for checking max < min. If the condition is true, then print the error message with respective values and return error. Change-Id: Iaf966d19275741a666d2dae1f0c32b72ab0642eb Signed-off-by: Siba Prasad --- drivers/mmc/card/block.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c903633f3904..4c63937114c8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -685,6 +685,15 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, idata = mmc_blk_ioctl_copy_from_user(ic_ptr); if (IS_ERR_OR_NULL(idata)) return PTR_ERR(idata); + if (idata->ic.postsleep_max_us < idata->ic.postsleep_min_us) { + pr_err("%s: min value: %u must not be greater than max value: %u\n", + __func__, idata->ic.postsleep_min_us, + idata->ic.postsleep_max_us); + WARN_ON(1); + err = -EPERM; + goto cmd_err; + } + md = mmc_blk_get(bdev->bd_disk); if (!md) { err = -EINVAL; From 897b479d15e0803270467d4d61af8ab09efe2536 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Tue, 7 Mar 2017 15:12:20 +0530 Subject: [PATCH 207/210] input: touchscreen: remove data pointer from driver structure Remove data pointer from the driver structure which is obtained from user-space. Exclude it from driver structure and move it outside as another global data pointer. The definition of CMD_HEAD_LENGTH is meant to exclude the last member (*data) from the copy from userspace. This change is meant to keep the definition of CMD_HEAD_LENGTH simple, and handle the data separately. Change-Id: I62f14c744e5c331718b6d84f67a4e89b511c9f44 Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/gt9xx/goodix_tool.c | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c index 905e74792bee..f087982fbf94 100644 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c @@ -27,7 +27,7 @@ #include #define DATA_LENGTH_UINT 512 -#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *)) +#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head)) static char procname[20] = {0}; struct st_cmd_head { @@ -44,10 +44,10 @@ struct st_cmd_head { u8 addr_len; /* address length */ u8 addr[2]; /* address */ u8 res[3]; /* reserved */ - u8 *data; /* data pointer */ } __packed; static struct st_cmd_head cmd_head; +static u8 *cmd_data; static struct i2c_client *gt_client; @@ -194,7 +194,7 @@ static void unregister_i2c_func(void) void uninit_wr_node(void) { - cmd_head.data = NULL; + cmd_data = NULL; unregister_i2c_func(); proc_remove(goodix_proc_entry); } @@ -311,7 +311,6 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, size_t count, loff_t *ppos) { s32 ret = 0; - u8 *dataptr = NULL; mutex_lock(&lock); ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); @@ -343,14 +342,14 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, } if (cmd_head.wr == GTP_RW_WRITE) { - ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], + ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH], &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); if (ret) { dev_err(>_client->dev, "copy_from_user failed."); goto exit; } - memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], + memcpy(&cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len); if (cmd_head.flag == GTP_NEED_FLAG) { @@ -363,7 +362,7 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, /* Need interrupt! */ } if (tool_i2c_write( - &cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], + &cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.data_len + cmd_head.addr_len) <= 0) { dev_err(>_client->dev, "Write data failed!"); ret = -EIO; @@ -376,7 +375,7 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, ret = cmd_head.data_len + CMD_HEAD_LENGTH; goto exit; } else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) { /* Write ic type */ - ret = copy_from_user(&cmd_head.data[0], + ret = copy_from_user(&cmd_data[0], &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); if (ret) { @@ -391,7 +390,7 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, ret = -EINVAL; goto exit; } - memcpy(ic_type, cmd_head.data, cmd_head.data_len); + memcpy(ic_type, cmd_data, cmd_head.data_len); register_i2c_func(); @@ -418,13 +417,14 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, goto exit; } else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) { struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); - ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], + + ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH], &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); if (ret) { pr_debug("copy_from_user failed."); goto exit; } - if (cmd_head.data[GTP_ADDR_LENGTH]) { + if (cmd_data[GTP_ADDR_LENGTH]) { pr_debug("gtp enter rawdiff."); ts->gtp_rawdiff_mode = true; } else { @@ -452,11 +452,11 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, ret = -EINVAL; goto exit; } - memset(cmd_head.data, 0, cmd_head.data_len + 1); - memcpy(cmd_head.data, &userbuf[CMD_HEAD_LENGTH], + memset(cmd_data, 0, cmd_head.data_len + 1); + memcpy(cmd_data, &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); - if (gup_update_proc((void *)cmd_head.data) == FAIL) { + if (gup_update_proc((void *)cmd_data) == FAIL) { ret = -EBUSY; goto exit; } @@ -464,10 +464,8 @@ static s32 goodix_tool_write(struct file *filp, const char __user *userbuf, ret = CMD_HEAD_LENGTH; exit: - dataptr = cmd_head.data; memset(&cmd_head, 0, sizeof(cmd_head)); cmd_head.wr = 0xFF; - cmd_head.data = dataptr; mutex_unlock(&lock); return ret; @@ -507,10 +505,10 @@ static s32 goodix_tool_read(struct file *file, char __user *user_buf, /* Need interrupt! */ } - memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len); + memcpy(cmd_data, cmd_head.addr, cmd_head.addr_len); - pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0], - cmd_head.data[1]); + pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_data[0], + cmd_data[1]); pr_debug("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); @@ -527,13 +525,13 @@ static s32 goodix_tool_read(struct file *file, char __user *user_buf, if (data_len > count) data_len = count; - if (tool_i2c_read(cmd_head.data, data_len) <= 0) { + if (tool_i2c_read(cmd_data, data_len) <= 0) { dev_err(>_client->dev, "Read data failed!\n"); ret = -EIO; goto exit; } ret = simple_read_from_buffer(user_buf, count, ppos, - &cmd_head.data[GTP_ADDR_LENGTH], data_len); + &cmd_data[GTP_ADDR_LENGTH], data_len); break; case GTP_RW_FILL_INFO: ret = fill_update_info(user_buf, count, ppos); @@ -568,13 +566,13 @@ s32 init_wr_node(struct i2c_client *client) gt_client = client; memset(&cmd_head, 0, sizeof(cmd_head)); - cmd_head.data = NULL; + cmd_data = NULL; i = GTP_I2C_RETRY_5; - while ((!cmd_head.data) && i) { - cmd_head.data = devm_kzalloc(&client->dev, + while ((!cmd_data) && i) { + cmd_data = devm_kzalloc(&client->dev, i * DATA_LENGTH_UINT, GFP_KERNEL); - if (cmd_head.data) + if (cmd_data) break; i--; } From fbd87bf263c5116ad9a113804145d2206ab8958f Mon Sep 17 00:00:00 2001 From: Gaoxiang Chen Date: Tue, 21 Mar 2017 03:38:19 -0700 Subject: [PATCH 208/210] msm: sensor: validating the flash initialization parameters Copying the flash initialization parameters from userspace memory to kernel memory and in turn checking for the validity of the flash initialization parameters pointer sent from userspace. CRs-Fixed: 1068903 Change-Id: I17d57016c254fb6628844a152b0e7d45c0b23b2d Signed-off-by: Gaoxiang Chen --- .../msm/camera_v2/sensor/flash/msm_flash.c | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index fa84829461e1..3b8dbeded441 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -523,6 +523,42 @@ static int32_t msm_flash_init( return 0; } +#ifdef CONFIG_COMPAT +static int32_t msm_flash_init_prepare( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + return msm_flash_init(flash_ctrl, flash_data); +} +#else +static int32_t msm_flash_init_prepare( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + struct msm_flash_cfg_data_t flash_data_k; + struct msm_flash_init_info_t flash_init_info; + int32_t i = 0; + + flash_data_k.cfg_type = flash_data->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data_k.flash_current[i] = + flash_data->flash_current[i]; + flash_data_k.flash_duration[i] = + flash_data->flash_duration[i]; + } + + flash_data_k.cfg.flash_init_info = &flash_init_info; + if (copy_from_user(&flash_init_info, + (void *)(flash_data->cfg.flash_init_info), + sizeof(struct msm_flash_init_info_t))) { + pr_err("%s copy_from_user failed %d\n", + __func__, __LINE__); + return -EFAULT; + } + return msm_flash_init(flash_ctrl, &flash_data_k); +} +#endif + static int32_t msm_flash_low( struct msm_flash_ctrl_t *flash_ctrl, struct msm_flash_cfg_data_t *flash_data) @@ -629,7 +665,7 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, switch (flash_data->cfg_type) { case CFG_FLASH_INIT: - rc = msm_flash_init(flash_ctrl, flash_data); + rc = msm_flash_init_prepare(flash_ctrl, flash_data); break; case CFG_FLASH_RELEASE: if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) From aa4d1a794ca2e5d8b8a62c0ce5e246393d8c668a Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 210/210] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; };