From c4b2f05b5f7ef898f61990fe5ddbeb9d1bcb59c5 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Thu, 20 May 2021 12:31:08 +0530 Subject: [PATCH 1/5] 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 10dc2028353609dfdfa12b60f8473c6d5e10dfde Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 29 Nov 2024 17:01:56 +0530 Subject: [PATCH 2/5] 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 3/5] 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 4/5] 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 5/5] 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;