From: Taniya Das tdas@codeaurora.org
[ Upstream commit 21ea4b62e1f3dc258001a68da98c9663a9dbd6c7 ]
In case of update config failure, return -EBUSY, so that consumers could handle the failure gracefully.
Signed-off-by: Taniya Das tdas@codeaurora.org Link: https://lkml.kernel.org/r/1557339895-21952-2-git-send-email-tdas@codeaurora.... Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/clk/qcom/clk-rcg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index a93439242565d..2e23f8754f8ed 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -112,7 +112,7 @@ static int update_config(struct clk_rcg2 *rcg) }
WARN(1, "%s: rcg didn't update its configuration.", name); - return 0; + return -EBUSY; }
static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
From: Rob Clark robdclark@chromium.org
[ Upstream commit 0036bc73ccbe7e600a3468bf8e8879b122252274 ]
Recently splats like this started showing up:
WARNING: CPU: 4 PID: 251 at drivers/iommu/dma-iommu.c:451 __iommu_dma_unmap+0xb8/0xc0 Modules linked in: ath10k_snoc ath10k_core fuse msm ath mac80211 uvcvideo cfg80211 videobuf2_vmalloc videobuf2_memops vide CPU: 4 PID: 251 Comm: kworker/u16:4 Tainted: G W 5.2.0-rc5-next-20190619+ #2317 Hardware name: LENOVO 81JL/LNVNB161216, BIOS 9UCN23WW(V1.06) 10/25/2018 Workqueue: msm msm_gem_free_work [msm] pstate: 80c00005 (Nzcv daif +PAN +UAO) pc : __iommu_dma_unmap+0xb8/0xc0 lr : __iommu_dma_unmap+0x54/0xc0 sp : ffff0000119abce0 x29: ffff0000119abce0 x28: 0000000000000000 x27: ffff8001f9946648 x26: ffff8001ec271068 x25: 0000000000000000 x24: ffff8001ea3580a8 x23: ffff8001f95ba010 x22: ffff80018e83ba88 x21: ffff8001e548f000 x20: fffffffffffff000 x19: 0000000000001000 x18: 00000000c00001fe x17: 0000000000000000 x16: 0000000000000000 x15: ffff000015b70068 x14: 0000000000000005 x13: 0003142cc1be1768 x12: 0000000000000001 x11: ffff8001f6de9100 x10: 0000000000000009 x9 : ffff000015b78000 x8 : 0000000000000000 x7 : 0000000000000001 x6 : fffffffffffff000 x5 : 0000000000000fff x4 : ffff00001065dbc8 x3 : 000000000000000d x2 : 0000000000001000 x1 : fffffffffffff000 x0 : 0000000000000000 Call trace: __iommu_dma_unmap+0xb8/0xc0 iommu_dma_unmap_sg+0x98/0xb8 put_pages+0x5c/0xf0 [msm] msm_gem_free_work+0x10c/0x150 [msm] process_one_work+0x1e0/0x330 worker_thread+0x40/0x438 kthread+0x12c/0x130 ret_from_fork+0x10/0x18 ---[ end trace afc0dc5ab81a06bf ]---
Not quite sure what triggered that, but we really shouldn't be abusing dma_{map,unmap}_sg() for cache maint.
Cc: Stephen Boyd sboyd@kernel.org Tested-by: Stephen Boyd swboyd@chromium.org Reviewed-by: Jordan Crouse jcrouse@codeaurora.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sean Paul seanpaul@chromium.org Link: https://patchwork.freedesktop.org/patch/msgid/20190630124735.27786-1-robdcla... Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/gpu/drm/msm/msm_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index f2df718af370d..3a91ccd92c473 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -108,7 +108,7 @@ static struct page **get_pages(struct drm_gem_object *obj) * because display controller, GPU, etc. are not coherent: */ if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_map_sg(dev->dev, msm_obj->sgt->sgl, + dma_sync_sg_for_device(dev->dev, msm_obj->sgt->sgl, msm_obj->sgt->nents, DMA_BIDIRECTIONAL); }
@@ -138,7 +138,7 @@ static void put_pages(struct drm_gem_object *obj) * GPU, etc. are not coherent: */ if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, + dma_sync_sg_for_cpu(obj->dev->dev, msm_obj->sgt->sgl, msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
From: Arun KS arunks@codeaurora.org
[ Upstream commit 61cf61d81e326163ce1557ceccfca76e11d0e57c ]
__early_cpu_boot_status is of type long. Use quad assembler directive to allocate proper size.
Acked-by: Mark Rutland mark.rutland@arm.com Signed-off-by: Arun KS arunks@codeaurora.org Signed-off-by: Will Deacon will.deacon@arm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm64/kernel/head.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 9c00fd2acc2a4..bd24c8aed6120 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -558,7 +558,7 @@ ENTRY(__boot_cpu_mode) * with MMU turned off. */ ENTRY(__early_cpu_boot_status) - .long 0 + .quad 0
.popsection
From: Hans Verkuil hans.verkuil@cisco.com
[ Upstream commit a4c30a4861c54af78c4eb8b7855524c1a96d9f80 ]
When parsing the reply of a DP_REMOTE_DPCD_READ DPCD command the result is wrong due to a missing idx increment.
This was never noticed since DP_REMOTE_DPCD_READ is currently not used, but if you enable it, then it is all wrong.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Reviewed-by: Lyude Paul lyude@redhat.com Acked-by: Alex Deucher alexander.deucher@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/e72ddac2-1dc0-100a-d816-9ac98a... Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/gpu/drm/drm_dp_mst_topology.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 9d94c306c8ca1..a4bf98e6af57d 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -433,6 +433,7 @@ static bool drm_dp_sideband_parse_remote_dpcd_read(struct drm_dp_sideband_msg_rx if (idx > raw->curlen) goto fail_len; repmsg->u.remote_dpcd_read_ack.num_bytes = raw->msg[idx]; + idx++; if (idx > raw->curlen) goto fail_len;
From: Joe Moriarty joe.moriarty@oracle.com
[ Upstream commit 22a07038c0eaf4d1315a493ce66dcd255accba19 ]
The Parfait (version 2.1.0) static code analysis tool found the following NULL pointer derefernce problem.
- drivers/gpu/drm/drm_dp_mst_topology.c The call to drm_dp_calculate_rad() in function drm_dp_port_setup_pdt() could result in a NULL pointer being returned to port->mstb due to a failure to allocate memory for port->mstb.
Signed-off-by: Joe Moriarty joe.moriarty@oracle.com Reviewed-by: Steven Sistare steven.sistare@oracle.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20180212195144.98323-3-joe.mor... Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/gpu/drm/drm_dp_mst_topology.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index a4bf98e6af57d..9f67e1c8474bc 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1054,10 +1054,12 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port) lct = drm_dp_calculate_rad(port, rad);
port->mstb = drm_dp_add_mst_branch_device(lct, rad); - port->mstb->mgr = port->mgr; - port->mstb->port_parent = port; + if (port->mstb) { + port->mstb->mgr = port->mgr; + port->mstb->port_parent = port;
- send_link = true; + send_link = true; + } break; } return send_link;
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit 4c8326d5ebb0de3191e98980c80ab644026728d0 ]
When exposing data access through debugfs, the correct debugfs_create_*() functions must be used, matching the data types.
Remove all casts from data pointers passed to debugfs_create_*() functions, as such casts prevent the compiler from flagging bugs.
clk_core.rate and .accuracy are "unsigned long", hence casting their addresses to "u32 *" exposed the wrong halves on big-endian 64-bit systems. Fix this by using debugfs_create_ulong() instead.
Octal permissions are preferred, as they are easier to read than symbolic permissions. Hence replace "S_IRUGO" by "0444" throughout.
Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be [sboyd@codeaurora.org: Squash the octal change in too] Signed-off-by: Stephen Boyd sboyd@codeaurora.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/clk/clk.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8341a128dab1d..44b6f23cc851d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2172,18 +2172,16 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
core->dentry = d;
- d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry, - (u32 *)&core->rate); + d = debugfs_create_ulong("clk_rate", 0444, core->dentry, &core->rate); if (!d) goto err_out;
- d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry, - (u32 *)&core->accuracy); + d = debugfs_create_ulong("clk_accuracy", 0444, core->dentry, + &core->accuracy); if (!d) goto err_out;
- d = debugfs_create_u32("clk_phase", S_IRUGO, core->dentry, - (u32 *)&core->phase); + d = debugfs_create_u32("clk_phase", 0444, core->dentry, &core->phase); if (!d) goto err_out;
@@ -2192,23 +2190,23 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) if (!d) goto err_out;
- d = debugfs_create_u32("clk_prepare_count", S_IRUGO, core->dentry, - (u32 *)&core->prepare_count); + d = debugfs_create_u32("clk_prepare_count", 0444, core->dentry, + &core->prepare_count); if (!d) goto err_out;
- d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry, - (u32 *)&core->enable_count); + d = debugfs_create_u32("clk_enable_count", 0444, core->dentry, + &core->enable_count); if (!d) goto err_out;
- d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry, - (u32 *)&core->notifier_count); + d = debugfs_create_u32("clk_notifier_count", 0444, core->dentry, + &core->notifier_count); if (!d) goto err_out;
if (core->num_parents > 1) { - d = debugfs_create_file("clk_possible_parents", S_IRUGO, + d = debugfs_create_file("clk_possible_parents", 0444, core->dentry, core, &possible_parents_fops); if (!d) goto err_out; @@ -2304,22 +2302,22 @@ static int __init clk_debug_init(void) if (!rootdir) return -ENOMEM;
- d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists, + d = debugfs_create_file("clk_summary", 0444, rootdir, &all_lists, &clk_summary_fops); if (!d) return -ENOMEM;
- d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists, + d = debugfs_create_file("clk_dump", 0444, rootdir, &all_lists, &clk_dump_fops); if (!d) return -ENOMEM;
- d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir, + d = debugfs_create_file("clk_orphan_summary", 0444, rootdir, &orphan_list, &clk_summary_fops); if (!d) return -ENOMEM;
- d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir, + d = debugfs_create_file("clk_orphan_dump", 0444, rootdir, &orphan_list, &clk_dump_fops); if (!d) return -ENOMEM;
From: Timur Tabi timur@codeaurora.org
[ Upstream commit 1ca2a92b2a99323f666f1b669b7484df4bda05e4 ]
This reverts commit 72d3200061776264941be1b5a9bb8e926b3b30a5.
We cannot blindly query the direction of all GPIOs when the pins are first registered. The get_direction callback normally triggers a read/write to hardware, but we shouldn't be touching the hardware for an individual GPIO until after it's been properly claimed.
Signed-off-by: Timur Tabi timur@codeaurora.org Reviewed-by: Stephen Boyd sboyd@codeaurora.org Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/gpio/gpiolib.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f0777a7a4305b..d5b42cc86d718 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1245,31 +1245,14 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) struct gpio_desc *desc = &gdev->descs[i];
desc->gdev = gdev; - /* - * REVISIT: most hardware initializes GPIOs as inputs - * (often with pullups enabled) so power usage is - * minimized. Linux code should set the gpio direction - * first thing; but until it does, and in case - * chip->get_direction is not set, we may expose the - * wrong direction in sysfs. - */ - - if (chip->get_direction) { - /* - * If we have .get_direction, set up the initial - * direction flag from the hardware. - */ - int dir = chip->get_direction(chip, i);
- if (!dir) - set_bit(FLAG_IS_OUT, &desc->flags); - } else if (!chip->direction_input) { - /* - * If the chip lacks the .direction_input callback - * we logically assume all lines are outputs. - */ - set_bit(FLAG_IS_OUT, &desc->flags); - } + /* REVISIT: most hardware initializes GPIOs as inputs (often + * with pullups enabled) so power usage is minimized. Linux + * code should set the gpio direction first thing; but until + * it does, and in case chip->get_direction is not set, we may + * expose the wrong direction in sysfs. + */ + desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0; }
#ifdef CONFIG_PINCTRL
From: Xu YiPing xuyiping@hisilicon.com
[ Upstream commit f8ada189550984ee21f27be736042b74a7da1d68 ]
bus access read/write events are not supported in A73, based on the Cortex-A73 TRM r0p2, section 11.9 Events (pages 11-457 to 11-460).
Fixes: 5561b6c5e981 "arm64: perf: add support for Cortex-A73" Acked-by: Julien Thierry julien.thierry@arm.com Signed-off-by: Xu YiPing xuyiping@hisilicon.com Signed-off-by: Will Deacon will.deacon@arm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm64/kernel/perf_event.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 05fdae70e9f6e..53df84b2a07f4 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -262,12 +262,6 @@ static const unsigned armv8_a73_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD, [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR, - - [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD, - [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR, - - [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD, - [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR, };
static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
From: Will Deacon will.deacon@arm.com
[ Upstream commit a25ffd3a6302a67814280274d8f1aa4ae2ea4b59 ]
Printing raw pointer values in backtraces has potential security implications and are of questionable value anyway.
This patch follows x86's lead and removes the "Exception stack:" dump from kernel backtraces, as well as converting PC/LR values to symbols such as "sysrq_handle_crash+0x20/0x30".
Tested-by: Laura Abbott labbott@redhat.com Signed-off-by: Will Deacon will.deacon@arm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- arch/arm64/kernel/process.c | 8 ++--- arch/arm64/kernel/traps.c | 65 ++----------------------------------- 2 files changed, 6 insertions(+), 67 deletions(-)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 243fd247d04e0..4cbf571f428cd 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -186,11 +186,9 @@ void __show_regs(struct pt_regs *regs) }
show_regs_print_info(KERN_DEFAULT); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - print_symbol("LR is at %s\n", lr); - printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", - regs->pc, lr, regs->pstate); - printk("sp : %016llx\n", sp); + print_symbol("pc : %s\n", regs->pc); + print_symbol("lr : %s\n", lr); + printk("sp : %016llx pstate : %08llx\n", sp, regs->pstate);
i = top_reg;
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 5ae9c86c30d1d..b30d23431fe11 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -59,55 +59,9 @@ static const char *handler[]= {
int show_unhandled_signals = 0;
-/* - * Dump out the contents of some kernel memory nicely... - */ -static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - unsigned long top) -{ - unsigned long first; - mm_segment_t fs; - int i; - - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - printk("%s%s(0x%016lx to 0x%016lx)\n", lvl, str, bottom, top); - - for (first = bottom & ~31; first < top; first += 32) { - unsigned long p; - char str[sizeof(" 12345678") * 8 + 1]; - - memset(str, ' ', sizeof(str)); - str[sizeof(str) - 1] = '\0'; - - for (p = first, i = 0; i < (32 / 8) - && p < top; i++, p += 8) { - if (p >= bottom && p < top) { - unsigned long val; - - if (__get_user(val, (unsigned long *)p) == 0) - sprintf(str + i * 17, " %016lx", val); - else - sprintf(str + i * 17, " ????????????????"); - } - } - printk("%s%04lx:%s\n", lvl, first & 0xffff, str); - } - - set_fs(fs); -} - static void dump_backtrace_entry(unsigned long where) { - /* - * Note that 'where' can have a physical address, but it's not handled. - */ - print_ip_sym(where); + printk(" %pS\n", (void *)where); }
static void __dump_instr(const char *lvl, struct pt_regs *regs) @@ -177,10 +131,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) #endif
printk("Call trace:\n"); - while (1) { - unsigned long stack; - int ret; - + do { /* skip until specified stack frame */ if (!skip) { dump_backtrace_entry(frame.pc); @@ -195,17 +146,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) */ dump_backtrace_entry(regs->pc); } - ret = unwind_frame(tsk, &frame); - if (ret < 0) - break; - if (in_entry_text(frame.pc)) { - stack = frame.fp - offsetof(struct pt_regs, stackframe); - - if (on_accessible_stack(tsk, stack)) - dump_mem("", "Exception stack", stack, - stack + sizeof(struct pt_regs)); - } - } + } while (!unwind_frame(tsk, &frame));
put_task_stack(tsk); }
From: "Gustavo A. R. Silva" gustavo@embeddedor.com
[ Upstream commit 197410ad884eb18b31d48e9d8e64cb5a9e326f2f ]
Assign true or false to boolean variables instead of an integer value.
This issue was detected with the help of Coccinelle.
Signed-off-by: Gustavo A. R. Silva gustavo@embeddedor.com Cc: Todd Kjos tkjos@android.com Cc: Martijn Coenen maco@android.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/android/binder.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 05e75d18b4d93..afb690ed31ed9 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -249,7 +249,7 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( unsigned int cur = atomic_inc_return(&log->cur);
if (cur >= ARRAY_SIZE(log->entry)) - log->full = 1; + log->full = true; e = &log->entry[cur % ARRAY_SIZE(log->entry)]; WRITE_ONCE(e->debug_id_done, 0); /* @@ -2598,7 +2598,7 @@ static bool binder_proc_transaction(struct binder_transaction *t, target_list = &node->async_todo; wakeup = false; } else { - node->has_async_transaction = 1; + node->has_async_transaction = true; } }
@@ -3453,7 +3453,7 @@ static int binder_thread_write(struct binder_proc *proc, w = binder_dequeue_work_head_ilocked( &buf_node->async_todo); if (!w) { - buf_node->has_async_transaction = 0; + buf_node->has_async_transaction = false; } else { binder_enqueue_work_ilocked( w, &proc->todo);
From: Prasad Sodagudi psodagud@codeaurora.org
[ Upstream commit 82d8ba717ccb54dd803624db044f351b2a54d000 ]
Remove the __init annotation from free_raw_capacity() to avoid the following warning.
The function init_cpu_capacity_callback() references the function __init free_raw_capacity(). WARNING: vmlinux.o(.text+0x425cc0): Section mismatch in reference from the function init_cpu_capacity_callback() to the function .init.text:free_raw_capacity().
Signed-off-by: Prasad Sodagudi psodagud@codeaurora.org Acked-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/base/arch_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 41be9ff7d70a9..3da53cc6cf2be 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -96,7 +96,7 @@ subsys_initcall(register_cpu_capacity_sysctl); static u32 capacity_scale; static u32 *raw_capacity;
-static int __init free_raw_capacity(void) +static int free_raw_capacity(void) { kfree(raw_capacity); raw_capacity = NULL;
From: Chris Lew clew@codeaurora.org
[ Upstream commit f0beb4ba9b185d497c8efe7b349363700092aee0 ]
It is possible for the chunk sizes coming from the non RPM remote procs to not be word aligned. Remove the alignment warning and continue to read from the FIFO so execution is not stalled.
Signed-off-by: Chris Lew clew@codeaurora.org Signed-off-by: Arun Kumar Neelakantam aneela@codeaurora.org Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/rpmsg/qcom_glink_native.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 1e6253f1e070e..114481c9fba12 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -811,9 +811,6 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) return -EAGAIN; }
- if (WARN(chunk_size % 4, "Incoming data must be word aligned\n")) - return -EINVAL; - rcid = le16_to_cpu(hdr.msg.param1); spin_lock_irqsave(&glink->idr_lock, flags); channel = idr_find(&glink->rcids, rcid);
From: Karthick Gopalasubramanian kargop@codeaurora.org
[ Upstream commit 32dcfe8316cdbd885542967c0c85f5b9de78874b ]
Reset file is not used and may cause race conditions with operational driver if used.
Signed-off-by: Karthick Gopalasubramanian kargop@codeaurora.org Signed-off-by: Maya Erez merez@codeaurora.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/debugfs.c | 27 ---------------------- 1 file changed, 27 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 6db00c167d2e1..b17ecf796ed83 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -555,32 +555,6 @@ struct dentry *wil_debugfs_create_ioblob(const char *name, return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob); }
-/*---reset---*/ -static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, - size_t len, loff_t *ppos) -{ - struct wil6210_priv *wil = file->private_data; - struct net_device *ndev = wil_to_ndev(wil); - - /** - * BUG: - * this code does NOT sync device state with the rest of system - * use with care, debug only!!! - */ - rtnl_lock(); - dev_close(ndev); - ndev->flags &= ~IFF_UP; - rtnl_unlock(); - wil_reset(wil, true); - - return len; -} - -static const struct file_operations fops_reset = { - .write = wil_write_file_reset, - .open = simple_open, -}; - /*---write channel 1..4 to rxon for it, 0 to rxoff---*/ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, size_t len, loff_t *ppos) @@ -1697,7 +1671,6 @@ static const struct { {"bf", 0444, &fops_bf}, {"ssid", 0644, &fops_ssid}, {"mem_val", 0644, &fops_memread}, - {"reset", 0244, &fops_reset}, {"rxon", 0244, &fops_rxon}, {"tx_mgmt", 0244, &fops_txmgmt}, {"wmi_send", 0244, &fops_wmi},
From: Hamad Kadmany hkadmany@codeaurora.org
[ Upstream commit 6ccae584014ef7074359eb4151086beef66ecfa9 ]
Firmware ready event may take longer than current timeout in some scenarios, for example with multiple RFs connected where each requires an initial calibration.
Increase the timeout to support these scenarios.
Signed-off-by: Hamad Kadmany hkadmany@codeaurora.org Signed-off-by: Maya Erez merez@codeaurora.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index bac829aa950d5..a3dc42841526f 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -871,7 +871,7 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err)
static int wil_wait_for_fw_ready(struct wil6210_priv *wil) { - ulong to = msecs_to_jiffies(1000); + ulong to = msecs_to_jiffies(2000); ulong left = wait_for_completion_timeout(&wil->wmi_ready, to);
if (0 == left) {
From: Dedy Lansky dlansky@codeaurora.org
[ Upstream commit 6d9eb7ebae3d7e951bc0999235ae7028eb4cae4f ]
For negative temperatures, "temp" debugfs is showing wrong values. Use signed types so proper calculations is done for sub zero temperatures.
Signed-off-by: Dedy Lansky dlansky@codeaurora.org Signed-off-by: Maya Erez merez@codeaurora.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/debugfs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index b17ecf796ed83..feb2701280139 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1067,7 +1067,7 @@ static const struct file_operations fops_ssid = { };
/*---------temp------------*/ -static void print_temp(struct seq_file *s, const char *prefix, u32 t) +static void print_temp(struct seq_file *s, const char *prefix, s32 t) { switch (t) { case 0: @@ -1075,7 +1075,8 @@ static void print_temp(struct seq_file *s, const char *prefix, u32 t) seq_printf(s, "%s N/A\n", prefix); break; default: - seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000); + seq_printf(s, "%s %s%d.%03d\n", prefix, (t < 0 ? "-" : ""), + abs(t / 1000), abs(t % 1000)); break; } } @@ -1083,7 +1084,7 @@ static void print_temp(struct seq_file *s, const char *prefix, u32 t) static int wil_temp_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; - u32 t_m, t_r; + s32 t_m, t_r; int rc = wmi_get_temperature(wil, &t_m, &t_r);
if (rc) {
From: Venkat Gopalakrishnan venkatg@codeaurora.org
[ Upstream commit 7f6ba4f12e6cbfdefbb95cfd8fc67ece6c15d799 ]
As multiple requests are submitted to the ufs host controller in parallel there could be instances where the command completion interrupt arrives later for a request that is already processed earlier as the corresponding doorbell was cleared when handling the previous interrupt. Read the interrupt status in a loop after processing the received interrupt to catch such interrupts and handle it.
Signed-off-by: Venkat Gopalakrishnan venkatg@codeaurora.org Signed-off-by: Asutosh Das asutoshd@codeaurora.org Reviewed-by: Subhash Jadavani subhashj@codeaurora.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/scsi/ufs/ufshcd.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d25082e573e0a..059ae83412068 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5363,19 +5363,30 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) u32 intr_status, enabled_intr_status; irqreturn_t retval = IRQ_NONE; struct ufs_hba *hba = __hba; + int retries = hba->nutrs;
spin_lock(hba->host->host_lock); intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS); - enabled_intr_status = - intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
- if (intr_status) - ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS); + /* + * There could be max of hba->nutrs reqs in flight and in worst case + * if the reqs get finished 1 by 1 after the interrupt status is + * read, make sure we handle them by checking the interrupt status + * again in a loop until we process all of the reqs before returning. + */ + do { + enabled_intr_status = + intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE); + if (intr_status) + ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS); + if (enabled_intr_status) { + ufshcd_sl_intr(hba, enabled_intr_status); + retval = IRQ_HANDLED; + } + + intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS); + } while (intr_status && --retries);
- if (enabled_intr_status) { - ufshcd_sl_intr(hba, enabled_intr_status); - retval = IRQ_HANDLED; - } spin_unlock(hba->host->host_lock); return retval; }
From: Subhash Jadavani subhashj@codeaurora.org
[ Upstream commit 69a6fff068567469c0ef1156ae5ac8d3d71701f0 ]
UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION is only applicable for QCOM UFS host controller version 2.x.y and this has been fixed from version 3.x.y onwards, hence this change removes this quirk for version 3.x.y onwards.
[mkp: applied by hand]
Signed-off-by: Subhash Jadavani subhashj@codeaurora.org Signed-off-by: Asutosh Das asutoshd@codeaurora.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/scsi/ufs/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index c87d770b519a7..f2b8de195d8af 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1094,7 +1094,7 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC; }
- if (host->hw_ver.major >= 0x2) { + if (host->hw_ver.major == 0x2) { hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION;
if (!ufs_qcom_cap_qunipro(host))
From: Dedy Lansky dlansky@codeaurora.org
[ Upstream commit 3d6b72729cc2933906de8d2c602ae05e920b2122 ]
wil_err inside wil_rx_refill can flood the log buffer. Replace it with wil_err_ratelimited.
Signed-off-by: Dedy Lansky dlansky@codeaurora.org Signed-off-by: Maya Erez merez@codeaurora.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/txrx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 16750056b8b52..b483c42660971 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -636,8 +636,8 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) v->swtail = next_tail) { rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); if (unlikely(rc)) { - wil_err(wil, "Error %d in wil_rx_refill[%d]\n", - rc, v->swtail); + wil_err_ratelimited(wil, "Error %d in rx refill[%d]\n", + rc, v->swtail); break; } }
From: Arvind Yadav arvind.yadav.cs@gmail.com
[ Upstream commit a9011726c4bb37e5d6a7279bf47fcc19cd9d3e1a ]
if device_register() returned an error! Always use put_device() to give up the reference initialized. And unregister device for other return error.
Signed-off-by: Arvind Yadav arvind.yadav.cs@gmail.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/rpmsg/qcom_glink_smem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 53b3a43160f47..b1c15c64cdec3 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -216,6 +216,7 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, ret = device_register(dev); if (ret) { pr_err("failed to register glink edge\n"); + put_device(dev); return ERR_PTR(ret); }
@@ -298,7 +299,7 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, return glink;
err_put_dev: - put_device(dev); + device_unregister(dev);
return ERR_PTR(ret); }
From: Mohit Aggarwal maggarwa@codeaurora.org
[ Upstream commit 83220bf38b77a830f8e62ab1a0d0408304f9b966 ]
In order to set time in rtc, need to disable rtc hw before writing into rtc registers.
Also fixes disabling of alarm while setting rtc time.
Signed-off-by: Mohit Aggarwal maggarwa@codeaurora.org Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/rtc/rtc-pm8xxx.c | 49 +++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-)
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index a1b4b0ed1f196..3b619b7b2c530 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -74,16 +74,18 @@ struct pm8xxx_rtc { /* * Steps to write the RTC registers. * 1. Disable alarm if enabled. - * 2. Write 0x00 to LSB. - * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. - * 4. Enable alarm if disabled in step 1. + * 2. Disable rtc if enabled. + * 3. Write 0x00 to LSB. + * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0]. + * 5. Enable rtc if disabled in step 2. + * 6. Enable alarm if disabled in step 1. */ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) { int rc, i; unsigned long secs, irq_flags; - u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0; - unsigned int ctrl_reg; + u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0; + unsigned int ctrl_reg, rtc_ctrl_reg; struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
@@ -92,23 +94,38 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_tm_to_time(tm, &secs);
+ dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); + for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { value[i] = secs & 0xFF; secs >>= 8; }
- dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); - spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
- rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg); + rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); if (rc) goto rtc_rw_fail;
if (ctrl_reg & regs->alarm_en) { alarm_enabled = 1; ctrl_reg &= ~regs->alarm_en; - rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); + rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); + if (rc) { + dev_err(dev, "Write to RTC Alarm control register failed\n"); + goto rtc_rw_fail; + } + } + + /* Disable RTC H/w before writing on RTC register */ + rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg); + if (rc) + goto rtc_rw_fail; + + if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) { + rtc_disabled = 1; + rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE; + rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg); if (rc) { dev_err(dev, "Write to RTC control register failed\n"); goto rtc_rw_fail; @@ -137,11 +154,21 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) goto rtc_rw_fail; }
+ /* Enable RTC H/w after writing on RTC register */ + if (rtc_disabled) { + rtc_ctrl_reg |= PM8xxx_RTC_ENABLE; + rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg); + if (rc) { + dev_err(dev, "Write to RTC control register failed\n"); + goto rtc_rw_fail; + } + } + if (alarm_enabled) { ctrl_reg |= regs->alarm_en; - rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); + rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); if (rc) { - dev_err(dev, "Write to RTC control register failed\n"); + dev_err(dev, "Write to RTC Alarm control register failed\n"); goto rtc_rw_fail; } }
From: Subash Abhinov Kasiviswanathan subashab@codeaurora.org
[ Upstream commit 6e010dd9b16b1a320bbf8312359ac294d7e1d9a8 ]
Fix warnings which were reported when running with sparse (make C=1 CF=-D__CHECK_ENDIAN__)
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c:81:15: warning: cast to restricted __be16 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c:271:37: warning: incorrect type in assignment (different base types) expected unsigned short [unsigned] [usertype] pkt_len got restricted __be16 [usertype] <noident> drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c:287:29: warning: incorrect type in assignment (different base types) expected unsigned short [unsigned] [usertype] pkt_len got restricted __be16 [usertype] <noident> drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c:310:22: warning: cast to restricted __be16 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c:319:13: warning: cast to restricted __be16 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c:49:18: warning: cast to restricted __be16 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c:50:18: warning: cast to restricted __be32 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c:74:21: warning: cast to restricted __be16
Signed-off-by: Subash Abhinov Kasiviswanathan subashab@codeaurora.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h index ce2302c25b128..41fa881e4540e 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h @@ -23,8 +23,8 @@ struct rmnet_map_control_command { struct { u16 ip_family:2; u16 reserved:14; - u16 flow_control_seq_num; - u32 qos_id; + __be16 flow_control_seq_num; + __be32 qos_id; } flow_control; u8 data[0]; }; @@ -53,7 +53,7 @@ struct rmnet_map_header { u8 reserved_bit:1; u8 cd_bit:1; u8 mux_id; - u16 pkt_len; + __be16 pkt_len; } __aligned(1);
#define RMNET_MAP_GET_MUX_ID(Y) (((struct rmnet_map_header *) \
From: Wei Yongjun weiyongjun1@huawei.com
[ Upstream commit fb416f69900773d5a6030c909114099f92d07ab9 ]
qcom_glink_alloc_channel() allocates the mutex but not initialize it. Use mutex_init() on it to initialize it correctly.
This is detected by Coccinelle semantic patch.
Signed-off-by: Wei Yongjun weiyongjun1@huawei.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/rpmsg/qcom_glink_native.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 114481c9fba12..7802663efe332 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -221,6 +221,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, /* Setup glink internal glink_channel data */ spin_lock_init(&channel->recv_lock); spin_lock_init(&channel->intent_lock); + mutex_init(&channel->intent_req_lock);
channel->glink = glink; channel->name = kstrdup(name, GFP_KERNEL);
From: Bjorn Andersson bjorn.andersson@linaro.org
[ Upstream commit 9d32497361ff89d2fc8306407de6f04b2bfb2836 ]
Ensure the ordering of the fifo write and the update of the write index, so that the index is not updated before the data has landed in the fifo.
Acked-By: Chris Lew clew@codeaurora.org Reported-by: Arun Kumar Neelakantam aneela@codeaurora.org Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/rpmsg/qcom_glink_smem.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index b1c15c64cdec3..c2a4467b5fcdf 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -185,6 +185,9 @@ static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe, if (head >= pipe->native.length) head -= pipe->native.length;
+ /* Ensure ordering of fifo and head update */ + wmb(); + *pipe->head = cpu_to_le32(head); }
From: Lazar Alexei qca_ailizaro@qca.qualcomm.com
[ Upstream commit 680c242dc25e036265793edc7d755cfc15afd231 ]
In case of interface down, radio is turned off but PCIe mastering is not cleared. This can cause unexpected PCIe access to the shutdown device. Fix this by clearing PCIe mastering also in case interface is down
Signed-off-by: Lazar Alexei qca_ailizaro@qca.qualcomm.com Signed-off-by: Maya Erez qca_merez@qca.qualcomm.com Signed-off-by: Kalle Valo kvalo@qca.qualcomm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/pcie_bus.c | 24 +++++++++++++-------- drivers/net/wireless/ath/wil6210/pm.c | 10 ++------- drivers/net/wireless/ath/wil6210/wil6210.h | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 6a3ab4bf916dd..b2c3cf6db8814 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -393,6 +393,9 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) int rc = 0; struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); + struct net_device *ndev = wil_to_ndev(wil); + bool keep_radio_on = ndev->flags & IFF_UP && + wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
@@ -400,14 +403,14 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) if (rc) goto out;
- rc = wil_suspend(wil, is_runtime); + rc = wil_suspend(wil, is_runtime, keep_radio_on); if (!rc) { wil->suspend_stats.successful_suspends++;
- /* If platform device supports keep_radio_on_during_sleep - * it will control PCIe master + /* In case radio stays on, platform device will control + * PCIe master */ - if (!wil->keep_radio_on_during_sleep) + if (!keep_radio_on) /* disable bus mastering */ pci_clear_master(pdev); } @@ -420,20 +423,23 @@ static int wil6210_resume(struct device *dev, bool is_runtime) int rc = 0; struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); + struct net_device *ndev = wil_to_ndev(wil); + bool keep_radio_on = ndev->flags & IFF_UP && + wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
- /* If platform device supports keep_radio_on_during_sleep it will - * control PCIe master + /* In case radio stays on, platform device will control + * PCIe master */ - if (!wil->keep_radio_on_during_sleep) + if (!keep_radio_on) /* allow master */ pci_set_master(pdev); - rc = wil_resume(wil, is_runtime); + rc = wil_resume(wil, is_runtime, keep_radio_on); if (rc) { wil_err(wil, "device failed to resume (%d)\n", rc); wil->suspend_stats.failed_resumes++; - if (!wil->keep_radio_on_during_sleep) + if (!keep_radio_on) pci_clear_master(pdev); } else { wil->suspend_stats.successful_resumes++; diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index 8f5d1b447aaa2..8378742ecd49d 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c @@ -279,12 +279,9 @@ static int wil_resume_radio_off(struct wil6210_priv *wil) return rc; }
-int wil_suspend(struct wil6210_priv *wil, bool is_runtime) +int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on) { int rc = 0; - struct net_device *ndev = wil_to_ndev(wil); - bool keep_radio_on = ndev->flags & IFF_UP && - wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
@@ -307,12 +304,9 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime) return rc; }
-int wil_resume(struct wil6210_priv *wil, bool is_runtime) +int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on) { int rc = 0; - struct net_device *ndev = wil_to_ndev(wil); - bool keep_radio_on = ndev->flags & IFF_UP && - wil->keep_radio_on_during_sleep; unsigned long long suspend_time_usec = 0;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 315ec8b596628..c5b6b783100aa 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1000,8 +1000,8 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name, bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); -int wil_suspend(struct wil6210_priv *wil, bool is_runtime); -int wil_resume(struct wil6210_priv *wil, bool is_runtime); +int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on); +int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on); bool wil_is_wmi_idle(struct wil6210_priv *wil); int wmi_resume(struct wil6210_priv *wil); int wmi_suspend(struct wil6210_priv *wil);
From: Lior David qca_liord@qca.qualcomm.com
[ Upstream commit 705d2fde94b23cd76efbeedde643ffa7c32fac7f ]
When loading FW from file add block size checks to ensure a corrupted FW file will not cause the driver to write outside the device memory.
Signed-off-by: Lior David qca_liord@qca.qualcomm.com Signed-off-by: Maya Erez qca_merez@qca.qualcomm.com Signed-off-by: Kalle Valo kvalo@qca.qualcomm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/fw_inc.c | 58 ++++++++++++++-------- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + drivers/net/wireless/ath/wil6210/wmi.c | 11 +++- 3 files changed, 49 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index e01acac88825d..7d090150187c8 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -26,14 +26,17 @@ prefix_type, rowsize, \ groupsize, buf, len, ascii)
-#define FW_ADDR_CHECK(ioaddr, val, msg) do { \ - ioaddr = wmi_buffer(wil, val); \ - if (!ioaddr) { \ - wil_err_fw(wil, "bad " msg ": 0x%08x\n", \ - le32_to_cpu(val)); \ - return -EINVAL; \ - } \ - } while (0) +static bool wil_fw_addr_check(struct wil6210_priv *wil, + void __iomem **ioaddr, __le32 val, + u32 size, const char *msg) +{ + *ioaddr = wmi_buffer_block(wil, val, size); + if (!(*ioaddr)) { + wil_err_fw(wil, "bad %s: 0x%08x\n", msg, le32_to_cpu(val)); + return false; + } + return true; +}
/** * wil_fw_verify - verify firmware file validity @@ -165,7 +168,8 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data, return -EINVAL; }
- FW_ADDR_CHECK(dst, d->addr, "address"); + if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) + return -EINVAL; wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr), s); wil_memcpy_toio_32(dst, d->data, s); @@ -197,7 +201,8 @@ static int fw_handle_fill(struct wil6210_priv *wil, const void *data, return -EINVAL; }
- FW_ADDR_CHECK(dst, d->addr, "address"); + if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) + return -EINVAL;
v = le32_to_cpu(d->value); wil_dbg_fw(wil, "fill [0x%08x] <== 0x%08x, %zu bytes\n", @@ -253,7 +258,8 @@ static int fw_handle_direct_write(struct wil6210_priv *wil, const void *data, u32 v = le32_to_cpu(block[i].value); u32 x, y;
- FW_ADDR_CHECK(dst, block[i].addr, "address"); + if (!wil_fw_addr_check(wil, &dst, block[i].addr, 0, "address")) + return -EINVAL;
x = readl(dst); y = (x & m) | (v & ~m); @@ -319,10 +325,15 @@ static int fw_handle_gateway_data(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd);
- FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); - FW_ADDR_CHECK(gwa_val, d->gateway_value_addr, "gateway_value_addr"); - FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); - FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); + if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, + "gateway_addr_addr") || + !wil_fw_addr_check(wil, &gwa_val, d->gateway_value_addr, 0, + "gateway_value_addr") || + !wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, + "gateway_cmd_addr") || + !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, + "gateway_ctrl_address")) + return -EINVAL;
wil_dbg_fw(wil, "gw addresses: addr 0x%08x val 0x%08x" " cmd 0x%08x ctl 0x%08x\n", @@ -378,12 +389,19 @@ static int fw_handle_gateway_data4(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw4 write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd);
- FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); + if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, + "gateway_addr_addr")) + return -EINVAL; for (k = 0; k < ARRAY_SIZE(block->value); k++) - FW_ADDR_CHECK(gwa_val[k], d->gateway_value_addr[k], - "gateway_value_addr"); - FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); - FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); + if (!wil_fw_addr_check(wil, &gwa_val[k], + d->gateway_value_addr[k], + 0, "gateway_value_addr")) + return -EINVAL; + if (!wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, + "gateway_cmd_addr") || + !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, + "gateway_ctrl_address")) + return -EINVAL;
wil_dbg_fw(wil, "gw4 addresses: addr 0x%08x cmd 0x%08x ctl 0x%08x\n", le32_to_cpu(d->gateway_addr_addr), diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index c5b6b783100aa..0bfd51adcc81f 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -865,6 +865,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); void wil_set_ethtoolops(struct net_device *ndev);
+void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size); void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 798516f42f2f9..6cfb820caa3ee 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -140,13 +140,15 @@ static u32 wmi_addr_remap(u32 x) /** * Check address validity for WMI buffer; remap if needed * @ptr - internal (linker) fw/ucode address + * @size - if non zero, validate the block does not + * exceed the device memory (bar) * * Valid buffer should be DWORD aligned * * return address for accessing buffer from the host; * if buffer is not valid, return NULL. */ -void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) +void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size) { u32 off; u32 ptr = le32_to_cpu(ptr_); @@ -161,10 +163,17 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) off = HOSTADDR(ptr); if (off > wil->bar_size - 4) return NULL; + if (size && ((off + size > wil->bar_size) || (off + size < off))) + return NULL;
return wil->csr + off; }
+void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) +{ + return wmi_buffer_block(wil, ptr_, 0); +} + /** * Check address validity */
From: Lior David qca_liord@qca.qualcomm.com
[ Upstream commit 26a6d5274865532502c682ff378ac8ebe2886238 ]
The current length check: sizeof(cmd) + len > r->entry_size will allow very large values of len (> U16_MAX - sizeof(cmd)) and can cause a buffer overflow. Fix the check to cover this case. In addition, ensure the mailbox entry_size is not too small, since this can also bypass the above check.
Signed-off-by: Lior David qca_liord@qca.qualcomm.com Signed-off-by: Maya Erez qca_merez@qca.qualcomm.com Signed-off-by: Kalle Valo kvalo@qca.qualcomm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/interrupt.c | 22 +++++++++++++++++++- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 59def4f3fcf3d..5cf341702dc11 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -358,6 +358,25 @@ static void wil_cache_mbox_regs(struct wil6210_priv *wil) wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); }
+static bool wil_validate_mbox_regs(struct wil6210_priv *wil) +{ + size_t min_size = sizeof(struct wil6210_mbox_hdr) + + sizeof(struct wmi_cmd_hdr); + + if (wil->mbox_ctl.rx.entry_size < min_size) { + wil_err(wil, "rx mbox entry too small (%d)\n", + wil->mbox_ctl.rx.entry_size); + return false; + } + if (wil->mbox_ctl.tx.entry_size < min_size) { + wil_err(wil, "tx mbox entry too small (%d)\n", + wil->mbox_ctl.tx.entry_size); + return false; + } + + return true; +} + static irqreturn_t wil6210_irq_misc(int irq, void *cookie) { struct wil6210_priv *wil = cookie; @@ -393,7 +412,8 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) if (isr & ISR_MISC_FW_READY) { wil_dbg_irq(wil, "IRQ: FW ready\n"); wil_cache_mbox_regs(wil); - set_bit(wil_status_mbox_ready, wil->status); + if (wil_validate_mbox_regs(wil)) + set_bit(wil_status_mbox_ready, wil->status); /** * Actual FW ready indicated by the * WMI_FW_READY_EVENTID diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 6cfb820caa3ee..22bfa10ea8276 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -231,7 +231,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) uint retry; int rc = 0;
- if (sizeof(cmd) + len > r->entry_size) { + if (len > r->entry_size - sizeof(cmd)) { wil_err(wil, "WMI size too large: %d bytes, max is %d\n", (int)(sizeof(cmd) + len), r->entry_size); return -ERANGE;
From: Hamad Kadmany qca_hkadmany@qca.qualcomm.com
[ Upstream commit 144a12a6d83f3ca34ddefce5dee4d502afd2fc5b ]
On-going operations were not aborted properly and required locks were not taken.
Signed-off-by: Hamad Kadmany qca_hkadmany@qca.qualcomm.com Signed-off-by: Maya Erez qca_merez@qca.qualcomm.com Signed-off-by: Kalle Valo kvalo@qca.qualcomm.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/net/wireless/ath/wil6210/cfg80211.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index c374ed311520e..58784e77e215b 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1735,9 +1735,12 @@ static int wil_cfg80211_suspend(struct wiphy *wiphy,
wil_dbg_pm(wil, "suspending\n");
- wil_p2p_stop_discovery(wil); - + mutex_lock(&wil->mutex); + mutex_lock(&wil->p2p_wdev_mutex); + wil_p2p_stop_radio_operations(wil); wil_abort_scan(wil, true); + mutex_unlock(&wil->p2p_wdev_mutex); + mutex_unlock(&wil->mutex);
out: return rc;
From: Chris Lew clew@codeaurora.org
[ Upstream commit a216000f0140f415cec96129f777b5234c9d142f ]
Endianness can vary in the system, add le32_to_cpu when comparing partition sizes from smem.
Signed-off-by: Chris Lew clew@codeaurora.org Acked-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Andy Gross andy.gross@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/soc/qcom/smem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 18ec52f2078aa..89dd50fa404f7 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -646,7 +646,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, return -EINVAL; }
- if (header->size != entry->size) { + if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { dev_err(smem->dev, "Partition %d has invalid size\n", i); return -EINVAL;
From: Rob Herring robh@kernel.org
[ Upstream commit bd82bbf38cbe27f2c65660da801900d71bcc5cc8 ]
The ref counting is broken for OF_DYNAMIC when sysfs is disabled because the kobject initialization is skipped. Only the properties add/remove/update should be skipped for !SYSFS config.
Tested-by: Nicolas Pitre nico@linaro.org Reviewed-by: Frank Rowand frowand.list@gmail.com Acked-by: Grant Likely grant.likely@secretlab.ca Signed-off-by: Rob Herring robh@kernel.org Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/of/base.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c index 41b254be02954..c0281be8e0611 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -169,9 +169,6 @@ int __of_attach_node_sysfs(struct device_node *np) struct property *pp; int rc;
- if (!IS_ENABLED(CONFIG_SYSFS)) - return 0; - if (!of_kset) return 0;
From: Alexander Shishkin alexander.shishkin@linux.intel.com
[ Upstream commit f25d8ba9e1b204b90fbf55970ea6e68955006068 ]
A comment is in a wrong place in perf_event_create_kernel_counter(). Fix that.
Signed-off-by: Alexander Shishkin alexander.shishkin@linux.intel.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: Arnaldo Carvalho de Melo acme@redhat.com Cc: David Ahern dsahern@gmail.com Cc: Jiri Olsa jolsa@redhat.com Cc: Linus Torvalds torvalds@linux-foundation.org Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Stephane Eranian eranian@google.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Vince Weaver vincent.weaver@maine.edu Link: https://lkml.kernel.org/r/20191030134731.5437-2-alexander.shishkin@linux.int... Signed-off-by: Ingo Molnar mingo@kernel.org Signed-off-by: Lee Jones lee.jones@linaro.org --- kernel/events/core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/events/core.c b/kernel/events/core.c index 2ac73b4cb8a93..9d8f699f11873 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -10430,10 +10430,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, struct perf_event *event; int err;
- /* - * Get the target context (task or percpu): - */ - event = perf_event_alloc(attr, cpu, task, NULL, NULL, overflow_handler, context, -1); if (IS_ERR(event)) { @@ -10444,6 +10440,9 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, /* Mark owner so we could distinguish it from user events. */ event->owner = TASK_TOMBSTONE;
+ /* + * Get the target context (task or percpu): + */ ctx = find_get_context(event->pmu, task, event); if (IS_ERR(ctx)) { err = PTR_ERR(ctx);
From: Austin Kim austindh.kim@gmail.com
[ Upstream commit 7ea362427c170061b8822dd41bafaa72b3bcb9ad ]
If !area->pages statement is true where memory allocation fails, area is freed.
In this case 'area->pages = pages' should not executed. So move 'area->pages = pages' after if statement.
[akpm@linux-foundation.org: give area->pages the same treatment] Link: http://lkml.kernel.org/r/20190830035716.GA190684@LGEARND20B15 Signed-off-by: Austin Kim austindh.kim@gmail.com Acked-by: Michal Hocko mhocko@suse.com Reviewed-by: Andrew Morton akpm@linux-foundation.org Cc: Uladzislau Rezki (Sony) urezki@gmail.com Cc: Roman Gushchin guro@fb.com Cc: Roman Penyaev rpenyaev@suse.de Cc: Rick Edgecombe rick.p.edgecombe@intel.com Cc: Mike Rapoport rppt@linux.ibm.com Cc: Andrey Ryabinin aryabinin@virtuozzo.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Lee Jones lee.jones@linaro.org --- mm/vmalloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 0b8852d80f440..30dc16d000ba0 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1682,7 +1682,6 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, nr_pages = get_vm_area_size(area) >> PAGE_SHIFT; array_size = (nr_pages * sizeof(struct page *));
- area->nr_pages = nr_pages; /* Please note that the recursion is strictly bounded. */ if (array_size > PAGE_SIZE) { pages = __vmalloc_node(array_size, 1, nested_gfp|highmem_mask, @@ -1690,13 +1689,16 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, } else { pages = kmalloc_node(array_size, nested_gfp, node); } - area->pages = pages; - if (!area->pages) { + + if (!pages) { remove_vm_area(area->addr); kfree(area); return NULL; }
+ area->pages = pages; + area->nr_pages = nr_pages; + for (i = 0; i < area->nr_pages; i++) { struct page *page;
From: Roger Quadros rogerq@ti.com
[ Upstream commit c09b73cfac2a9317f1104169045c519c6021aa1d ]
This reverts commit 6a4290cc28be1 ("usb: dwc3: gadget: set the OTG flag in dwc3 gadget driver.")
We don't yet support any of the OTG mechanisms (HNP/SRP/ADP) and are not setting gadget->otg_caps, so don't set gadget->is_otg flag.
If we do then we end up publishing a OTG1.0 descriptor in the gadget descriptor which causes device enumeration to fail if we are connected to a host with CONFIG_USB_OTG enabled.
Host side log without this patch
[ 96.720453] usb 1-1: new high-speed USB device number 2 using xhci-hcd [ 96.901391] usb 1-1: Dual-Role OTG device on non-HNP port [ 96.907552] usb 1-1: set a_alt_hnp_support failed: -32 [ 97.060447] usb 1-1: new high-speed USB device number 3 using xhci-hcd [ 97.241378] usb 1-1: Dual-Role OTG device on non-HNP port [ 97.247536] usb 1-1: set a_alt_hnp_support failed: -32 [ 97.253606] usb usb1-port1: attempt power cycle [ 97.960449] usb 1-1: new high-speed USB device number 4 using xhci-hcd [ 98.141383] usb 1-1: Dual-Role OTG device on non-HNP port [ 98.147540] usb 1-1: set a_alt_hnp_support failed: -32 [ 98.300453] usb 1-1: new high-speed USB device number 5 using xhci-hcd [ 98.481391] usb 1-1: Dual-Role OTG device on non-HNP port [ 98.487545] usb 1-1: set a_alt_hnp_support failed: -32 [ 98.493532] usb usb1-port1: unable to enumerate USB device
Signed-off-by: Roger Quadros rogerq@ti.com Signed-off-by: Felipe Balbi felipe.balbi@linux.intel.com Signed-off-by: Lee Jones lee.jones@linaro.org --- drivers/usb/dwc3/gadget.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e96b22d6fa52e..76a0020b0f2e8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3257,7 +3257,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported = true; dwc->gadget.name = "dwc3-gadget"; - dwc->gadget.is_otg = dwc->dr_mode == USB_DR_MODE_OTG;
/* * FIXME We might be setting max_speed to <SUPER, however versions
From: George Spelvin lkml@sdf.org
[ Upstream commit 043b3f7b6388fca6be86ca82979f66c5723a0d10 ]
Rather than a fixed-size array of pending sorted runs, use the ->prev links to keep track of things. This reduces stack usage, eliminates some ugly overflow handling, and reduces the code size.
Also: * merge() no longer needs to handle NULL inputs, so simplify. * The same applies to merge_and_restore_back_links(), which is renamed to the less ponderous merge_final(). (It's a static helper function, so we don't need a super-descriptive name; comments will do.) * Document the actual return value requirements on the (*cmp)() function; some callers are already using this feature.
x86-64 code size 1086 -> 739 bytes (-347)
(Yes, I see checkpatch complaining about no space after comma in "__attribute__((nonnull(2,3,4,5)))". Checkpatch is wrong.)
Feedback from Rasmus Villemoes, Andy Shevchenko and Geert Uytterhoeven.
[akpm@linux-foundation.org: remove __pure usage due to mysterious warning] Link: http://lkml.kernel.org/r/f63c410e0ff76009c9b58e01027e751ff7fdb749.1552704200... Signed-off-by: George Spelvin lkml@sdf.org Acked-by: Andrey Abramov st5pub@yandex.ru Acked-by: Rasmus Villemoes linux@rasmusvillemoes.dk Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Cc: Geert Uytterhoeven geert@linux-m68k.org Cc: Daniel Wagner daniel.wagner@siemens.com Cc: Dave Chinner dchinner@redhat.com Cc: Don Mullis don.mullis@gmail.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Lee Jones lee.jones@linaro.org --- include/linux/list_sort.h | 1 + lib/list_sort.c | 165 ++++++++++++++++++++++++-------------- 2 files changed, 104 insertions(+), 62 deletions(-)
diff --git a/include/linux/list_sort.h b/include/linux/list_sort.h index ba79956e848d5..20f178c24e9d1 100644 --- a/include/linux/list_sort.h +++ b/include/linux/list_sort.h @@ -6,6 +6,7 @@
struct list_head;
+__attribute__((nonnull(2,3))) void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, struct list_head *a, struct list_head *b)); diff --git a/lib/list_sort.c b/lib/list_sort.c index 85759928215b4..ba9431bcac0bc 100644 --- a/lib/list_sort.c +++ b/lib/list_sort.c @@ -7,33 +7,41 @@ #include <linux/list_sort.h> #include <linux/list.h>
-#define MAX_LIST_LENGTH_BITS 20 +typedef int __attribute__((nonnull(2,3))) (*cmp_func)(void *, + struct list_head const *, struct list_head const *);
/* * Returns a list organized in an intermediate format suited * to chaining of merge() calls: null-terminated, no reserved or * sentinel head node, "prev" links not maintained. */ -static struct list_head *merge(void *priv, - int (*cmp)(void *priv, struct list_head *a, - struct list_head *b), +__attribute__((nonnull(2,3,4))) +static struct list_head *merge(void *priv, cmp_func cmp, struct list_head *a, struct list_head *b) { - struct list_head head, *tail = &head; + struct list_head *head, **tail = &head;
- while (a && b) { + for (;;) { /* if equal, take 'a' -- important for sort stability */ - if ((*cmp)(priv, a, b) <= 0) { - tail->next = a; + if (cmp(priv, a, b) <= 0) { + *tail = a; + tail = &a->next; a = a->next; + if (!a) { + *tail = b; + break; + } } else { - tail->next = b; + *tail = b; + tail = &b->next; b = b->next; + if (!b) { + *tail = a; + break; + } } - tail = tail->next; } - tail->next = a?:b; - return head.next; + return head; }
/* @@ -43,44 +51,52 @@ static struct list_head *merge(void *priv, * prev-link restoration pass, or maintaining the prev links * throughout. */ -static void merge_and_restore_back_links(void *priv, - int (*cmp)(void *priv, struct list_head *a, - struct list_head *b), - struct list_head *head, - struct list_head *a, struct list_head *b) +__attribute__((nonnull(2,3,4,5))) +static void merge_final(void *priv, cmp_func cmp, struct list_head *head, + struct list_head *a, struct list_head *b) { struct list_head *tail = head; u8 count = 0;
- while (a && b) { + for (;;) { /* if equal, take 'a' -- important for sort stability */ - if ((*cmp)(priv, a, b) <= 0) { + if (cmp(priv, a, b) <= 0) { tail->next = a; a->prev = tail; + tail = a; a = a->next; + if (!a) + break; } else { tail->next = b; b->prev = tail; + tail = b; b = b->next; + if (!b) { + b = a; + break; + } } - tail = tail->next; } - tail->next = a ? : b;
+ /* Finish linking remainder of list b on to tail */ + tail->next = b; do { /* - * In worst cases this loop may run many iterations. + * If the merge is highly unbalanced (e.g. the input is + * already sorted), this loop may run many iterations. * Continue callbacks to the client even though no * element comparison is needed, so the client's cmp() * routine can invoke cond_resched() periodically. */ - if (unlikely(!(++count))) - (*cmp)(priv, tail->next, tail->next); - - tail->next->prev = tail; - tail = tail->next; - } while (tail->next); - + if (unlikely(!++count)) + cmp(priv, b, b); + b->prev = tail; + tail = b; + b = b->next; + } while (b); + + /* And the final links to make a circular doubly-linked list */ tail->next = head; head->prev = tail; } @@ -91,55 +107,80 @@ static void merge_and_restore_back_links(void *priv, * @head: the list to sort * @cmp: the elements comparison function * - * This function implements "merge sort", which has O(nlog(n)) - * complexity. + * This function implements a bottom-up merge sort, which has O(nlog(n)) + * complexity. We use depth-first order to take advantage of cacheing. + * (E.g. when we get to the fourth element, we immediately merge the + * first two 2-element lists.) + * + * The comparison funtion @cmp must return > 0 if @a should sort after + * @b ("@a > @b" if you want an ascending sort), and <= 0 if @a should + * sort before @b *or* their original order should be preserved. It is + * always called with the element that came first in the input in @a, + * and list_sort is a stable sort, so it is not necessary to distinguish + * the @a < @b and @a == @b cases. * - * The comparison function @cmp must return a negative value if @a - * should sort before @b, and a positive value if @a should sort after - * @b. If @a and @b are equivalent, and their original relative - * ordering is to be preserved, @cmp must return 0. + * This is compatible with two styles of @cmp function: + * - The traditional style which returns <0 / =0 / >0, or + * - Returning a boolean 0/1. + * The latter offers a chance to save a few cycles in the comparison + * (which is used by e.g. plug_ctx_cmp() in block/blk-mq.c). + * + * A good way to write a multi-word comparison is + * if (a->high != b->high) + * return a->high > b->high; + * if (a->middle != b->middle) + * return a->middle > b->middle; + * return a->low > b->low; */ +__attribute__((nonnull(2,3))) void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, struct list_head *a, struct list_head *b)) { - struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists - -- last slot is a sentinel */ - int lev; /* index into part[] */ - int max_lev = 0; - struct list_head *list; + struct list_head *list = head->next, *pending = NULL; + size_t count = 0; /* Count of pending */
- if (list_empty(head)) + if (list == head->prev) /* Zero or one elements */ return;
- memset(part, 0, sizeof(part)); - + /* Convert to a null-terminated singly-linked list. */ head->prev->next = NULL; - list = head->next;
- while (list) { + /* + * Data structure invariants: + * - All lists are singly linked and null-terminated; prev + * pointers are not maintained. + * - pending is a prev-linked "list of lists" of sorted + * sublists awaiting further merging. + * - Each of the sorted sublists is power-of-two in size, + * corresponding to bits set in "count". + * - Sublists are sorted by size and age, smallest & newest at front. + */ + do { + size_t bits; struct list_head *cur = list; + + /* Extract the head of "list" as a single-element list "cur" */ list = list->next; cur->next = NULL;
- for (lev = 0; part[lev]; lev++) { - cur = merge(priv, cmp, part[lev], cur); - part[lev] = NULL; + /* Do merges corresponding to set lsbits in count */ + for (bits = count; bits & 1; bits >>= 1) { + cur = merge(priv, (cmp_func)cmp, pending, cur); + pending = pending->prev; /* Untouched by merge() */ } - if (lev > max_lev) { - if (unlikely(lev >= ARRAY_SIZE(part)-1)) { - printk_once(KERN_DEBUG "list too long for efficiency\n"); - lev--; - } - max_lev = lev; - } - part[lev] = cur; + /* And place the result at the head of "pending" */ + cur->prev = pending; + pending = cur; + count++; + } while (list->next); + + /* Now merge together last element with all pending lists */ + while (pending->prev) { + list = merge(priv, (cmp_func)cmp, pending, list); + pending = pending->prev; } - - for (lev = 0; lev < max_lev; lev++) - if (part[lev]) - list = merge(priv, cmp, part[lev], list); - - merge_and_restore_back_links(priv, cmp, head, part[max_lev], list); + /* The final merge, rebuilding prev links */ + merge_final(priv, (cmp_func)cmp, head, pending, list); } EXPORT_SYMBOL(list_sort);
linux-stable-mirror@lists.linaro.org