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

Commit 9bc84cff authored by Veerabhadrarao Badiganti's avatar Veerabhadrarao Badiganti
Browse files

msm: ep_pcie: Send pme from panic/reboot handler while in D3hot



Send pme from panic/reboot handler if the device is in D3hot to
bring device state back to D0. This helps PBL to take retrain
the link gracefully as PBL didn't have ability to bring the device
our of D3hot state. Also send MHI to syserr, so that MHI host
wont timeout on M0ack.

Change-Id: I3de45cab30caa332bd00abe8b1ed1487d7889d5f
Signed-off-by: default avatarVeerabhadrarao Badiganti <quic_vbadigan@quicinc.com>
parent a3762090
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -359,6 +359,7 @@ struct ep_pcie_dev_t {
	bool			     m2_autonomous;
	bool			     mhi_soc_reset_en;
	bool			     aoss_rst_clear;
	bool			     avoid_reboot_in_d3hot;
	u32                          dbi_base_reg;
	u32                          slv_space_reg;
	u32                          phy_status_reg;
+64 −0
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@
#include <linux/of_gpio.h>
#include <linux/clk/qcom.h>
#include <linux/reset.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/kdebug.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/interconnect.h>
@@ -3190,6 +3193,49 @@ int ep_pcie_core_config_db_routing(struct ep_pcie_db_config chdb_cfg,
	return 0;
}

static int ep_pcie_core_panic_reboot_callback(struct notifier_block *nb,
					   unsigned long reason, void *arg)
{
	struct ep_pcie_dev_t *dev = &ep_pcie_dev;
	u32 mhi_syserr = BIT(2)|(0xff << 8);
	unsigned long irqsave_flags;

	if (!ep_pcie_dev.avoid_reboot_in_d3hot)
		goto out;

	/* If the device is in D3hot state, bring it to D0 */
	spin_lock_irqsave(&dev->isr_lock, irqsave_flags);
	if (dev->l23_ready && atomic_read(&dev->perst_deast)) {

		EP_PCIE_INFO(dev,
			"PCIe V%d got %s notification while in D3hot\n",
			dev->rev, reason ? "reboot":"panic/die");

		/* Set MHI to SYSERR state */
		if (dev->config_mmio_init)
			ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS,
						mhi_syserr);
		/* Bring device out of D3hot */
		ep_pcie_core_issue_inband_pme();
	}
	spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags);

out:
	return NOTIFY_DONE;
}

static struct notifier_block ep_pcie_core_reboot_notifier = {
	.notifier_call	= ep_pcie_core_panic_reboot_callback,
};

static struct notifier_block ep_pcie_core_die_notifier = {
	.notifier_call	= ep_pcie_core_panic_reboot_callback,
};

static struct notifier_block ep_pcie_core_panic_notifier = {
	.notifier_call	= ep_pcie_core_panic_reboot_callback,
};

struct ep_pcie_hw hw_drv = {
	.register_event	= ep_pcie_core_register_event,
	.deregister_event = ep_pcie_core_deregister_event,
@@ -3361,6 +3407,13 @@ static int ep_pcie_probe(struct platform_device *pdev)
		"PCIe V%d: MHI M2 autonomous is %s enabled\n",
		ep_pcie_dev.rev, ep_pcie_dev.m2_autonomous ? "" : "not");

	ep_pcie_dev.avoid_reboot_in_d3hot =
		of_property_read_bool((&pdev->dev)->of_node,
				"qcom,avoid-reboot-in-d3hot");
	EP_PCIE_DBG(&ep_pcie_dev,
	"PCIe V%d: PME during reboot/panic (in D3hot) is %s needed\n",
	ep_pcie_dev.rev, ep_pcie_dev.avoid_reboot_in_d3hot ? "" : "not");

	ret = of_property_read_u32((&pdev->dev)->of_node,
				"qcom,mhi-soc-reset-offset",
				&ep_pcie_dev.mhi_soc_reset_offset);
@@ -3453,6 +3506,12 @@ static int ep_pcie_probe(struct platform_device *pdev)
	if (ret && !ep_pcie_debug_keep_resource)
		goto irq_deinit;

	register_reboot_notifier(&ep_pcie_core_reboot_notifier);
	/* Handler for wilful crash like BUG_ON */
	register_die_notifier(&ep_pcie_core_die_notifier);
	atomic_notifier_chain_register(&panic_notifier_list,
				       &ep_pcie_core_panic_notifier);

	qcom_edma_init(&pdev->dev);

	if (!ep_pcie_dev.perst_enum)
@@ -3476,6 +3535,11 @@ static int __exit ep_pcie_remove(struct platform_device *pdev)
{
	pr_debug("%s\n", __func__);

	unregister_reboot_notifier(&ep_pcie_core_reboot_notifier);
	unregister_die_notifier(&ep_pcie_core_die_notifier);
	atomic_notifier_chain_unregister(&panic_notifier_list,
					 &ep_pcie_core_panic_notifier);

	ep_pcie_irq_deinit(&ep_pcie_dev);
	ep_pcie_vreg_deinit(&ep_pcie_dev);
	ep_pcie_pipe_clk_deinit(&ep_pcie_dev);