From 1417dba1034d644953238add381e31ada3a3a199 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 15 Jul 2019 22:03:27 -0700 Subject: remoteproc: qcom: Move glink_ssr notification after stop glink_ssr is used to signal a remote processor "A" about the stopping of another remote processor "B", so that in the event that remote processor B is ever booted again the fifos of the glink channel between A and B is in a known state. But if remote processor A receives this notification before B is actually stopped the newly reset fifo indices will be interpreted as there being "data" on the channel and either side of the channel will enter a fatal error handler. Move the glink_ssr notification to the "unprepare" state of the rproc_subdev to avoid this issue. This has the side effect of us not notifying the dying remote processor itself about its fate, which has been seen to block in certain resource constraint scenarios. Tested-by: Sibi Sankar Reviewed-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c index 6a448429f223..60650bcc8c67 100644 --- a/drivers/remoteproc/qcom_common.c +++ b/drivers/remoteproc/qcom_common.c @@ -200,7 +200,7 @@ void qcom_unregister_ssr_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier); -static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed) +static void ssr_notify_unprepare(struct rproc_subdev *subdev) { struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev); @@ -220,7 +220,7 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr, const char *ssr_name) { ssr->name = ssr_name; - ssr->subdev.stop = ssr_notify_stop; + ssr->subdev.unprepare = ssr_notify_unprepare; rproc_add_subdev(rproc, &ssr->subdev); } -- cgit v1.2.3 From 6ed756aa0148a5ad0dbdced6f14f22e2f5748d35 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 9 Aug 2019 17:20:57 -0500 Subject: remoteproc: Add a sysfs interface for name This patch adds a sysfs interface that provides the name of the remote processor to userspace. This allows the userspace to identify a remote processor as the remoteproc devices themselves are created based on probe order and can change from one boot to another or at runtime. The name is made available in debugfs originally, and is being retained for now. This can be cleaned up after couple of releases once users get familiar with the new interface. Signed-off-by: Suman Anna Signed-off-by: Bjorn Andersson --- Documentation/ABI/testing/sysfs-class-remoteproc | 10 ++++++++++ drivers/remoteproc/remoteproc_sysfs.c | 11 +++++++++++ 2 files changed, 21 insertions(+) (limited to 'drivers/remoteproc') diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc b/Documentation/ABI/testing/sysfs-class-remoteproc index c3afe9fab646..36094fbeb974 100644 --- a/Documentation/ABI/testing/sysfs-class-remoteproc +++ b/Documentation/ABI/testing/sysfs-class-remoteproc @@ -48,3 +48,13 @@ Description: Remote processor state Writing "stop" will attempt to halt the remote processor and return it to the "offline" state. + +What: /sys/class/remoteproc/.../name +Date: August 2019 +KernelVersion: 5.4 +Contact: Suman Anna +Description: Remote processor name + + Reports the name of the remote processor. This can be used by + userspace in exactly identifying a remote processor and ease + up the usage in modifying the 'firmware' or 'state' files. diff --git a/drivers/remoteproc/remoteproc_sysfs.c b/drivers/remoteproc/remoteproc_sysfs.c index fa4131930106..7f8536b73295 100644 --- a/drivers/remoteproc/remoteproc_sysfs.c +++ b/drivers/remoteproc/remoteproc_sysfs.c @@ -113,9 +113,20 @@ static ssize_t state_store(struct device *dev, } static DEVICE_ATTR_RW(state); +/* Expose the name of the remote processor via sysfs */ +static ssize_t name_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct rproc *rproc = to_rproc(dev); + + return sprintf(buf, "%s\n", rproc->name); +} +static DEVICE_ATTR_RO(name); + static struct attribute *rproc_attrs[] = { &dev_attr_firmware.attr, &dev_attr_state.attr, + &dev_attr_name.attr, NULL }; -- cgit v1.2.3 From f2583fde2719362039a6efb3b4094f46284df541 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 21 Aug 2019 23:35:48 +0530 Subject: remoteproc: qcom: q6v5-mss: fixup q6v5_pds_enable error handling dev_pm_domain_attach_by_name will return NULL if the requested power-domain is not a part device node. This could result in NULL pointer de-reference in q6v5_pds_enable. Fix this by checking for IS_ERR_OR_NULL and forward the appropriate error code. Fixes: 4760a896be88e ("remoteproc: q6v5-mss: Vote for rpmh power domains") Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_mss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 8fcf9d28dd73..de919f2e8b94 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -1282,8 +1282,8 @@ static int q6v5_pds_attach(struct device *dev, struct device **devs, for (i = 0; i < num_pds; i++) { devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]); - if (IS_ERR(devs[i])) { - ret = PTR_ERR(devs[i]); + if (IS_ERR_OR_NULL(devs[i])) { + ret = PTR_ERR(devs[i]) ? : -ENODATA; goto unroll_attach; } } -- cgit v1.2.3 From abbe429d56168b90c03bc548403d72505e4fd6b2 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Mon, 26 Aug 2019 17:38:06 +0200 Subject: remoteproc: stm32: clear MCU PDDS at firmware start When remoteproc stops a firmware, it sets the MCU PDDS flag, allowing the platform to reach the Standby power mode if needed. Symmetrically, clear this flag before running a firmware. This fixes the issue where the system goes to Standby mode when the MCU crashes while MPU is in CSTOP mode. Signed-off-by: Fabien Dessenne Signed-off-by: Bjorn Andersson --- drivers/remoteproc/stm32_rproc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index e2da7198b65f..1c959131d796 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -383,10 +383,21 @@ static void stm32_rproc_add_coredump_trace(struct rproc *rproc) static int stm32_rproc_start(struct rproc *rproc) { + struct stm32_rproc *ddata = rproc->priv; int err; stm32_rproc_add_coredump_trace(rproc); + /* clear remote proc Deep Sleep */ + if (ddata->pdds.map) { + err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg, + ddata->pdds.mask, 0); + if (err) { + dev_err(&rproc->dev, "failed to clear pdds\n"); + return err; + } + } + err = stm32_rproc_set_hold_boot(rproc, false); if (err) return err; -- cgit v1.2.3 From d333de3707785b10c4f42e14f3ff254ac15cd7dc Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Mon, 26 Aug 2019 17:38:29 +0200 Subject: remoteproc: stm32: manage the get_irq probe defer case Manage the -EPROBE_DEFER error case for "wdg" IRQ. Signed-off-by: Fabien Dessenne Signed-off-by: Bjorn Andersson --- drivers/remoteproc/stm32_rproc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 1c959131d796..2cf4b2992bfc 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -517,6 +517,9 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev) int err, irq; irq = platform_get_irq(pdev, 0); + if (irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (irq > 0) { err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0, dev_name(dev), rproc); -- cgit v1.2.3 From d446609df212938c0d4660f8a328f694aa11e5ef Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:38 -0700 Subject: remoteproc: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Ohad Ben-Cohen Cc: Bjorn Andersson Cc: linux-remoteproc@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- drivers/remoteproc/da8xx_remoteproc.c | 4 +--- drivers/remoteproc/keystone_remoteproc.c | 4 ---- drivers/remoteproc/qcom_q6v5.c | 35 +++++--------------------------- 3 files changed, 6 insertions(+), 37 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index b2c7af323ed1..98e0be9476a4 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -249,10 +249,8 @@ static int da8xx_rproc_probe(struct platform_device *pdev) int ret; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "platform_get_irq(pdev, 0) error: %d\n", irq); + if (irq < 0) return irq; - } irq_data = irq_get_irq_data(irq); if (!irq_data) { diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c index 4cb44017af8a..5c4658f00b3d 100644 --- a/drivers/remoteproc/keystone_remoteproc.c +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -424,16 +424,12 @@ static int keystone_rproc_probe(struct platform_device *pdev) ksproc->irq_ring = platform_get_irq_byname(pdev, "vring"); if (ksproc->irq_ring < 0) { ret = ksproc->irq_ring; - dev_err(dev, "failed to get vring interrupt, status = %d\n", - ret); goto disable_clk; } ksproc->irq_fault = platform_get_irq_byname(pdev, "exception"); if (ksproc->irq_fault < 0) { ret = ksproc->irq_fault; - dev_err(dev, "failed to get exception interrupt, status = %d\n", - ret); goto disable_clk; } diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 0d33e3079f0d..cb0f4a0be032 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -187,13 +187,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, init_completion(&q6v5->stop_done); q6v5->wdog_irq = platform_get_irq_byname(pdev, "wdog"); - if (q6v5->wdog_irq < 0) { - if (q6v5->wdog_irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to retrieve wdog IRQ: %d\n", - q6v5->wdog_irq); + if (q6v5->wdog_irq < 0) return q6v5->wdog_irq; - } ret = devm_request_threaded_irq(&pdev->dev, q6v5->wdog_irq, NULL, q6v5_wdog_interrupt, @@ -205,13 +200,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, } q6v5->fatal_irq = platform_get_irq_byname(pdev, "fatal"); - if (q6v5->fatal_irq < 0) { - if (q6v5->fatal_irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to retrieve fatal IRQ: %d\n", - q6v5->fatal_irq); + if (q6v5->fatal_irq < 0) return q6v5->fatal_irq; - } ret = devm_request_threaded_irq(&pdev->dev, q6v5->fatal_irq, NULL, q6v5_fatal_interrupt, @@ -223,13 +213,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, } q6v5->ready_irq = platform_get_irq_byname(pdev, "ready"); - if (q6v5->ready_irq < 0) { - if (q6v5->ready_irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to retrieve ready IRQ: %d\n", - q6v5->ready_irq); + if (q6v5->ready_irq < 0) return q6v5->ready_irq; - } ret = devm_request_threaded_irq(&pdev->dev, q6v5->ready_irq, NULL, q6v5_ready_interrupt, @@ -241,13 +226,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, } q6v5->handover_irq = platform_get_irq_byname(pdev, "handover"); - if (q6v5->handover_irq < 0) { - if (q6v5->handover_irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to retrieve handover IRQ: %d\n", - q6v5->handover_irq); + if (q6v5->handover_irq < 0) return q6v5->handover_irq; - } ret = devm_request_threaded_irq(&pdev->dev, q6v5->handover_irq, NULL, q6v5_handover_interrupt, @@ -260,13 +240,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, disable_irq(q6v5->handover_irq); q6v5->stop_irq = platform_get_irq_byname(pdev, "stop-ack"); - if (q6v5->stop_irq < 0) { - if (q6v5->stop_irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to retrieve stop-ack IRQ: %d\n", - q6v5->stop_irq); + if (q6v5->stop_irq < 0) return q6v5->stop_irq; - } ret = devm_request_threaded_irq(&pdev->dev, q6v5->stop_irq, NULL, q6v5_stop_interrupt, -- cgit v1.2.3