From af743fe3d70e5545d9829a37cd3f5a340b5ba50c Mon Sep 17 00:00:00 2001 From: Chetan C R Date: Thu, 20 Jan 2022 20:25:22 +0530 Subject: [PATCH 01/15] power: reset: Disable support of dynamic download mode (ramdump) Disable support of dynamic download mode (ramdump) Change-Id: I1f90bb02515876b2dd8485a850402bc4ef89ccfa Signed-off-by: Chetan C R --- drivers/power/reset/qcom-dload-mode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/reset/qcom-dload-mode.c b/drivers/power/reset/qcom-dload-mode.c index 113db59c2aab..002ac72a579e 100644 --- a/drivers/power/reset/qcom-dload-mode.c +++ b/drivers/power/reset/qcom-dload-mode.c @@ -99,7 +99,9 @@ static int param_set_download_mode(const char *val, if (ret) return ret; - msm_enable_dump_mode(true); + msm_enable_dump_mode(enable_dump); + if (!enable_dump) + qcom_scm_disable_sdi(); return 0; } From c4b2f05b5f7ef898f61990fe5ddbeb9d1bcb59c5 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Thu, 20 May 2021 12:31:08 +0530 Subject: [PATCH 02/15] USB: dwc3: gadget: Queue data for 16 micro frames ahead in future While starting transfer for isochronous endpoints, make sure first request is queued for 16 microframes ahead in future. Also set PENDING_REQUEST flag before giving back usb request if started_list is empty to avoid queuing in same context. Else it leads to request getting queued for micro frame interval which might have expired and resulting USB HW retiring TRB without sending data to host. Change-Id: Ia5e4512fa2a3ae6637f2be7ef2f102c26d56213c Signed-off-by: Vijayavardhan Vennapusa Signed-off-by: AKASH KUMAR --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/debug_ipc.c | 6 ++++-- drivers/usb/dwc3/gadget.c | 18 ++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c555ebb0b223..d7fe83efabbd 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -738,6 +738,7 @@ struct dwc3_ep_events { * @desc: usb_endpoint_descriptor pointer * @dwc: pointer to DWC controller * @saved_state: ep state saved during hibernation + * @missed_isoc_packets: counter for missed packets sent * @flags: endpoint flags (wedged, stalled, ...) * @number: endpoint number (1 - 15) * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK @@ -771,6 +772,7 @@ struct dwc3_ep { struct dwc3 *dwc; u32 saved_state; + u32 missed_isoc_packets; unsigned flags; #define DWC3_EP_ENABLED BIT(0) #define DWC3_EP_STALL BIT(1) diff --git a/drivers/usb/dwc3/debug_ipc.c b/drivers/usb/dwc3/debug_ipc.c index 4126936aed87..f475b0622edb 100644 --- a/drivers/usb/dwc3/debug_ipc.c +++ b/drivers/usb/dwc3/debug_ipc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. */ #include "debug.h" @@ -150,10 +151,11 @@ void dwc3_dbg_dma_unmap(struct dwc3 *dwc, u8 ep_num, struct dwc3_request *req) req->trb->ctrl & DWC3_TRB_CTRL_HWO); } else { ipc_log_string(dwc->dwc_dma_ipc_log_ctxt, - "%02X-%-3.3s %-25.25s 0x%pK 0x%lx %u 0x%lx %d", + "%02X-%-3.3s %-25.25s 0x%pK 0x%lx %u 0x%lx %d %u", ep_num >> 1, ep_num & 1 ? "IN":"OUT", "UNMAP", &req->request, req->request.dma, req->request.length, - req->trb_dma, req->trb->ctrl & DWC3_TRB_CTRL_HWO); + req->trb_dma, req->trb->ctrl & DWC3_TRB_CTRL_HWO, + req->request.actual); } } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0e17387167d5..dd12d4289479 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -308,6 +308,12 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, dwc3_gadget_del_and_unmap_request(dep, req, status); req->status = DWC3_REQUEST_STATUS_COMPLETED; + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && + (list_empty(&dep->started_list))) { + dep->flags |= DWC3_EP_PENDING_REQUEST; + dbg_event(dep->number, "STARTEDLISTEMPTY", 0); + } + spin_unlock(&dwc->lock); usb_gadget_giveback_request(&dep->endpoint, &req->request); spin_lock(&dwc->lock); @@ -983,6 +989,8 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep) spin_lock_irqsave(&dwc->lock, flags); ret = __dwc3_gadget_ep_disable(dep); dbg_event(dep->number, "DISABLE", ret); + dbg_event(dep->number, "MISSEDISOCPKTS", dep->missed_isoc_packets); + dep->missed_isoc_packets = 0; spin_unlock_irqrestore(&dwc->lock, flags); return ret; @@ -1661,6 +1669,7 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) } for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) { + dep->frame_number = __dwc3_gadget_get_frame(dep->dwc) + 16; dep->frame_number = DWC3_ALIGN_FRAME(dep, i + 1); ret = __dwc3_gadget_kick_transfer(dep); @@ -1727,8 +1736,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) { + dep->flags &= ~DWC3_EP_PENDING_REQUEST; return __dwc3_gadget_start_isoc(dep); } + return 0; } } @@ -3391,15 +3402,18 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, if (event->status & DEPEVT_STATUS_BUSERR) status = -ECONNRESET; + dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); + if (event->status & DEPEVT_STATUS_MISSED_ISOC) { status = -EXDEV; + dep->missed_isoc_packets++; + dbg_event(dep->number, "MISSEDISOC", 0); + if (list_empty(&dep->started_list)) stop = true; } - dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); - if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) goto out; From bb76f075ca4ba2721019401b0ed809b82876126c Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Mon, 9 Sep 2024 18:37:24 +0800 Subject: [PATCH 03/15] coresight-tmc: Replace deprecated function Use 'scnprintf' to replace deprecated function 'sprintf'. Change-Id: Ic258e7dfe719f1f871f9c9eb5988609a5f3b6284 Signed-off-by: Yuanfang Zhang --- drivers/hwtracing/coresight/coresight-tmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 05a7cbfd63ec..3e606171d1dd 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -304,7 +304,7 @@ static ssize_t trigger_cntr_show(struct device *dev, struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); unsigned long val = drvdata->trigger_cntr; - return sprintf(buf, "%#lx\n", val); + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); } static ssize_t trigger_cntr_store(struct device *dev, @@ -329,7 +329,7 @@ static ssize_t buffer_size_show(struct device *dev, { struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); - return sprintf(buf, "%#x\n", drvdata->size); + return scnprintf(buf, PAGE_SIZE, "%#x\n", drvdata->size); } static ssize_t buffer_size_store(struct device *dev, From 32de0804b1379d126033893ef70955fbbb77eb91 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Tue, 12 Mar 2024 20:27:22 -0700 Subject: [PATCH 04/15] msm: ep_pcie: Disable hot reset and ignore linkdown Intel host tends to retrain the link if device doesn't send PM_Enter_L23 in time, leading to linkdown and hot reset in device side. The hot reset here even results to PERST# timeout and device crash to PBL, which is not expected. Since we are in the entry of shutdown the link when linkdown happen, it makes sense to ignore the linkdown. To avoid device crash because of PERST# timeout, disable hot reset in pm_turnoff irq and reenable it when we do linktrain again. Change-Id: I87961faaae2a14c9a5e7d24543b416914076dd2e Signed-off-by: Qiang Yu Signed-off-by: Sai Chaitanya Kaveti --- drivers/platform/msm/ep_pcie/ep_pcie_com.h | 2 + drivers/platform/msm/ep_pcie/ep_pcie_core.c | 51 ++++++++++++++++++++- include/linux/msm_ep_pcie.h | 1 + 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h index 34b7a56b2217..5e3d8a02279b 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h +++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.*/ #ifndef __EP_PCIE_COM_H #define __EP_PCIE_COM_H @@ -429,6 +430,7 @@ struct ep_pcie_dev_t { struct clk *pipe_clk_mux; struct clk *pipe_clk_ext_src; struct clk *ref_clk_src; + u32 tcsr_hot_reset_en_offset; }; extern struct ep_pcie_dev_t ep_pcie_dev; diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index d0b8e3f386a3..591f7cb47d38 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.*/ /* * MSM PCIe endpoint core driver. @@ -37,6 +38,7 @@ #define PCIE_MHI_STATUS(n) ((n) + 0x148) #define TCSR_PERST_SEPARATION_ENABLE 0x270 #define TCSR_PCIE_RST_SEPARATION 0x3F8 +#define TCSR_HOT_RESET_EN 0x3e8 #define PCIE_ISSUE_WAKE 1 #define PCIE_MHI_FWD_STATUS_MIN 5000 #define PCIE_MHI_FWD_STATUS_MAX 5100 @@ -1815,6 +1817,13 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) */ writel_relaxed(0, dev->tcsr_perst_en + TCSR_PERST_SEPARATION_ENABLE); + + /* + * Re-enable hot reset before link up since we disable it + * in pm_turnoff irq. + */ + ep_pcie_write_reg_field(dev->tcsr_perst_en, + ep_pcie_dev.tcsr_hot_reset_en_offset, BIT(0), BIT(0)); } /* check link status during initial bootup */ @@ -2280,6 +2289,10 @@ static irqreturn_t ep_pcie_handle_linkdown_irq(int irq, void *data) EP_PCIE_DBG(dev, "PCIe V%d:Linkdown IRQ happened when the link is suspending\n", dev->rev); + } else if (dev->link_status == EP_PCIE_LINK_IN_L23READY) { + EP_PCIE_DBG(dev, + "PCIe V%d:Linkdown IRQ happened when link goes to l23ready\n", + dev->rev); } else { dev->link_status = EP_PCIE_LINK_DISABLED; EP_PCIE_ERR(dev, "PCIe V%d:PCIe link is down for %ld times\n", @@ -2320,13 +2333,29 @@ static irqreturn_t ep_pcie_handle_pm_turnoff_irq(int irq, void *data) spin_lock_irqsave(&dev->isr_lock, irqsave_flags); + if (!dev->tcsr_not_supported) + /* + * Some hosts will try to recovery link if it doesn't receive PM_L23_Enter + * within 10ms after sending PME turn off, in which case if Hot reset is + * enabled, PERST# timeout circuit will start to work. If it measures that + * the link doesn't enter L0 within a predetermined time, device will crash + * with PERST_TIMEOUT_RESET_STATUS set to 1. + * + * Note that PERST# timeout circuit monitors the Detect to L0 transition and + * it gets activated in two scenario: + * 1) When PERST# gets de-asserted and perst-separation is enabled. + * 2) When hot-reset is enabled and link training is initiated. + */ + ep_pcie_write_reg_field(dev->tcsr_perst_en, + ep_pcie_dev.tcsr_hot_reset_en_offset, BIT(0), 0); + dev->pm_to_counter++; EP_PCIE_DBG2(dev, "PCIe V%d: No. %ld PM_TURNOFF is received\n", dev->rev, dev->pm_to_counter); EP_PCIE_DBG2(dev, "PCIe V%d: Put the link into L23\n", dev->rev); ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(2)); - + dev->link_status = EP_PCIE_LINK_IN_L23READY; spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); return IRQ_HANDLED; @@ -2943,6 +2972,11 @@ enum ep_pcie_link_status ep_pcie_core_get_linkstatus(void) return EP_PCIE_LINK_DISABLED; } + if (dev->link_status == EP_PCIE_LINK_IN_L23READY) { + EP_PCIE_DBG(dev, "PCIe V%d: PCIe endpoint has sent PM_ENTER_L23\n", dev->rev); + return EP_PCIE_LINK_IN_L23READY; + } + bme = readl_relaxed(dev->dm_core + PCIE20_COMMAND_STATUS) & BIT(2); if (bme) { @@ -3499,6 +3533,21 @@ static int ep_pcie_probe(struct platform_device *pdev) EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: tcsr pcie perst is %s supported\n", ep_pcie_dev.rev, ep_pcie_dev.tcsr_not_supported ? "not" : ""); + if (!ep_pcie_dev.tcsr_not_supported) { + + ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,tcsr-hot-reset-en-offset", + &ep_pcie_dev.tcsr_hot_reset_en_offset); + if (ret) { + EP_PCIE_DBG(&ep_pcie_dev, + "PCIe V%d: TCSR Hot Reset Enable Offset is not supplied from DT", + ep_pcie_dev.rev); + ep_pcie_dev.tcsr_hot_reset_en_offset = TCSR_HOT_RESET_EN; + } + + EP_PCIE_DBG(&ep_pcie_dev, + "PCIe V%d: TCSR Hot Reset Enable Offset: 0x%x\n", + ep_pcie_dev.rev, ep_pcie_dev.tcsr_hot_reset_en_offset); + } ep_pcie_dev.aoss_rst_clear = of_property_read_bool ((&pdev->dev)->of_node, diff --git a/include/linux/msm_ep_pcie.h b/include/linux/msm_ep_pcie.h index d98ed7b13984..82da45762bfc 100644 --- a/include/linux/msm_ep_pcie.h +++ b/include/linux/msm_ep_pcie.h @@ -20,6 +20,7 @@ enum ep_pcie_link_status { EP_PCIE_LINK_DISABLED, EP_PCIE_LINK_UP, EP_PCIE_LINK_ENABLED, + EP_PCIE_LINK_IN_L23READY, }; enum ep_pcie_event { From f1d1549d8e9a17dddb7a128955d28bc96eaeca38 Mon Sep 17 00:00:00 2001 From: Vishnu Teja Date: Tue, 21 Nov 2023 17:24:23 +0530 Subject: [PATCH 05/15] scripts: mod: replace with a safe function Add safe function vsnprintf instead of sprintf by passing size as argument. Change-Id: Ibd21a0c7d9039543dee32c1297035ed9984ed748 Signed-off-by: Vishnu Teja --- scripts/mod/modpost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 5ca626d0de92..0ac6bf1d14c4 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2577,7 +2577,7 @@ static void write_namespace_deps_files(void) if (ns_deps_buf.pos == 0) continue; - sprintf(fname, "%s.ns_deps", mod->name); + snprintf(fname, PATH_MAX, "%s.ns_deps", mod->name); write_if_changed(&ns_deps_buf, fname); } } @@ -2689,7 +2689,7 @@ int main(int argc, char **argv) add_moddevtable(&buf, mod); add_srcversion(&buf, mod); - sprintf(fname, "%s.mod.c", mod->name); + snprintf(fname, PATH_MAX, "%s.mod.c", mod->name); write_if_changed(&buf, fname); } From b2af2b5f9f4ed3e43ea4a227783e9f62ac645cd2 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 29 Mar 2024 14:37:42 +0530 Subject: [PATCH 06/15] firmware: qcom_scm: handle echo b > /proc/sysrq-trigger Introduce restart handler to handle "echo b > /proc/sysrq-trigger". One special thing with 'b' kind of reboot is, it does not call reboot notifiers and call restart handler right a way and that does not seems to work for blair SoC and it goes to dump mode. Keep this restart handler priority to 201 greater than 200 which is the priority for msm-poweroff to make reboot work cleaner. Change-Id: I42f8c0fde29af402096d760c37ec2d8b3a85439a Signed-off-by: Mukesh Ojha Signed-off-by: Sayan Dey --- drivers/power/reset/qcom-dload-mode.c | 43 +++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/power/reset/qcom-dload-mode.c b/drivers/power/reset/qcom-dload-mode.c index 5298b80921c9..71e77259625a 100644 --- a/drivers/power/reset/qcom-dload-mode.c +++ b/drivers/power/reset/qcom-dload-mode.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -24,10 +25,12 @@ enum qcom_download_dest { struct qcom_dload { struct notifier_block panic_nb; + struct notifier_block reboot_nb; struct notifier_block restart_nb; struct kobject kobj; bool in_panic; + bool in_reboot; void __iomem *dload_dest_addr; }; @@ -280,16 +283,40 @@ static int qcom_dload_panic(struct notifier_block *this, unsigned long event, static int qcom_dload_restart(struct notifier_block *this, unsigned long event, void *ptr) { - char *cmd = ptr; - if (cmd && !strcmp(cmd, "edl")) { - set_download_mode(QCOM_DOWNLOAD_EDL); - reboot_mode = REBOOT_WARM; + struct qcom_dload *poweroff = container_of(this, struct qcom_dload, + restart_nb); + + if (!poweroff->in_panic && !poweroff->in_reboot) { + qcom_scm_disable_sdi(); + set_download_mode(QCOM_DOWNLOAD_NODUMP); } return NOTIFY_OK; } +static int qcom_dload_reboot(struct notifier_block *this, unsigned long event, + void *ptr) +{ + char *cmd = ptr; + struct qcom_dload *poweroff = container_of(this, struct qcom_dload, + reboot_nb); + + poweroff->in_reboot = true; + set_download_mode(QCOM_DOWNLOAD_NODUMP); + if (cmd) { + if (!strcmp(cmd, "edl")) + set_download_mode(QCOM_DOWNLOAD_EDL); + else if (!strcmp(cmd, "qcom_dload")) + msm_enable_dump_mode(true); + } + + if (current_download_mode != QCOM_DOWNLOAD_NODUMP) + reboot_mode = REBOOT_WARM; + + return NOTIFY_OK; +} + static void __iomem *map_prop_mem(const char *propname) { struct device_node *np = of_find_compatible_node(NULL, NULL, propname); @@ -394,13 +421,17 @@ static int qcom_dload_probe(struct platform_device *pdev) atomic_notifier_chain_register(&panic_notifier_list, &poweroff->panic_nb); + poweroff->reboot_nb.notifier_call = qcom_dload_reboot; + poweroff->reboot_nb.priority = 255; + register_reboot_notifier(&poweroff->reboot_nb); + poweroff->restart_nb.notifier_call = qcom_dload_restart; /* Here, Restart handler priority should be higher than * of restart handler present in scm driver so that * reboot_mode set by this handler seen by SCM's one * for EDL mode. */ - poweroff->restart_nb.priority = 131; + poweroff->restart_nb.priority = 201; register_restart_handler(&poweroff->restart_nb); platform_set_drvdata(pdev, poweroff); @@ -414,7 +445,9 @@ static int qcom_dload_remove(struct platform_device *pdev) atomic_notifier_chain_unregister(&panic_notifier_list, &poweroff->panic_nb); + unregister_restart_handler(&poweroff->restart_nb); + unregister_reboot_notifier(&poweroff->reboot_nb); if (poweroff->dload_dest_addr) iounmap(poweroff->dload_dest_addr); From c5539fb1c23b4a10d45fc9b878b7e2f51d1e981c Mon Sep 17 00:00:00 2001 From: Anil Veshala Veshala Date: Mon, 1 Jul 2024 02:39:57 -0700 Subject: [PATCH 07/15] i2c: i2c-master-msm-geni: add null pointer check in event call back Currently i2c geni driver doesn't have null pointer check condition in event call back function. If any invalid event is coming from GSI, i2c geni driver accessing null pointer which is causing crash. To solve this added null pointer checks in event call back functions. Change-Id: Ie14a40eee846c0ea29bec512d6320e9548c509b5 Signed-off-by: Anil Veshala Veshala --- drivers/i2c/busses/i2c-msm-geni.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index 473ff18b0f2e..e29a96949536 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -452,8 +452,16 @@ irqret: static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str, void *ptr) { - struct geni_i2c_dev *gi2c = ptr; - u32 m_stat = cb_str->status; + struct geni_i2c_dev *gi2c; + u32 m_stat; + + if (!ptr || !cb_str) { + pr_err("%s: Invalid ev_cb buffer\n", __func__); + return; + } + + gi2c = (struct geni_i2c_dev *)ptr; + m_stat = cb_str->status; switch (cb_str->cb_event) { case MSM_GPI_QUP_ERROR: From 79c14fa64191b69840df2055dfba906ab9d33e51 Mon Sep 17 00:00:00 2001 From: gaowang Date: Tue, 24 Sep 2024 16:19:44 +0800 Subject: [PATCH 08/15] msm: virtio_npu: Fix use-after-free issue in virt_npu_map_buf address the security CR of virtio_npu driver Change-Id: Ib77014bc12490e7b09367354024baa2754d3e433 Signed-off-by: gaowang --- drivers/media/platform/msm/npu/virtio_npu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/msm/npu/virtio_npu.c b/drivers/media/platform/msm/npu/virtio_npu.c index bed8eac6fe68..e21427f53734 100644 --- a/drivers/media/platform/msm/npu/virtio_npu.c +++ b/drivers/media/platform/msm/npu/virtio_npu.c @@ -814,6 +814,7 @@ static int32_t virt_npu_map_buf(struct npu_client *client, struct npu_ion_buf *ion_buf = NULL; int rc = 0; + mutex_lock(&npu_dev->lock); ion_buf = npu_alloc_npu_ion_buffer(client, buf_hdl, size); if (!ion_buf) { NPU_ERR("fail to alloc npu_ion_buffer\n"); @@ -853,6 +854,7 @@ static int32_t virt_npu_map_buf(struct npu_client *client, rc = virt_npu_mmap(client, 0, ion_buf->table->sgl, ion_buf->table->nents, size, &ion_buf->iova); + mutex_unlock(&npu_dev->lock); map_end: if (rc) From a721c06f7d24b8ce8136ebf1c031d4f4e0f6dbda Mon Sep 17 00:00:00 2001 From: Gao Wang Date: Thu, 19 Sep 2024 16:19:59 +0800 Subject: [PATCH 09/15] msm: virtio_npu: Fix use-after-free issue in unmap_buf address the security CR of virtio_npu driver Change-Id: Ibf656fa76dedb19086b75d8bf519b2f415ac8d22 Signed-off-by: Gao Wang --- drivers/media/platform/msm/npu/virtio_npu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/msm/npu/virtio_npu.c b/drivers/media/platform/msm/npu/virtio_npu.c index bed8eac6fe68..f1cceb8c8605 100644 --- a/drivers/media/platform/msm/npu/virtio_npu.c +++ b/drivers/media/platform/msm/npu/virtio_npu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -668,8 +669,10 @@ fail: static int32_t virt_npu_unmap_buf(struct npu_client *client, int buf_hdl, uint64_t iova) { + struct npu_device *npu_dev = client->npu_dev; struct npu_ion_buf *ion_buf; + mutex_lock(&npu_dev->lock); /* clear entry and retrieve the corresponding buffer */ ion_buf = npu_get_npu_ion_buffer(client, buf_hdl); if (!ion_buf) { @@ -694,6 +697,7 @@ static int32_t virt_npu_unmap_buf(struct npu_client *client, NPU_DBG("unmapped mem addr:0x%llx size:0x%x\n", ion_buf->iova, ion_buf->size); npu_free_npu_ion_buffer(client, buf_hdl); + mutex_unlock(&npu_dev->lock); return 0; } From 10dc2028353609dfdfa12b60f8473c6d5e10dfde Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 29 Nov 2024 17:01:56 +0530 Subject: [PATCH 10/15] firmware: qcom_scm: do not clear dump mode from shutdown Do not overwrite download mode to NO dump mode from SCM driver, it is already being done at proper place in qcom-dload-mode driver and writing it here can clean up EDL mode written from qcom-dload-mode. Fix this issue by remove writing no dump mode from SCM driver. Change-Id: Ibfe8b8484dd69ae8386b46c9a53ef42a4a475688 Signed-off-by: Mukesh Ojha --- drivers/firmware/qcom_scm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 99593aaebacd..96b71bc4cd99 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1248,8 +1248,6 @@ static void qcom_scm_shutdown(struct platform_device *pdev) { qcom_scm_disable_sdi(); qcom_scm_halt_spmi_pmic_arbiter(); - /* Clean shutdown, disable download mode to allow normal restart */ - qcom_scm_set_download_mode(QCOM_DOWNLOAD_NODUMP, 0); } static const struct of_device_id qcom_scm_dt_match[] = { From 944949f22ee4857434c47ac6a0c08a0a9a1bd23b Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Fri, 6 Dec 2024 14:47:27 +0530 Subject: [PATCH 11/15] arm64: defconfig: Enable uvc for QCM6490 IOT target Enable USB UVC peripheral function driver that enables video streaming over USB. Change-Id: I951d93f735a57b382aa5e43f2997880ded89b2f4 Signed-off-by: Akash Kumar --- arch/arm64/configs/vendor/lahaina_QGKI.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 5358cae0d6d2..e3e057f67630 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -216,7 +216,14 @@ CONFIG_HID_WIIMOTE=y CONFIG_USB_DUMMY_HCD=y CONFIG_USB_CONFIGFS_ACM=y # CONFIG_USB_CONFIGFS_RNDIS is not set +CONFIG_USB_CONFIGFS_F_UVC=y CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_USB_F_UVC=y +CONFIG_USB_G_WEBCAM=m +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_F_UVC=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EROFS_FS=y # CONFIG_SERIAL_MSM_GENI_EARLY_CONSOLE is not set From 09c3ad5d253ab8c79824d796cd8eaea1f94ac733 Mon Sep 17 00:00:00 2001 From: AKASH KUMAR Date: Sun, 11 Dec 2022 15:12:02 +0530 Subject: [PATCH 12/15] USB: dwc3: gadget: Add stop transfer request for isoc transfers Currently,stop transfer is done based on missed isoc packets which can cause issue when software list is empty with no missed isoc. Issue stop active transfers if started list is empty. Also,Frame_number is set from XferNotReady and may be already out of date. DSTS only provides the lower 14 bit of the current frame number. So add the upper two bits of frame_number and handle a possible rollover. This will provide the correct frame_number unless more than rollover has happened since XferNotReady. Increase TX fifo size for isochronous endpoint in case maxburst is greater than 6 for better performance. Added Endtransfer logic to be called when BUS expiry happens due to frame mismatch. Change-Id: I672529f4a4fa2740b46febbe265cd386e5932017 Signed-off-by: AKASH KUMAR --- drivers/usb/dwc3/gadget.c | 54 +++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index dd12d4289479..5c23ef112656 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -30,6 +30,8 @@ #define DWC3_ALIGN_FRAME(d, n) (((d)->frame_number + ((d)->interval * (n))) \ & ~((d)->interval - 1)) +#define DWC3_FRAME_WRAP_AROUND_MASK (BIT(14) | BIT(15)) + static int __dwc3_gadget_start(struct dwc3 *dwc); static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc); static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup); @@ -228,6 +230,11 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep) && dwc3_is_usb31(dwc)) mult = 6; + if ((dep->endpoint.maxburst > 6) && + usb_endpoint_xfer_isoc(dep->endpoint.desc)) + mult = 6; + + tmp = ((max_packet + mdwidth) * mult) + mdwidth; fifo_size = DIV_ROUND_UP(tmp, mdwidth); dep->fifo_depth = fifo_size; @@ -1651,7 +1658,7 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) { struct dwc3 *dwc = dep->dwc; int ret; - int i; + u16 wraparound_bits, uf; if (list_empty(&dep->pending_list)) { dep->flags |= DWC3_EP_PENDING_REQUEST; @@ -1668,13 +1675,36 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) return dwc3_gadget_start_isoc_quirk(dep); } - for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) { - dep->frame_number = __dwc3_gadget_get_frame(dep->dwc) + 16; - dep->frame_number = DWC3_ALIGN_FRAME(dep, i + 1); + wraparound_bits = dep->frame_number & DWC3_FRAME_WRAP_AROUND_MASK; + uf = dep->frame_number & ~DWC3_FRAME_WRAP_AROUND_MASK; - ret = __dwc3_gadget_kick_transfer(dep); - if (ret != -EAGAIN) - break; + /* if frame wrapped-around update wrap-around bits to reflect that */ + if (__dwc3_gadget_get_frame(dep->dwc) < uf) + wraparound_bits += BIT(14); + + uf = __dwc3_gadget_get_frame(dep->dwc) + max_t(u32, 16, 2 * dep->interval); + + /* align frame number to ep interval */ + dep->frame_number = (wraparound_bits + uf) & ~(dep->interval - 1); + + ret = __dwc3_gadget_kick_transfer(dep); + + if (ret == -EAGAIN) { + struct dwc3_gadget_ep_cmd_params params; + u32 cmd; + + dwc3_gadget_ep_get_transfer_index(dep); + dep->flags |= DWC3_EP_PENDING_REQUEST; + cmd = DWC3_DEPCMD_ENDTRANSFER | + DWC3_DEPCMD_CMDIOC | + DWC3_DEPCMD_PARAM(dep->resource_index); + + dep->resource_index = 0; + memset(¶ms, 0, sizeof(params)); + + ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); + if (!ret) + dep->flags |= DWC3_EP_END_TRANSFER_PENDING; } return ret; @@ -3406,12 +3436,14 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, if (event->status & DEPEVT_STATUS_MISSED_ISOC) { status = -EXDEV; - dep->missed_isoc_packets++; - dbg_event(dep->number, "MISSEDISOC", 0); + dbg_event(dep->number, "MISSEDISOC", dep->missed_isoc_packets); + } - if (list_empty(&dep->started_list)) - stop = true; + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && + (list_empty(&dep->started_list))) { + stop = true; + dbg_event(dep->number, "STOPXFER", dep->frame_number); } if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) From a8ee531704b607d5f023315d34f78d4fb7ef421f Mon Sep 17 00:00:00 2001 From: Gao Wang Date: Mon, 23 Dec 2024 17:14:59 +0800 Subject: [PATCH 13/15] msm: npu: Fix use after free issue There is possibility that network will be used after free. This change is to fix this issue. Change-Id: I12205b750450bee36f85dff3f620f8f0689a4e46 Signed-off-by: Gao Wang --- drivers/media/platform/msm/npu/npu_dev.c | 2 +- drivers/media/platform/msm/npu/npu_mgr.c | 30 ++++++++++++++++++++++++ drivers/media/platform/msm/npu/npu_mgr.h | 3 +++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index e5b2d93d9db0..704ccddd09e2 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -1552,7 +1553,6 @@ static int npu_set_fw_state(struct npu_client *client, uint32_t enable) if (host_ctx->network_num > 0) { pr_err("Need to unload network first\n"); - mutex_unlock(&npu_dev->dev_lock); return -EINVAL; } diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index 6b017934f985..e21ba85a839d 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -1593,6 +1594,13 @@ int32_t npu_host_unload_network(struct npu_client *client, return -EINVAL; } + if (network->is_unloading) { + pr_err("network is unloading\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return -EINVAL; + } + if (!network->is_active) { pr_err("network is not active\n"); network_put(network); @@ -1600,10 +1608,18 @@ int32_t npu_host_unload_network(struct npu_client *client, return -EINVAL; } + if (network->is_executing) { + pr_err("network is in execution\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return -EINVAL; + } + if (network->fw_error) { pr_err("fw in error state, skip unload network in fw\n"); goto free_network; } + network->is_unloading = true; pr_debug("Unload network %lld\n", network->id); /* prepare IPC packet for UNLOAD */ @@ -1832,12 +1848,24 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); + if (network->is_unloading) { + pr_err("network is unloading\n"); + ret = -EINVAL; + goto exec_v2_done; + } + if (!network->is_active) { pr_err("network is not active\n"); ret = -EINVAL; goto exec_v2_done; } + if (network->is_executing) { + pr_err("network is already in execution\n"); + ret = -EINVAL; + goto exec_v2_done; + } + if (network->fw_error) { pr_err("fw is in error state\n"); ret = -EIO; @@ -1855,6 +1883,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, goto exec_v2_done; } + network->is_executing = true; for (i = 0; i < num_patch_params; i++) { exec_packet->patch_params[i].id = patch_buf_info[i].buf_id; pr_debug("%d: patch_id: %x\n", i, @@ -1936,6 +1965,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, free_exec_packet: kfree(exec_packet); + network->is_executing = false; exec_v2_done: network_put(network); mutex_unlock(&host_ctx->lock); diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index f0ab23267787..b6bf46557dbd 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _NPU_MGR_H @@ -52,6 +53,8 @@ struct npu_network { atomic_t ref_cnt; bool is_valid; bool is_active; + bool is_unloading; + bool is_executing; bool fw_error; bool cmd_pending; bool cmd_async; From f4425004febe07e9b1d9d1f6bae5567b66dc2ea3 Mon Sep 17 00:00:00 2001 From: Madhu Ananthula Date: Fri, 17 Jan 2025 12:15:04 +0530 Subject: [PATCH 14/15] msm: eva: Copy back the validated size to avoid security issue As we are reading the packet from a shared queue, there is a possibility to corrupt the packet->size data of shared queue by malicious FW after validating it in the kernel driver. Change-Id: I9bff8f2daa64054eada37de54fe3fa837d57b22a Signed-off-by: Aniruddh Sharma Signed-off-by: Madhu Ananthula (cherry picked from commit bb8a45801d247ebe5201e1e97d4e890142d6cbf7) --- drivers/media/platform/msm/cvp/cvp_hfi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index fc4236397575..6f598089406a 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -717,7 +717,7 @@ static int __read_queue(struct cvp_iface_q_info *qinfo, u8 *packet, u32 *read_ptr; u32 receive_request = 0; u32 read_idx, write_idx; - int rc = 0; + int rc = 0; if (!qinfo || !packet || !pb_tx_req_is_set) { dprintk(CVP_ERR, "Invalid Params\n"); @@ -807,6 +807,12 @@ static int __read_queue(struct cvp_iface_q_info *qinfo, u8 *packet, (u8 *)qinfo->q_array.align_virtual_addr, new_read_idx << 2); } + /* + * Copy back the validated size to avoid security issue. As we are reading + * the packet from a shared queue, there is a possibility to get the + * packet->size data corrupted of shared queue by mallicious FW. + */ + *((u32 *) packet) = packet_size_in_words << 2; } else { dprintk(CVP_WARN, "BAD packet received, read_idx: %#x, pkt_size: %d\n", From d7c484822f8201cfc064ca6d0c7702cdba38eed2 Mon Sep 17 00:00:00 2001 From: Pulkit Singh Tak Date: Mon, 6 Jan 2025 16:28:14 +0530 Subject: [PATCH 15/15] msm: eva: Validating the SFR buffer size before accessing To avoid any OOB write or other security issues, it's good to validate the buffer size before accessing it. Change-Id: Ibfdef21293c9385119cfb6338ef36e20c0fc1f2f Signed-off-by: Pulkit Singh Tak (cherry picked from commit 8ee6cd6bef52b65e6afba63310e07891e39eb38e) --- drivers/media/platform/msm/cvp/cvp_hfi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index fc4236397575..a38603f89ae3 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -2757,17 +2757,19 @@ skip_power_off: static void __process_sys_error(struct iris_hfi_device *device) { struct cvp_hfi_sfr_struct *vsfr = NULL; + u32 sfr_buf_size = 0; vsfr = (struct cvp_hfi_sfr_struct *)device->sfr.align_virtual_addr; - if (vsfr) { - void *p = memchr(vsfr->rg_data, '\0', vsfr->bufSize); + sfr_buf_size = vsfr->bufSize; + if (vsfr && sfr_buf_size < ALIGNED_SFR_SIZE) { + void *p = memchr(vsfr->rg_data, '\0', sfr_buf_size); /* * SFR isn't guaranteed to be NULL terminated * since SYS_ERROR indicates that Iris is in the * process of crashing. */ if (p == NULL) - vsfr->rg_data[vsfr->bufSize - 1] = '\0'; + vsfr->rg_data[sfr_buf_size - 1] = '\0'; dprintk(CVP_ERR, "SFR Message from FW: %s\n", vsfr->rg_data);