From 3da7600ca4a66dd3442b4c23094a75857aaa1cc7 Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Tue, 3 May 2022 11:17:48 +0530 Subject: [PATCH 01/11] power: qpnp-fg-gen4: Improve SDAM corruption check Add support for 4-byte SDAM cookie, instead of 1-byte(default), to make the SDAM corruption check more accurate. Change-Id: I084c44eef08d4555896a7efb38a098420ebfec69 Signed-off-by: Kamal Wadhwa --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 32 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 1274edfb1347..033028e091b2 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "FG: %s: " fmt, __func__ @@ -30,12 +31,13 @@ #define FG_MEM_IF_PM8150B 0x0D #define FG_ADC_RR_PM8150B 0x13 -#define SDAM_COOKIE_OFFSET 0x80 #define SDAM_CYCLE_COUNT_OFFSET 0x81 #define SDAM_CAP_LEARN_OFFSET 0x91 -#define SDAM_COOKIE 0xA5 #define SDAM_FG_PARAM_LENGTH 20 +#define SDAM_COOKIE_OFFSET_4BYTE 0x95 +#define SDAM_COOKIE_4BYTE 0x12345678 + #define FG_SRAM_LEN 972 #define PROFILE_LEN 416 #define PROFILE_COMP_LEN 24 @@ -1302,7 +1304,7 @@ static int fg_gen4_store_learned_capacity(void *data, int64_t learned_cap_uah) struct fg_dev *fg; int16_t cc_mah; int rc; - u8 cookie = SDAM_COOKIE; + u32 cookie_4byte = SDAM_COOKIE_4BYTE; if (!chip) return -ENODEV; @@ -1329,8 +1331,8 @@ static int fg_gen4_store_learned_capacity(void *data, int64_t learned_cap_uah) return rc; } - rc = nvmem_device_write(chip->fg_nvmem, SDAM_COOKIE_OFFSET, 1, - &cookie); + rc = nvmem_device_write(chip->fg_nvmem, + SDAM_COOKIE_OFFSET_4BYTE, 1, &cookie_4byte); if (rc < 0) { pr_err("Error in writing cookie to SDAM, rc=%d\n", rc); return rc; @@ -2377,17 +2379,17 @@ static bool is_sdam_cookie_set(struct fg_gen4_chip *chip) { struct fg_dev *fg = &chip->fg; int rc; - u8 cookie; + u32 cookie_4byte; - rc = nvmem_device_read(chip->fg_nvmem, SDAM_COOKIE_OFFSET, 1, - &cookie); + rc = nvmem_device_read(chip->fg_nvmem, SDAM_COOKIE_OFFSET_4BYTE, 4, + &cookie_4byte); if (rc < 0) { pr_err("Error in reading SDAM_COOKIE rc=%d\n", rc); return false; } - fg_dbg(fg, FG_STATUS, "cookie: %x\n", cookie); - return (cookie == SDAM_COOKIE); + fg_dbg(fg, FG_STATUS, "cookie_4byte: %08x\n", cookie_4byte); + return (cookie_4byte == SDAM_COOKIE_4BYTE); } static void fg_gen4_clear_sdam(struct fg_gen4_chip *chip) @@ -2411,8 +2413,9 @@ static void fg_gen4_clear_sdam(struct fg_gen4_chip *chip) static void fg_gen4_post_profile_load(struct fg_gen4_chip *chip) { struct fg_dev *fg = &chip->fg; - int rc, act_cap_mah; + int rc = 0, act_cap_mah; u8 buf[16] = {0}; + u32 cookie_4byte = 0; if (chip->dt.multi_profile_load && chip->batt_age_level != chip->last_batt_age_level) { @@ -2466,6 +2469,13 @@ static void fg_gen4_post_profile_load(struct fg_gen4_chip *chip) pr_err("Error in writing learned capacity to SDAM, rc=%d\n", rc); } + + /* Set the COOKIE to prevent rechecking the SRAM again */ + cookie_4byte = SDAM_COOKIE_4BYTE; + rc = nvmem_device_write(chip->fg_nvmem, + SDAM_COOKIE_OFFSET_4BYTE, 4, (u8 *)&cookie_4byte); + if (rc < 0) + pr_err("Failed to set SDAM cookie, rc=%d\n", rc); } /* Restore the cycle counters so that it would be valid at this point */ From cd23045ae0a4fbf39acbd7b084a5dee5c52fa481 Mon Sep 17 00:00:00 2001 From: Naina Mehta Date: Mon, 29 Aug 2022 19:12:27 +0530 Subject: [PATCH 02/11] soc: qcom: socinfo: Add soc information for Khaje IOT Add SOC ID to support socinfo for Khaje IOT platform. Change-Id: Ibcc958d1f7326afeccb53c5cf6582f7f2269b46b Signed-off-by: Naina Mehta --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index c0d8ece4acbb..c53b971aecbe 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -340,6 +340,7 @@ static struct msm_soc_info cpu_of_id[] = { /* Khaje ID */ [518] = {MSM_CPU_KHAJE, "KHAJE"}, + [586] = {MSM_CPU_KHAJE, "KHAJE"}, /* Khajep ID */ [561] = {MSM_CPU_KHAJEP, "KHAJEP"}, From 2b533456cabb947c6302997c68b6137b29c70c5f Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Gattupalli Date: Tue, 6 Sep 2022 15:01:31 +0530 Subject: [PATCH 03/11] msm: adsprpc: Validate the CID Validating the CID is a valid channel number. Change-Id: Ic11a259e8a04088f54b3df4bad982e669b02ee71 Acked-by: Abhishek Singh Signed-off-by: Vamsi Krishna Gattupalli --- 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 3de040f97c27..36d218ff2b21 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1466,8 +1466,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, spin_lock(&fl->hlock); hlist_add_head(&ctx->hn, &clst->pending); - cid = (fl->cid >= ADSP_DOMAIN_ID && fl->cid < NUM_CHANNELS) - ? fl->cid : 0; + if (!(fl->cid >= ADSP_DOMAIN_ID && fl->cid < NUM_CHANNELS)) { + err = -ECHRNG; + goto bail; + } + cid = fl->cid; chan = &me->channel[cid]; spin_unlock(&fl->hlock); From 93906db14a878515e20caa671b487ad39480d6b9 Mon Sep 17 00:00:00 2001 From: Vijay Dandiga Date: Thu, 8 Sep 2022 14:38:31 +0530 Subject: [PATCH 04/11] msm_perf: check cpu_possible to improve stability check cpu_possible to improve stability Change-Id: I9ce3b5a5a6b1e846f44ffb9e255cc5b6b701b377 Signed-off-by: Gaurav Singh Signed-off-by: Vijay Dandiga --- drivers/soc/qcom/msm_performance.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 7430bb271b2d..a5767b0cb081 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -76,13 +76,15 @@ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) for (i = 0; i < ntokens; i += 2) { if (sscanf(cp, "%u:%u", &cpu, &val) != 2) return -EINVAL; - if (cpu > (num_present_cpus() - 1)) - return -EINVAL; + if (cpu >= nr_cpu_ids) + break; - i_cpu_stats = &per_cpu(msm_perf_cpu_stats, cpu); + if (cpu_possible(cpu)) { + i_cpu_stats = &per_cpu(msm_perf_cpu_stats, cpu); - i_cpu_stats->min = val; - cpumask_set_cpu(cpu, limit_mask); + i_cpu_stats->min = val; + cpumask_set_cpu(cpu, limit_mask); + } cp = strnchr(cp, strlen(cp), ' '); cp++; @@ -153,14 +155,15 @@ static int set_cpu_max_freq(const char *buf, const struct kernel_param *kp) for (i = 0; i < ntokens; i += 2) { if (sscanf(cp, "%u:%u", &cpu, &val) != 2) return -EINVAL; - if (cpu > (num_present_cpus() - 1)) - return -EINVAL; + if (cpu >= nr_cpu_ids) + break; - i_cpu_stats = &per_cpu(msm_perf_cpu_stats, cpu); - - i_cpu_stats->max = val; - cpumask_set_cpu(cpu, limit_mask); + if (cpu_possible(cpu)) { + i_cpu_stats = &per_cpu(msm_perf_cpu_stats, cpu); + i_cpu_stats->max = val; + cpumask_set_cpu(cpu, limit_mask); + } cp = strnchr(cp, strlen(cp), ' '); cp++; } From 7cdb30b02b264acf0d98b896fe5b588675746a03 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Mon, 1 Aug 2022 18:25:11 +0000 Subject: [PATCH 05/11] FROMLIST: binder: fix UAF of ref->proc caused by race condition A transaction of type BINDER_TYPE_WEAK_HANDLE can fail to increment the reference for a node. In this case, the target proc normally releases the failed reference upon close as expected. However, if the target is dying in parallel the call will race with binder_deferred_release(), so the target could have released all of its references by now leaving the cleanup of the new failed reference unhandled. The transaction then ends and the target proc gets released making the ref->proc now a dangling pointer. Later on, ref->node is closed and we attempt to take spin_lock(&ref->proc->inner_lock), which leads to the use-after-free bug reported below. Let's fix this by cleaning up the failed reference on the spot instead of relying on the target to do so. ================================================================== BUG: KASAN: use-after-free in _raw_spin_lock+0xa8/0x150 Write of size 4 at addr ffff5ca207094238 by task kworker/1:0/590 CPU: 1 PID: 590 Comm: kworker/1:0 Not tainted 5.19.0-rc8 #10 Hardware name: linux,dummy-virt (DT) Workqueue: events binder_deferred_func Call trace: dump_backtrace.part.0+0x1d0/0x1e0 show_stack+0x18/0x70 dump_stack_lvl+0x68/0x84 print_report+0x2e4/0x61c kasan_report+0xa4/0x110 kasan_check_range+0xfc/0x1a4 __kasan_check_write+0x3c/0x50 _raw_spin_lock+0xa8/0x150 binder_deferred_func+0x5e0/0x9b0 process_one_work+0x38c/0x5f0 worker_thread+0x9c/0x694 kthread+0x188/0x190 ret_from_fork+0x10/0x20 Signed-off-by: Carlos Llamas Acked-by: Christian Brauner (Microsoft) Bug: 239630375 Link: https://lore.kernel.org/all/20220801182511.3371447-1-cmllamas@google.com/ Signed-off-by: Carlos Llamas Change-Id: I5085dd0dc805a780a64c057e5819f82dd8f02868 (cherry picked from commit ae3fa5d16a02ba7c7b170e0e1ab56d6f0ba33964) Git-commit: 70f060f93cb5ace673e4c83ed451fb1de2098de1 Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: PavanKumar S.R --- drivers/android/binder.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 6a91287fe55f..38e2cacf0b4e 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1948,6 +1948,18 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, } ret = binder_inc_ref_olocked(ref, strong, target_list); *rdata = ref->data; + if (ret && ref == new_ref) { + /* + * Cleanup the failed reference here as the target + * could now be dead and have already released its + * references by now. Calling on the new reference + * with strong=0 and a tmp_refs will not decrement + * the node. The new_ref gets kfree'd below. + */ + binder_cleanup_ref_olocked(new_ref); + ref = NULL; + } + binder_proc_unlock(proc); if (new_ref && ref != new_ref) /* From 72b827866607b878888ea74f71c606c1283c3747 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 1 Mar 2022 11:04:24 +0300 Subject: [PATCH 06/11] usb: gadget: rndis: prevent integer overflow in rndis_set_response() commit 65f3324f4b6fed78b8761c3b74615ecf0ffa81fa upstream. If "BufOffset" is very large the "BufOffset + 8" operation can have an integer overflow. Change-Id: I2d68b3cc11832de13cf33f3eb56f1e8ecac4dda6 Cc: stable@kernel.org Fixes: 38ea1eac7d88 ("usb: gadget: rndis: check size of RNDIS_MSG_SET command") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20220301080424.GA17208@kili Signed-off-by: Greg Kroah-Hartman Git-commit: 138d4f739b35dfb40438a0d5d7054965763bfbe7 Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: PavanKumar S.R --- drivers/usb/gadget/function/rndis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 006aa43eb4a9..46448e845f8d 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -636,6 +636,7 @@ static int rndis_set_response(struct rndis_params *params, BufLength = le32_to_cpu(buf->InformationBufferLength); BufOffset = le32_to_cpu(buf->InformationBufferOffset); if ((BufLength > RNDIS_MAX_TOTAL_SIZE) || + (BufOffset > RNDIS_MAX_TOTAL_SIZE) || (BufOffset + 8 >= RNDIS_MAX_TOTAL_SIZE)) return -EINVAL; From 1e5ab21d52a3df63ddb17f6d2b091d499e10e140 Mon Sep 17 00:00:00 2001 From: Shivnandan Kumar Date: Tue, 13 Sep 2022 10:37:45 +0530 Subject: [PATCH 07/11] cpu-topology: Don't error on more than CONFIG_NR_CPUS CPUs in device tree When the kernel is configured with CONFIG_NR_CPUS smaller than the number of CPU nodes in the device tree(DT), all the CPU nodes parsing done to fetch topology information will fail. This is not reasonable as it is valid to have all the physical CPUs in the system in the DT. Let us just skip such CPU DT nodes that are not used in the kernel rather than returning an error. Change-Id: Ic7c50afd52741eb2a472fe33d532835f767e8d1c Signed-off-by: Shivnandan Kumar --- arch/arm64/kernel/topology.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 518ecb796b29..7962a49d192b 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -31,6 +31,16 @@ #include #include +/* + * This function returns the logic cpu number of the node. + * There are basically three kinds of return values: + * (1) logic cpu number which is > 0. + * (2) -ENODEV when the device tree(DT) node is valid and found in the DT but + * there is no possible logical CPU in the kernel to match. This happens + * when CONFIG_NR_CPUS is configure to be smaller than the number of + * CPU nodes in DT. We need to just ignore this case. + * (3) -1 if the node does not exist in the device tree + */ static int __init get_cpu_for_node(struct device_node *node) { struct device_node *cpu_node; @@ -44,8 +54,8 @@ static int __init get_cpu_for_node(struct device_node *node) if (cpu >= 0) topology_parse_cpu_capacity(cpu_node, cpu); else - pr_crit("Unable to find CPU node for %pOF\n", cpu_node); - + pr_info("CPU node for %pOF exist but the possible cpu range is :%*pbl\n", + cpu_node, cpumask_pr_args(cpu_possible_mask)); of_node_put(cpu_node); return cpu; } @@ -69,7 +79,7 @@ static int __init parse_core(struct device_node *core, int package_id, cpu_topology[cpu].package_id = package_id; cpu_topology[cpu].core_id = core_id; cpu_topology[cpu].thread_id = i; - } else { + } else if (cpu != -ENODEV) { pr_err("%pOF: Can't get CPU for thread\n", t); of_node_put(t); @@ -90,7 +100,7 @@ static int __init parse_core(struct device_node *core, int package_id, cpu_topology[cpu].package_id = package_id; cpu_topology[cpu].core_id = core_id; - } else if (leaf) { + } else if (leaf && cpu != -ENODEV) { pr_err("%pOF: Can't get CPU for leaf core\n", core); return -EINVAL; } From 1eddffa235dc863e65daa209b4d16323980796c9 Mon Sep 17 00:00:00 2001 From: Waseem Akhtar Date: Tue, 13 Sep 2022 12:24:02 +0530 Subject: [PATCH 08/11] msm: camera: Increase the total number of camera ID's supported Increase the total number of camera ID's supported. Change-Id: Ib1eb78eb1d6686b28c90b06b87fa57bcc1f45c07 Signed-off-by: Waseem Akhtar --- include/uapi/media/msm_camsensor_sdk.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h index 950ecf79a472..35014ace9e40 100644 --- a/include/uapi/media/msm_camsensor_sdk.h +++ b/include/uapi/media/msm_camsensor_sdk.h @@ -62,6 +62,8 @@ enum msm_sensor_camera_id_t { CAMERA_1, CAMERA_2, CAMERA_3, + CAMERA_4, + CAMERA_5, MAX_CAMERAS, }; From 0441dc4864c88d194a20a289479875de49f17d4d Mon Sep 17 00:00:00 2001 From: Arjun Singh Date: Fri, 9 Sep 2022 13:02:37 +0530 Subject: [PATCH 09/11] media:uvc: supports dynamic setting of urb configuration Frames are corrupted for higher resolution with default URB queue size and frame size. This patch creates a sysfs node to support dynamic setting of number of packers per urb and maximum packet size for higher resolution frames. $ find . -name urb_config. $ echo qsize:fsize > urb_config. Change-Id: I70aaad824049acdc21a8a52242066a6437b96833 Signed-off-by: Arjun Singh --- drivers/media/usb/uvc/uvc_driver.c | 71 ++++++++++++++++++++++++++++++ drivers/media/usb/uvc/uvc_video.c | 40 ++++++++++++----- drivers/media/usb/uvc/uvcvideo.h | 15 +++++-- 3 files changed, 111 insertions(+), 15 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 38c73cdbef70..9c991835168b 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2093,6 +2093,71 @@ struct uvc_device_info { u32 meta_format; }; +/* ------------------------------------------------------------------------ + * set urb queue size and urb packet size + * + */ +static ssize_t store_urb_config(struct device *dev, + struct device_attribute *attr, const char *buff, size_t count) +{ + struct uvc_streaming *stream; + struct usb_interface *intf = to_usb_interface(dev); + struct uvc_device *udev = usb_get_intfdata(intf); + long max_urb, max_urb_packets; + int ret; + char *arr, *tmp; + + arr = kstrdup(buff, GFP_KERNEL); + + if (!arr) + return -ENOMEM; + + tmp = strsep(&arr, ":"); + + if (!tmp) + return -EINVAL; + + ret = kstrtol(tmp, 10, &max_urb); + if (ret < 0) + return ret; + + tmp = strsep(&arr, ":"); + if (!tmp) + return -EINVAL; + + ret = kstrtol(tmp, 10, &max_urb_packets); + if (ret < 0) + return ret; + + if (max_urb <= 0 || max_urb > 128 || + max_urb_packets <= 0 || max_urb_packets > 128) + return -EINVAL; + + list_for_each_entry(stream, &udev->streams, list) { + if (stream->refcnt) + continue; + stream->max_urb = max_urb; + stream->max_urb_packets = max_urb_packets; + } + + return count; +} + +static ssize_t show_urb_config(struct device *dev, + struct device_attribute *attr, char *buff) +{ + return 0; +} + +static struct device_attribute urb_config_attr = { + .attr = { + .name = "urb_config", + .mode = 00660, + }, + .show = show_urb_config, + .store = store_urb_config, +}; + static int uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -2225,6 +2290,12 @@ static int uvc_probe(struct usb_interface *intf, uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); usb_enable_autosuspend(udev); + + /* sysfs file for dynamically setting urb configs */ + ret = sysfs_create_file(&dev->intf->dev.kobj, &urb_config_attr.attr); + if (ret != 0) + pr_info("Unable to initialize urb configuration: %d\n", ret); + return 0; error: diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index ce64c58aceb3..a8940100a6ae 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1515,7 +1515,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream) { unsigned int i; - for (i = 0; i < UVC_URBS; ++i) { + for (i = 0; i < stream->max_urb; ++i) { if (stream->urb_buffer[i]) { #ifndef CONFIG_DMA_NONCOHERENT usb_free_coherent(stream->dev->udev, stream->urb_size, @@ -1555,12 +1555,22 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, * payloads across multiple URBs. */ npackets = DIV_ROUND_UP(size, psize); - if (npackets > UVC_MAX_PACKETS) - npackets = UVC_MAX_PACKETS; + if (npackets > stream->max_urb_packets) + npackets = stream->max_urb_packets; + + + /* Allocate memory for storing URB pointers */ + stream->urb = kcalloc(stream->max_urb, + sizeof(struct urb *), gfp_flags | __GFP_NOWARN); + stream->urb_buffer = kcalloc(stream->max_urb, + sizeof(char *), gfp_flags | __GFP_NOWARN); + stream->urb_dma = kcalloc(stream->max_urb, + sizeof(dma_addr_t), gfp_flags | __GFP_NOWARN); + /* Retry allocations until one succeed. */ for (; npackets > 1; npackets /= 2) { - for (i = 0; i < UVC_URBS; ++i) { + for (i = 0; i < stream->max_urb; ++i) { stream->urb_size = psize * npackets; #ifndef CONFIG_DMA_NONCOHERENT stream->urb_buffer[i] = usb_alloc_coherent( @@ -1576,10 +1586,10 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, } } - if (i == UVC_URBS) { - uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " - "of %ux%u bytes each.\n", UVC_URBS, npackets, - psize); + if (i == stream->max_urb) { + uvc_trace(UVC_TRACE_VIDEO, + "Allocated %u URB buffers of %ux%u bytes each.\n", + stream->max_urb, npackets, psize); return npackets; } } @@ -1599,7 +1609,7 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) uvc_video_stats_stop(stream); - for (i = 0; i < UVC_URBS; ++i) { + for (i = 0; i < stream->max_urb; ++i) { urb = stream->urb[i]; if (urb == NULL) continue; @@ -1611,6 +1621,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) if (free_buffers) uvc_free_urb_buffers(stream); + + stream->refcnt--; } /* @@ -1660,7 +1672,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, size = npackets * psize; - for (i = 0; i < UVC_URBS; ++i) { + for (i = 0; i < stream->max_urb; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { uvc_uninit_video(stream, 1); @@ -1726,7 +1738,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) size = 0; - for (i = 0; i < UVC_URBS; ++i) { + for (i = 0; i < stream->max_urb; ++i) { urb = usb_alloc_urb(0, gfp_flags); if (urb == NULL) { uvc_uninit_video(stream, 1); @@ -1831,7 +1843,8 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) return ret; /* Submit the URBs. */ - for (i = 0; i < UVC_URBS; ++i) { + stream->refcnt++; + for (i = 0; i < stream->max_urb; ++i) { ret = usb_submit_urb(stream->urb[i], gfp_flags); if (ret < 0) { uvc_printk(KERN_ERR, "Failed to submit URB %u " @@ -1992,6 +2005,9 @@ int uvc_video_init(struct uvc_streaming *stream) stream->cur_format = format; stream->cur_frame = frame; + stream->max_urb = UVC_URBS; + stream->max_urb_packets = UVC_MAX_PACKETS; + /* Select the video decoding function */ if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index a738486fd9d6..615aa630d5c0 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -535,9 +535,9 @@ struct uvc_streaming { u32 max_payload_size; } bulk; - struct urb *urb[UVC_URBS]; - char *urb_buffer[UVC_URBS]; - dma_addr_t urb_dma[UVC_URBS]; + struct urb **urb; + char **urb_buffer; + dma_addr_t *urb_dma; unsigned int urb_size; u32 sequence; @@ -570,6 +570,15 @@ struct uvc_streaming { spinlock_t lock; } clock; + + /* Maximum number of URBs that can be submitted */ + u32 max_urb; + + /* Maximum number of packets per URB */ + u32 max_urb_packets; + + /*set if stream in progress */ + u8 refcnt; }; struct uvc_device { From e10bd267a47a119f2c2ebf146f25d73479fcd82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?haibinzhang=20=28=E5=BC=A0=E6=B5=B7=E6=96=8C=29?= Date: Sat, 2 Jul 2022 05:43:19 +0000 Subject: [PATCH 10/11] FROMGIT: arm64: fix oops in concurrently setting insn_emulation sysctls emulation_proc_handler() changes table->data for proc_dointvec_minmax and can generate the following Oops if called concurrently with itself: | Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 | Internal error: Oops: 96000006 [#1] SMP | Call trace: | update_insn_emulation_mode+0xc0/0x148 | emulation_proc_handler+0x64/0xb8 | proc_sys_call_handler+0x9c/0xf8 | proc_sys_write+0x18/0x20 | __vfs_write+0x20/0x48 | vfs_write+0xe4/0x1d0 | ksys_write+0x70/0xf8 | __arm64_sys_write+0x20/0x28 | el0_svc_common.constprop.0+0x7c/0x1c0 | el0_svc_handler+0x2c/0xa0 | el0_svc+0x8/0x200 To fix this issue, keep the table->data as &insn->current_mode and use container_of() to retrieve the insn pointer. Another mutex is used to protect against the current_mode update but not for retrieving insn_emulation as table->data is no longer changing. Bug: 237540956 Co-developed-by: hewenliang Signed-off-by: hewenliang Signed-off-by: Haibin Zhang Reviewed-by: Catalin Marinas Link: https://lore.kernel.org/r/20220128090324.2727688-1-hewenliang4@huawei.com Link: https://lore.kernel.org/r/9A004C03-250B-46C5-BF39-782D7551B00E@tencent.com Signed-off-by: Will Deacon [Lee: Added Fixes: tag] (cherry picked from commit af483947d472eccb79e42059276c4deed76f99a6 git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core) Fixes: 587064b610c7 ("arm64: Add framework for legacy instruction emulation") Signed-off-by: Lee Jones Change-Id: If9b96bb79c79903f9d8292e719b06fdef57ef1c5 Git-commit: 5d2c9fe6e354ff05e49ab063e231cc49f70e27ba Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: PavanKumar S.R --- arch/arm64/kernel/armv8_deprecated.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 181c29af5617..7c69a203cdf8 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -62,6 +62,7 @@ struct insn_emulation { static LIST_HEAD(insn_emulation); static int nr_insn_emulated __initdata; static DEFINE_RAW_SPINLOCK(insn_emulation_lock); +static DEFINE_MUTEX(insn_emulation_mutex); static void register_emulation_hooks(struct insn_emulation_ops *ops) { @@ -210,10 +211,10 @@ static int emulation_proc_handler(struct ctl_table *table, int write, loff_t *ppos) { int ret = 0; - struct insn_emulation *insn = (struct insn_emulation *) table->data; + struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode); enum insn_emulation_mode prev_mode = insn->current_mode; - table->data = &insn->current_mode; + mutex_lock(&insn_emulation_mutex); ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (ret || !write || prev_mode == insn->current_mode) @@ -226,7 +227,7 @@ static int emulation_proc_handler(struct ctl_table *table, int write, update_insn_emulation_mode(insn, INSN_UNDEF); } ret: - table->data = insn; + mutex_unlock(&insn_emulation_mutex); return ret; } @@ -250,7 +251,7 @@ static void __init register_insn_emulation_sysctl(void) sysctl->maxlen = sizeof(int); sysctl->procname = insn->ops->name; - sysctl->data = insn; + sysctl->data = &insn->current_mode; sysctl->extra1 = &insn->min; sysctl->extra2 = &insn->max; sysctl->proc_handler = emulation_proc_handler; From 2ade71c67be12c1b61e6931755741a1c8e2721ac Mon Sep 17 00:00:00 2001 From: Shivnandan Kumar Date: Tue, 13 Sep 2022 21:21:27 +0530 Subject: [PATCH 11/11] qcom/l2cache_counters: Add support to check available CPUS Add support to check available CPUS for each cluster. Change-Id: Ifc40333cdfe4e846b1cd527afc36a84f89bd8538 Signed-off-by: Shivnandan Kumar --- drivers/perf/qcom_l2_counters.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/perf/qcom_l2_counters.c b/drivers/perf/qcom_l2_counters.c index d1c93f237b8b..a7e71bcd6b69 100644 --- a/drivers/perf/qcom_l2_counters.c +++ b/drivers/perf/qcom_l2_counters.c @@ -1037,8 +1037,8 @@ static int l2_cache_pmu_probe_cluster(struct device *parent, struct cluster_pmu *cluster; u32 fw_cluster_id; struct resource res; - int ret; - int irq; + int ret = 0; + int irq, cpu, cpu_count = 0; cluster = kzalloc(sizeof(*cluster), GFP_KERNEL); if (!cluster) { @@ -1064,6 +1064,14 @@ static int l2_cache_pmu_probe_cluster(struct device *parent, goto err_put_dev; } + for_each_possible_cpu(cpu) { + if (topology_physical_package_id(cpu) == fw_cluster_id) { + cpu_count++; + break; + } + } + if (cpu_count == 0) + goto err_put_dev; ret = of_address_to_resource(cn, 0, &res); if (ret) { pr_err(L2_COUNTERS_BUG "not able to find the resource\n");