From nobody Thu Apr 9 08:54:43 2026 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7781644E045 for ; Tue, 10 Mar 2026 10:04:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773137046; cv=none; b=Uj8N7t6dISO77VRWSfnNWbcmvAXzN4SMklOqKxB4VDrIKsvYiQGSXDil4oY8QpBgvlOV5sMPlX1DCYWdf1tsBZBeMFXacpLU7GvWCExklo9ZV9jkv/670+miDe5F0ZjceqoqmmVo07n+YFI5+gaCF/SMXZLzTBnrJQ8ijm5sBDE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773137046; c=relaxed/simple; bh=t9eMrUtXNmy/fY4ijryz8rWuZqpKMZesRaQNHKoo6RM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=T7uZ9c1If1NZYIDj8RsQeaynGuA4cqP+N8KjJWzB8ApdLNE3aqC+irfx6rN+YCUXLyybWs1fG7mG8hJP7FFuzpgZ24wFKrG2GD6hw6WUh7ioXCewAurphofOj/WxnuAyRtd9nQHWJ3Ij0uOQUUKotyRMIjhg3B9PWwpl7T7xwDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=eZ5MAP7j; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=Bgho/XHa; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="eZ5MAP7j"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Bgho/XHa" Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 62A8r4VW2460625 for ; Tue, 10 Mar 2026 10:04:01 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= wUBswidzoqbPNal7luIOGx1YD2irRnbNMuEgZlRAQyM=; b=eZ5MAP7jFuMP6DxZ xecT2sROpo/e0f4tLdNHSIC0T/EcJ9A4dOPxeRspoFxtuvkvJktuBt9ybW3G9WKi fnEuY6AZ9GFi3lvZ7HCwIFfhOw1NS3Aveu5OonofV8RyMPYyGGZLJr2VtkGL1e3b oKbEMrOTEY1Lyhj9SWn0z3JWA3hQdsU2X8R4vvZu4DVkJgcunkgcXjIHfON5dfet Ga1edBb1vr+dWA9ShdBZIvmNsK0M4SsxLY5W1ryMDHZ2RdEnxCClakvXsdjFnWcT 05ie/UZZHOKdeMjzyFTOzRVV546kB0WUy/y4sccKiWCPaiReAxZew7MJLlFOBz0r j6KJFA== Received: from mail-ot1-f72.google.com (mail-ot1-f72.google.com [209.85.210.72]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4csyv1bpyk-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 10 Mar 2026 10:04:01 +0000 (GMT) Received: by mail-ot1-f72.google.com with SMTP id 46e09a7af769-7d75b6b8500so7022970a34.2 for ; Tue, 10 Mar 2026 03:04:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1773137041; x=1773741841; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=wUBswidzoqbPNal7luIOGx1YD2irRnbNMuEgZlRAQyM=; b=Bgho/XHau8lY+PcjL4gJ7HVvKaJFyZqG9T4Qm43JEgHYnPYlHdim3q3HsVnZ8kW/0Z yTVU3SLQRfwrLDKMFgVt5Muz7irRz0lVaMLXgTo/jVqyKlFsktBUwS8F7ighWtUEHelW F8PQKjWb4/vIEART4e17WZVSpEjKwM7N+gjcUc29xTiOtjFyH6vgumxkr3c5uXNkydfp kdStiJtOxuKaxjM9WpFYHeb39HKJ+pC3CGmgomMrtD71Was05dtl6IEmKngYpJnW/D6b QLdT0CWTG1t6OQ/TVx/EDmwRkpp4nTCZDcZcag8wt3PsbscCVmDzyKC+9Y3tTYKXfvYw EmVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773137041; x=1773741841; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=wUBswidzoqbPNal7luIOGx1YD2irRnbNMuEgZlRAQyM=; b=o5OiTMJf8SevPy9uSX++6og1HjlFbgssd2rjt41x4W6Tw7vuD/poBTAQyZb/ebS7xh rtRGb4G7lygLAoVi7m6U/SNBM+4O3LKCBEMEYcW+Do9aYclP1+FdnfRcEJmZlxr58vzh ZlF0/mbPZO36GsEGs64DRoR/SB7pGGH2EPiEiqUo/p0+xjtknBcXC1u5yGbtsQRLFlij p5IPII/kMtOsqVF2+n6+cu3vKYIjWIPaGyqN9fcV/zpE1hhxn1r5qcw98w2/gYdQ9YlY nlXX8IkBw585WUBGS9PZzlg8ocRsMF7gOQ6ag8bge5zhzZcL5NzzD10i6lmqsF3ggV7H 53tw== X-Forwarded-Encrypted: i=1; AJvYcCVliVjO4yBrATUMoKLAStjHEQ95SQ8SISnP7YMQgsLE9riZz4k4fA6hSwj5gGNoiEl+aCCr2xPsI6UkNw8=@vger.kernel.org X-Gm-Message-State: AOJu0Yx8wmPwvRNI9OnNEjFAZE4kDXs8NoH0qE7IVFAGK0wa8aRUdq2g YCKkG0iSB9yp9yFKLjUrZiK9sK2b/2WRcAiw67eiFCAaJqQ5MKB7eBSw40Uv+kSu0jOebDaupaf Z7BhvsQxiI/HL2/ZqRdFo51kGTdhzwoH35DayM2UP7k/qRmXTRTDJyEUpfU68LyiyRII= X-Gm-Gg: ATEYQzyD+QmuXmA0uo9LxkJU1xBMI5KHwOFqro6KtjYLheOu7Rgn3uqgsML7hNDgQ91 fiznRk2TZMEVxdfXtcwfZuIVcd0Bg4uoXyxMj6C5jcux8Um38Qmx8MnplXVEGrRByNc1HUkvSid I0Y4QSctAI+bGhigKETxvkvAstIci5ijBNkGhW8Qi8W0fYtK4jZaz2A4nDsMn7u3ubnSp/IXYuv MJ2SLNTSzDR9LHF4ScgBBAMJTsNzESLsf98xhJeN9XJrqmORjM2Hh23mKYz6fkywDWLyz0G1Rny EqrTLA+D2HPnL6un/TwsXAmH/5nx9GH9i2I4fTLr2+3N7bxrNKtY/shuCssRA5UdfdwernJcEcK n83kemBMY9ynybFhurFndKxV26kRZCJ7W/4tz5iVh70IoVdEkg3oQQj/VDrvmLgx/Bd6GHLB0 X-Received: by 2002:a05:6830:6b09:b0:7d7:4f9d:54a7 with SMTP id 46e09a7af769-7d74f9d639cmr3967062a34.28.1773137040637; Tue, 10 Mar 2026 03:04:00 -0700 (PDT) X-Received: by 2002:a05:6830:6b09:b0:7d7:4f9d:54a7 with SMTP id 46e09a7af769-7d74f9d639cmr3967043a34.28.1773137040197; Tue, 10 Mar 2026 03:04:00 -0700 (PDT) Received: from hu-jingyw-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7d746bdecbfsm4337611a34.10.2026.03.10.03.03.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Mar 2026 03:03:59 -0700 (PDT) From: Jingyi Wang Date: Tue, 10 Mar 2026 03:03:22 -0700 Subject: [PATCH v4 6/7] remoteproc: qcom: pas: Add late attach support for subsystems Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260310-knp-soccp-v4-6-0a91575e0e7e@oss.qualcomm.com> References: <20260310-knp-soccp-v4-0-0a91575e0e7e@oss.qualcomm.com> In-Reply-To: <20260310-knp-soccp-v4-0-0a91575e0e7e@oss.qualcomm.com> To: Bjorn Andersson , Mathieu Poirier , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Manivannan Sadhasivam , Luca Weiss , Bartosz Golaszewski , Konrad Dybcio Cc: aiqun.yu@oss.qualcomm.com, tingwei.zhang@oss.qualcomm.com, trilok.soni@oss.qualcomm.com, yijie.yang@oss.qualcomm.com, linux-arm-msm@vger.kernel.org, linux-remoteproc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jingyi Wang , Gokul Krishna Krishnakumar X-Mailer: b4 0.15-dev-3d134 X-Developer-Signature: v=1; a=ed25519-sha256; t=1773137028; l=14277; i=jingyi.wang@oss.qualcomm.com; s=20250911; h=from:subject:message-id; bh=9ih3y25HTDZ5f154MkriFpwHfDjyiSzVp5js9La0Zo0=; b=yoj8wg2JjGdYR0r/OEEut4aFo2A8ewCCtrzuQHglbvp+3ANX4deqhQpxNfBvIlP8pqJ1z83hY qEeY+rO5748B5is0AFqTZa1F/qsIprOaKzUbr0xajaWFF5ZR6FkvI7W X-Developer-Key: i=jingyi.wang@oss.qualcomm.com; a=ed25519; pk=PSoHZ6KbUss3IW8FPRVMHMK0Jkkr/jV347mBYJO3iLo= X-Proofpoint-GUID: XXiqSiEvZV13m2kIZkBcn3oNNVtNmXZY X-Proofpoint-ORIG-GUID: XXiqSiEvZV13m2kIZkBcn3oNNVtNmXZY X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMzEwMDA4NiBTYWx0ZWRfX9DmblnsY3DEv fgutexNPyy6jGBYKj2AdXzv0Te+Oe9LwRH/kCMZ2UamK3vzAUvDqItiPEH6OVIPUoJDUH5IsI1Y E6QQsaQbQmolalYwvXyhibnkWLAEOOp0BMITf/qFlbCXvpr6fCIVavOykA5hOZGPHaceWVFl0At pSZ4hIUGTI2JohPUzyqoPJHolvgZ7w8FzwqTzRHHuMi4HbD5usH99fsdRlhJEmIX6JuLrgudFpO h2L8p+rNG8ODds81CgjpsHT/U8Sg1rAJvjnnvasVTNk1Lg/olk4UwGsddfnUSMycJ/cne77nW4b n9a5BK8cL0FSoVhSLpF5Yeo2a8a6zYBqRfYyhSrrJ/NpLVgmBrDbYXCuHXSvRN3uubR1Shi7nU3 KBsJjIwDW6f0yxWzdbYpxX3rmTSxV9PAQMzptiTgatCwSWmW7GvZf29aFcvMrJbUJT+HK5po6dE 19bRZOQQoyJfqyMBheg== X-Authority-Analysis: v=2.4 cv=Cuays34D c=1 sm=1 tr=0 ts=69afec91 cx=c_pps a=+3WqYijBVYhDct2f5Fivkw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=Yq5XynenixoA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yOCtJkima9RkubShWh1s:22 a=EUspDBNiAAAA:8 a=x8meLMyhUKYFESlZP2wA:9 a=QEXdDO2ut3YA:10 a=eYe2g0i6gJ5uXG_o6N4q:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-03-10_01,2026-03-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 clxscore=1015 spamscore=0 adultscore=0 priorityscore=1501 phishscore=0 suspectscore=0 lowpriorityscore=0 bulkscore=0 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2603100086 From: Gokul Krishna Krishnakumar Subsystems can be brought out of reset by entities such as bootloaders. As the irq enablement could be later than subsystem bring up, the state of subsystem should be checked by reading SMP2P bits and performing ping test. A new qcom_pas_attach() function is introduced. if a crash state is detected for the subsystem, rproc_report_crash() is called. If the subsystem is ready either at the first check or within a 5-second timeout and the ping is successful, it will be marked as "attached". The ready state could be set by either ready interrupt or handover interrupt. If "early_boot" is set by kernel but "subsys_booted" is not completed within the timeout, It could be the early boot feature is not supported by other entities. In this case, the state will be marked as RPROC_OFFLINE so that the PAS driver can load the firmware and start the remoteproc. As the running state is set once attach function is called, the watchdog or fatal interrupt received can be handled correctly. Signed-off-by: Gokul Krishna Krishnakumar Co-developed-by: Jingyi Wang Signed-off-by: Jingyi Wang --- drivers/remoteproc/qcom_q6v5.c | 88 +++++++++++++++++++++++++++++- drivers/remoteproc/qcom_q6v5.h | 17 +++++- drivers/remoteproc/qcom_q6v5_adsp.c | 2 +- drivers/remoteproc/qcom_q6v5_mss.c | 2 +- drivers/remoteproc/qcom_q6v5_pas.c | 103 ++++++++++++++++++++++++++++++++= ++-- drivers/remoteproc/qcom_q6v5_wcss.c | 2 +- 6 files changed, 204 insertions(+), 10 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 58d5b85e58cd..abfe3aa71042 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -20,6 +20,7 @@ =20 #define Q6V5_LOAD_STATE_MSG_LEN 64 #define Q6V5_PANIC_DELAY_MS 200 +#define Q6V5_PING_TIMEOUT_MS 500 =20 static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable) { @@ -94,6 +95,9 @@ static irqreturn_t q6v5_wdog_interrupt(int irq, void *dat= a) size_t len; char *msg; =20 + if (q6v5->early_boot) + complete(&q6v5->subsys_booted); + /* Sometimes the stop triggers a watchdog rather than a stop-ack */ if (!q6v5->running) { complete(&q6v5->stop_done); @@ -118,6 +122,9 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *= data) size_t len; char *msg; =20 + if (q6v5->early_boot) + complete(&q6v5->subsys_booted); + if (!q6v5->running) return IRQ_HANDLED; =20 @@ -139,6 +146,9 @@ static irqreturn_t q6v5_ready_interrupt(int irq, void *= data) =20 complete(&q6v5->start_done); =20 + if (q6v5->early_boot) + complete(&q6v5->subsys_booted); + return IRQ_HANDLED; } =20 @@ -172,6 +182,9 @@ static irqreturn_t q6v5_handover_interrupt(int irq, voi= d *data) if (q6v5->handover) q6v5->handover(q6v5); =20 + if (q6v5->early_boot) + complete(&q6v5->subsys_booted); + icc_set_bw(q6v5->path, 0, 0); =20 q6v5->handover_issued =3D true; @@ -234,6 +247,74 @@ unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5) } EXPORT_SYMBOL_GPL(qcom_q6v5_panic); =20 +static irqreturn_t q6v5_pong_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 =3D data; + + complete(&q6v5->ping_done); + + return IRQ_HANDLED; +} + +int qcom_q6v5_ping_subsystem(struct qcom_q6v5 *q6v5) +{ + int ret; + int ping_failed =3D 0; + + reinit_completion(&q6v5->ping_done); + + /* Set master kernel Ping bit */ + ret =3D qcom_smem_state_update_bits(q6v5->ping_state, + BIT(q6v5->ping_bit), BIT(q6v5->ping_bit)); + if (ret) { + dev_err(q6v5->dev, "Failed to update ping bits\n"); + return ret; + } + + ret =3D wait_for_completion_timeout(&q6v5->ping_done, msecs_to_jiffies(Q6= V5_PING_TIMEOUT_MS)); + if (!ret) { + ping_failed =3D -ETIMEDOUT; + dev_err(q6v5->dev, "Failed to get back pong\n"); + } + + /* Clear ping bit master kernel */ + ret =3D qcom_smem_state_update_bits(q6v5->ping_state, BIT(q6v5->ping_bit)= , 0); + if (ret) { + dev_err(q6v5->dev, "Failed to clear master kernel bits\n"); + return ret; + } + + return ping_failed; +} +EXPORT_SYMBOL_GPL(qcom_q6v5_ping_subsystem); + +int qcom_q6v5_ping_subsystem_init(struct qcom_q6v5 *q6v5, struct platform_= device *pdev) +{ + int ret =3D -ENODEV; + + q6v5->ping_state =3D devm_qcom_smem_state_get(&pdev->dev, "ping", &q6v5->= ping_bit); + if (IS_ERR(q6v5->ping_state)) { + dev_err(&pdev->dev, "Failed to acquire smem state %ld\n", + PTR_ERR(q6v5->ping_state)); + return PTR_ERR(q6v5->ping_state); + } + + init_completion(&q6v5->ping_done); + + q6v5->pong_irq =3D platform_get_irq_byname(pdev, "pong"); + if (q6v5->pong_irq < 0) + return q6v5->pong_irq; + + ret =3D devm_request_threaded_irq(&pdev->dev, q6v5->pong_irq, NULL, + q6v5_pong_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 pong", q6v5); + if (ret) + dev_err(&pdev->dev, "Failed to acquire pong IRQ\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(qcom_q6v5_ping_subsystem_init); + /** * qcom_q6v5_init() - initializer of the q6v5 common struct * @q6v5: handle to be initialized @@ -242,12 +323,13 @@ EXPORT_SYMBOL_GPL(qcom_q6v5_panic); * @crash_reason: SMEM id for crash reason string, or 0 if none * @load_state: load state resource string * @handover: function to be called when proxy resources should be released + * @early_boot: true if the subsystem should be brought up by the bootload= er * * Return: 0 on success, negative errno on failure */ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, struct rproc *rproc, int crash_reason, const char *load_state, - void (*handover)(struct qcom_q6v5 *q6v5)) + bool early_boot, void (*handover)(struct qcom_q6v5 *q6v5)) { int ret; =20 @@ -255,10 +337,14 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct pla= tform_device *pdev, q6v5->dev =3D &pdev->dev; q6v5->crash_reason =3D crash_reason; q6v5->handover =3D handover; + q6v5->early_boot =3D early_boot; =20 init_completion(&q6v5->start_done); init_completion(&q6v5->stop_done); =20 + if (early_boot) + init_completion(&q6v5->subsys_booted); + q6v5->wdog_irq =3D platform_get_irq_byname(pdev, "wdog"); if (q6v5->wdog_irq < 0) return q6v5->wdog_irq; diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h index 5a859c41896e..69574a211710 100644 --- a/drivers/remoteproc/qcom_q6v5.h +++ b/drivers/remoteproc/qcom_q6v5.h @@ -17,22 +17,27 @@ struct qcom_q6v5 { struct rproc *rproc; =20 struct qcom_smem_state *state; + struct qcom_smem_state *ping_state; struct qmp *qmp; =20 struct icc_path *path; =20 unsigned stop_bit; + unsigned int ping_bit; =20 int wdog_irq; int fatal_irq; int ready_irq; int handover_irq; int stop_irq; + int pong_irq; =20 bool handover_issued; =20 struct completion start_done; struct completion stop_done; + struct completion subsys_booted; + struct completion ping_done; =20 int crash_reason; =20 @@ -40,10 +45,16 @@ struct qcom_q6v5 { =20 const char *load_state; void (*handover)(struct qcom_q6v5 *q6v5); + + bool early_boot; }; =20 -int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, - struct rproc *rproc, int crash_reason, const char *load_state, +int qcom_q6v5_init(struct qcom_q6v5 *q6v5, + struct platform_device *pdev, + struct rproc *rproc, + int crash_reason, + const char *load_state, + bool early_boot, void (*handover)(struct qcom_q6v5 *q6v5)); void qcom_q6v5_deinit(struct qcom_q6v5 *q6v5); =20 @@ -52,5 +63,7 @@ int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sys= mon); int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout); unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5); +int qcom_q6v5_ping_subsystem(struct qcom_q6v5 *q6v5); +int qcom_q6v5_ping_subsystem_init(struct qcom_q6v5 *q6v5, struct platform_= device *pdev); =20 #endif diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_= q6v5_adsp.c index b5c8d6d38c9c..15b3cdf8c157 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -712,7 +712,7 @@ static int adsp_probe(struct platform_device *pdev) goto disable_pm; =20 ret =3D qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, - desc->load_state, qcom_adsp_pil_handover); + desc->load_state, false, qcom_adsp_pil_handover); if (ret) goto disable_pm; =20 diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q= 6v5_mss.c index 4e9eb5bd11fa..99d48d48c37f 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -2181,7 +2181,7 @@ static int q6v5_probe(struct platform_device *pdev) qproc->has_mba_logs =3D desc->has_mba_logs; =20 ret =3D qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM,= "modem", - qcom_msa_handover); + false, qcom_msa_handover); if (ret) goto detach_proxy_pds; =20 diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q= 6v5_pas.c index 46204da046fa..4700d111e058 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -36,6 +36,8 @@ =20 #define MAX_ASSIGN_COUNT 3 =20 +#define EARLY_ATTACH_TIMEOUT_MS 5000 + struct qcom_pas_data { int crash_reason_smem; const char *firmware_name; @@ -60,6 +62,7 @@ struct qcom_pas_data { int region_assign_count; bool region_assign_shared; int region_assign_vmid; + bool early_boot; }; =20 struct qcom_pas { @@ -423,13 +426,21 @@ static int qcom_pas_stop(struct rproc *rproc) =20 qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); =20 - handover =3D qcom_q6v5_unprepare(&pas->q6v5); - if (handover) - qcom_pas_handover(&pas->q6v5); + /* + * qcom_q6v5_prepare is not called in qcom_pas_attach, skip unprepare to + * avoid mismatch. + */ + if (pas->rproc->state !=3D RPROC_ATTACHED) { + handover =3D qcom_q6v5_unprepare(&pas->q6v5); + if (handover) + qcom_pas_handover(&pas->q6v5); + } =20 if (pas->smem_host_id) ret =3D qcom_smem_bust_hwspin_lock_by_host(pas->smem_host_id); =20 + pas->q6v5.early_boot =3D false; + return ret; } =20 @@ -510,6 +521,80 @@ static unsigned long qcom_pas_panic(struct rproc *rpro= c) return qcom_q6v5_panic(&pas->q6v5); } =20 +static int qcom_pas_attach(struct rproc *rproc) +{ + int ret; + struct qcom_pas *pas =3D rproc->priv; + bool ready_state; + bool crash_state; + + pas->q6v5.running =3D true; + ret =3D irq_get_irqchip_state(pas->q6v5.fatal_irq, + IRQCHIP_STATE_LINE_LEVEL, &crash_state); + + if (!ret && crash_state) { + dev_err(pas->dev, "Sub system has crashed before driver probe\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + ret =3D -EINVAL; + goto disable_running; + } + + if (!ret) + ret =3D irq_get_irqchip_state(pas->q6v5.ready_irq, + IRQCHIP_STATE_LINE_LEVEL, &ready_state); + + /* + * smp2p allocate irq entry can be delayed, irq_get_irqchip_state will ge= t -ENODEV, + * the 5 seconds timeout is set to wait for this, after the entry is allo= cated, smp2p + * will call the qcom_smp2p_intr and complete the timeout in the ISR. + */ + if (unlikely(ret =3D=3D -ENODEV) || unlikely(!ready_state)) { + ret =3D wait_for_completion_timeout(&pas->q6v5.subsys_booted, + msecs_to_jiffies(EARLY_ATTACH_TIMEOUT_MS)); + + /* + * The bootloader may not support early boot, mark the state as + * RPROC_OFFLINE so that the PAS driver can load the firmware and + * start the remoteproc. + */ + if (!ret) { + dev_err(pas->dev, "Timeout on waiting for subsystem interrupt\n"); + pas->rproc->state =3D RPROC_OFFLINE; + ret =3D -ETIMEDOUT; + goto disable_running; + } + + /* Only ping the subsystem if ready_state is set */ + ret =3D irq_get_irqchip_state(pas->q6v5.ready_irq, + IRQCHIP_STATE_LINE_LEVEL, &ready_state); + + if (ret) + goto disable_running; + + if (!ready_state) { + ret =3D -EINVAL; + goto disable_running; + } + } + + ret =3D qcom_q6v5_ping_subsystem(&pas->q6v5); + + if (ret) { + dev_err(pas->dev, "Failed to ping subsystem, assuming device crashed\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + goto disable_running; + } + + pas->q6v5.handover_issued =3D true; + + return 0; + +disable_running: + pas->q6v5.running =3D false; + + return ret; +} + static const struct rproc_ops qcom_pas_ops =3D { .unprepare =3D qcom_pas_unprepare, .start =3D qcom_pas_start, @@ -518,6 +603,7 @@ static const struct rproc_ops qcom_pas_ops =3D { .parse_fw =3D qcom_pas_parse_firmware, .load =3D qcom_pas_load, .panic =3D qcom_pas_panic, + .attach =3D qcom_pas_attach, }; =20 static const struct rproc_ops qcom_pas_minidump_ops =3D { @@ -823,7 +909,7 @@ static int qcom_pas_probe(struct platform_device *pdev) pas->proxy_pd_count =3D ret; =20 ret =3D qcom_q6v5_init(&pas->q6v5, pdev, rproc, desc->crash_reason_smem, - desc->load_state, qcom_pas_handover); + desc->load_state, desc->early_boot, qcom_pas_handover); if (ret) goto detach_proxy_pds; =20 @@ -855,6 +941,15 @@ static int qcom_pas_probe(struct platform_device *pdev) =20 pas->pas_ctx->use_tzmem =3D rproc->has_iommu; pas->dtb_pas_ctx->use_tzmem =3D rproc->has_iommu; + + if (pas->q6v5.early_boot) { + ret =3D qcom_q6v5_ping_subsystem_init(&pas->q6v5, pdev); + if (ret) + dev_warn(&pdev->dev, "Falling back to firmware load\n"); + else + pas->rproc->state =3D RPROC_DETACHED; + } + ret =3D rproc_add(rproc); if (ret) goto remove_ssr_sysmon; diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_= q6v5_wcss.c index c27200159a88..859141589ed7 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -1011,7 +1011,7 @@ static int q6v5_wcss_probe(struct platform_device *pd= ev) if (ret) return ret; =20 - ret =3D qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem,= NULL, NULL); + ret =3D qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem,= NULL, false, NULL); if (ret) return ret; =20 --=20 2.25.1