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, 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: 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 07f605af0254..c8e23ac53d2f 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) { @@ -3505,6 +3539,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/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); 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 { 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); }