Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d709aeeb authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa
Browse files

USB: phy-msm-usb: Fix unclocked access during disconnect in qdss mode



when cable is disconnected in qdss composition, qdss driver will
queue disconnect work as part of qdss_disable() and doesn't wait
till the disconnect work is completed. This results in crash if
disconnect work is scheduled after USB enters low power mode. Fix
the issue by checking whether usb bam pipe is disconnected or not
and if it is not disconnected, don't allow low power mode and
instead schedule suspend later.

CRs-Fixed: 678631
Change-Id: I72ef57fc4a04407f624fa73cd5abc12f5df3fecc
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
parent 02a2c6ee
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -68,9 +68,6 @@ Optional properties :
	    Used for allowing USB to respond for remote wakup.
- qcom,hsusb-otg-delay-lpm: If present then USB core will wait one second
	after disconnect before entering low power mode.
- qcom,hsusb-otg-delay-lpm-hndshk-on-disconnect: If present then USB core will
	wait for the handshake with the IPA to complete before entering low
	power mode.
- <supply-name>-supply: handle to the regulator device tree node.
         Optional "supply-name" is "vbus_otg" to supply vbus in host mode.
- qcom,dp-manual-pullup: If present, vbus is not routed to USB controller/phy
+18 −0
Original line number Diff line number Diff line
@@ -3443,6 +3443,24 @@ bool msm_bam_device_lpm_ok(enum usb_ctrl bam_type)
		pr_err("%s: Scheduling LPM for later\n", __func__);
		return 0;
	} else {
		int idx = usb_bam_get_qdss_idx(0);
		struct usb_bam_pipe_connect *pipe_connect;

		/*
		 * Disconnecting bam pipes happens in work queue context during
		 * cable disconnect in qdss composition and will access USB bam
		 * registers. There is a chance that USB might have entered low
		 * power mode by the time this work is scheduled and could cause
		 * crash. Hence don't allow low power mode while bam pipes are
		 * still connected.
		 */
		if (idx >= 0) {
			pipe_connect = &usb_bam_connections[idx];
			if (pipe_connect->enabled) {
				spin_unlock(&usb_bam_ipa_handshake_info_lock);
				return 0;
			}
		}
		info[bam_type].pending_lpm = 0;
		info[bam_type].in_lpm = true;
		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+9 −6
Original line number Diff line number Diff line
@@ -900,9 +900,15 @@ phcd_retry:
	if (atomic_read(&motg->in_lpm))
		return 0;

	if (motg->pdata->delay_lpm_hndshk_on_disconnect &&
			!msm_bam_usb_lpm_ok(CI_CTRL))
	/*
	 * Don't allow low power mode if bam pipes are still connected.
	 * Otherwise it could lead to unclocked access when sps driver
	 * accesses USB bam registers as part of disconnecting bam pipes.
	 */
	if (!msm_bam_usb_lpm_ok(CI_CTRL)) {
		pm_schedule_suspend(phy->dev, 1000);
		return -EBUSY;
	}

	motg->ui_enabled = 0;
	disable_irq(motg->irq);
@@ -1153,7 +1159,6 @@ static int msm_otg_resume(struct msm_otg *motg)
	if (!atomic_read(&motg->in_lpm))
		return 0;

	if (motg->pdata->delay_lpm_hndshk_on_disconnect)
	msm_bam_notify_lpm_resume(CI_CTRL);

	if (motg->ui_enabled) {
@@ -4362,8 +4367,6 @@ struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
				"qcom,hsusb-otg-clk-always-on-workaround");
	pdata->delay_lpm_on_disconnect = of_property_read_bool(node,
				"qcom,hsusb-otg-delay-lpm");
	pdata->delay_lpm_hndshk_on_disconnect = of_property_read_bool(node,
				"qcom,hsusb-otg-delay-lpm-hndshk-on-disconnect");
	pdata->dp_manual_pullup = of_property_read_bool(node,
				"qcom,dp-manual-pullup");
	pdata->enable_sec_phy = of_property_read_bool(node,
+0 −1
Original line number Diff line number Diff line
@@ -283,7 +283,6 @@ struct msm_otg_platform_data {
	bool enable_lpm_on_dev_suspend;
	bool core_clk_always_on_workaround;
	bool delay_lpm_on_disconnect;
	bool delay_lpm_hndshk_on_disconnect;
	bool dp_manual_pullup;
	bool enable_sec_phy;
	struct msm_bus_scale_pdata *bus_scale_table;