Skip to content

Commit

Permalink
Merge tag 'rproc-v4.17' of git://github.com/andersson/remoteproc
Browse files Browse the repository at this point in the history
Pull remoteproc updates from Bjorn Andersson:

 - add support for generating coredumps for remoteprocs using
   devcoredump

 - add the Qualcomm sysmon driver for intra-remoteproc crash handling

 - a number of fixes in Qualcomm and IMX drivers

* tag 'rproc-v4.17' of git://github.com/andersson/remoteproc:
  remoteproc: fix null pointer dereference on glink only platforms
  soc: qcom: qmi: add CONFIG_NET dependency
  remoteproc: imx_rproc: Slightly simplify code in 'imx_rproc_probe()'
  remoteproc: imx_rproc: Re-use existing error handling path in 'imx_rproc_probe()'
  remoteproc: imx_rproc: Fix an error handling path in 'imx_rproc_probe()'
  samples: Introduce Qualcomm QMI sample client
  remoteproc: qcom: Introduce sysmon
  remoteproc: Pass type of shutdown to subdev remove
  remoteproc: qcom: Register segments for core dump
  soc: qcom: mdt-loader: Return relocation base
  remoteproc: Rename "load_rsc_table" to "parse_fw"
  remoteproc: Add remote processor coredump support
  remoteproc: Remove null character write of shared mem
  • Loading branch information
Linus Torvalds committed Apr 10, 2018
2 parents 9ab89c4 + 730b2ad commit 92589cb
Show file tree
Hide file tree
Showing 21 changed files with 1,524 additions and 56 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/msm/adreno/a5xx_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname)
*/
if (to_adreno_gpu(gpu)->fwloc == FW_LOCATION_LEGACY) {
ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID,
mem_region, mem_phys, mem_size);
mem_region, mem_phys, mem_size, NULL);
} else {
char newname[strlen("qcom/") + strlen(fwname) + 1];

sprintf(newname, "qcom/%s", fwname);

ret = qcom_mdt_load(dev, fw, newname, GPU_PAS_ID,
mem_region, mem_phys, mem_size);
mem_region, mem_phys, mem_size, NULL);
}
if (ret)
goto out;
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/platform/qcom/venus/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ int venus_boot(struct device *dev, const char *fwname)
}

ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
mem_size);
mem_size, NULL);

release_firmware(mdt);

Expand Down
19 changes: 19 additions & 0 deletions drivers/remoteproc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ config REMOTEPROC
select CRC32
select FW_LOADER
select VIRTIO
select WANT_DEV_COREDUMP
help
Support for remote processors (such as DSP coprocessors). These
are mainly used on embedded systems.
Expand Down Expand Up @@ -90,6 +91,7 @@ config QCOM_ADSP_PIL
depends on QCOM_SMEM
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SYSMON || QCOM_SYSMON=n
select MFD_SYSCON
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
Expand All @@ -107,19 +109,36 @@ config QCOM_Q6V5_PIL
depends on QCOM_SMEM
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SYSMON || QCOM_SYSMON=n
select MFD_SYSCON
select QCOM_RPROC_COMMON
select QCOM_SCM
help
Say y here to support the Qualcomm Peripherial Image Loader for the
Hexagon V5 based remote processors.

config QCOM_SYSMON
tristate "Qualcomm sysmon driver"
depends on RPMSG
depends on ARCH_QCOM
depends on NET
select QCOM_QMI_HELPERS
help
The sysmon driver implements a sysmon QMI client and a handler for
the sys_mon SMD and GLINK channel, which are used for graceful
shutdown, retrieving failure information and propagating information
about other subsystems being shut down.

Say y here if your system runs firmware on any other subsystems, e.g.
modem or DSP.

config QCOM_WCNSS_PIL
tristate "Qualcomm WCNSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SMEM
depends on QCOM_SYSMON || QCOM_SYSMON=n
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
select QCOM_SCM
Expand Down
1 change: 1 addition & 0 deletions drivers/remoteproc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o
obj-$(CONFIG_QCOM_ADSP_PIL) += qcom_adsp_pil.o
obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o
obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o
obj-$(CONFIG_QCOM_SYSMON) += qcom_sysmon.o
obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o
qcom_wcnss_pil-y += qcom_wcnss.o
qcom_wcnss_pil-y += qcom_wcnss_iris.o
Expand Down
23 changes: 11 additions & 12 deletions drivers/remoteproc/imx_rproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,14 @@ static int imx_rproc_probe(struct platform_device *pdev)
/* set some other name then imx */
rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops,
NULL, sizeof(*priv));
if (!rproc) {
ret = -ENOMEM;
goto err;
}
if (!rproc)
return -ENOMEM;

dcfg = of_device_get_match_data(dev);
if (!dcfg)
return -EINVAL;
if (!dcfg) {
ret = -EINVAL;
goto err_put_rproc;
}

priv = rproc->priv;
priv->rproc = rproc;
Expand All @@ -359,8 +359,8 @@ static int imx_rproc_probe(struct platform_device *pdev)
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(dev, "Failed to get clock\n");
rproc_free(rproc);
return PTR_ERR(priv->clk);
ret = PTR_ERR(priv->clk);
goto err_put_rproc;
}

/*
Expand All @@ -370,8 +370,7 @@ static int imx_rproc_probe(struct platform_device *pdev)
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&rproc->dev, "Failed to enable clock\n");
rproc_free(rproc);
return ret;
goto err_put_rproc;
}

ret = rproc_add(rproc);
Expand All @@ -380,13 +379,13 @@ static int imx_rproc_probe(struct platform_device *pdev)
goto err_put_clk;
}

return ret;
return 0;

err_put_clk:
clk_disable_unprepare(priv->clk);
err_put_rproc:
rproc_free(rproc);
err:

return ret;
}

Expand Down
20 changes: 16 additions & 4 deletions drivers/remoteproc/qcom_adsp_pil.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ struct adsp_data {
const char *firmware_name;
int pas_id;
bool has_aggre2_clk;

const char *ssr_name;
const char *sysmon_name;
int ssctl_id;
};

struct qcom_adsp {
Expand Down Expand Up @@ -75,14 +78,17 @@ struct qcom_adsp {
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_subdev smd_subdev;
struct qcom_rproc_ssr ssr_subdev;
struct qcom_sysmon *sysmon;
};

static int adsp_load(struct rproc *rproc, const struct firmware *fw)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;

return qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id,
adsp->mem_region, adsp->mem_phys, adsp->mem_size);
adsp->mem_region, adsp->mem_phys, adsp->mem_size,
&adsp->mem_reloc);

}

static int adsp_start(struct rproc *rproc)
Expand Down Expand Up @@ -177,6 +183,7 @@ static const struct rproc_ops adsp_ops = {
.start = adsp_start,
.stop = adsp_stop,
.da_to_va = adsp_da_to_va,
.parse_fw = qcom_register_dump_segments,
.load = adsp_load,
};

Expand All @@ -201,9 +208,6 @@ static irqreturn_t adsp_fatal_interrupt(int irq, void *dev)

rproc_report_crash(adsp->rproc, RPROC_FATAL_ERROR);

if (!IS_ERR(msg))
msg[0] = '\0';

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -398,6 +402,9 @@ static int adsp_probe(struct platform_device *pdev)
qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
adsp->sysmon = qcom_add_sysmon_subdev(rproc,
desc->sysmon_name,
desc->ssctl_id);

ret = rproc_add(rproc);
if (ret)
Expand All @@ -419,6 +426,7 @@ static int adsp_remove(struct platform_device *pdev)
rproc_del(adsp->rproc);

qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
qcom_remove_sysmon_subdev(adsp->sysmon);
qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
rproc_free(adsp->rproc);
Expand All @@ -432,6 +440,8 @@ static const struct adsp_data adsp_resource_init = {
.pas_id = 1,
.has_aggre2_clk = false,
.ssr_name = "lpass",
.sysmon_name = "adsp",
.ssctl_id = 0x14,
};

static const struct adsp_data slpi_resource_init = {
Expand All @@ -440,6 +450,8 @@ static const struct adsp_data slpi_resource_init = {
.pas_id = 12,
.has_aggre2_clk = true,
.ssr_name = "dsps",
.sysmon_name = "slpi",
.ssctl_id = 0x16,
};

static const struct of_device_id adsp_of_match[] = {
Expand Down
56 changes: 53 additions & 3 deletions drivers/remoteproc/qcom_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/remoteproc.h>
#include <linux/rpmsg/qcom_glink.h>
#include <linux/rpmsg/qcom_smd.h>
#include <linux/soc/qcom/mdt_loader.h>

#include "remoteproc_internal.h"
#include "qcom_common.h"
Expand All @@ -41,7 +42,7 @@ static int glink_subdev_probe(struct rproc_subdev *subdev)
return PTR_ERR_OR_ZERO(glink->edge);
}

static void glink_subdev_remove(struct rproc_subdev *subdev)
static void glink_subdev_remove(struct rproc_subdev *subdev, bool crashed)
{
struct qcom_rproc_glink *glink = to_glink_subdev(subdev);

Expand Down Expand Up @@ -74,11 +75,57 @@ EXPORT_SYMBOL_GPL(qcom_add_glink_subdev);
*/
void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
{
if (!glink->node)
return;

rproc_remove_subdev(rproc, &glink->subdev);
of_node_put(glink->node);
}
EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev);

/**
* qcom_register_dump_segments() - register segments for coredump
* @rproc: remoteproc handle
* @fw: firmware header
*
* Register all segments of the ELF in the remoteproc coredump segment list
*
* Return: 0 on success, negative errno on failure.
*/
int qcom_register_dump_segments(struct rproc *rproc,
const struct firmware *fw)
{
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
const struct elf32_hdr *ehdr;
int ret;
int i;

ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);

for (i = 0; i < ehdr->e_phnum; i++) {
phdr = &phdrs[i];

if (phdr->p_type != PT_LOAD)
continue;

if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)
continue;

if (!phdr->p_memsz)
continue;

ret = rproc_coredump_add_segment(rproc, phdr->p_paddr,
phdr->p_memsz);
if (ret)
return ret;
}

return 0;
}
EXPORT_SYMBOL_GPL(qcom_register_dump_segments);

static int smd_subdev_probe(struct rproc_subdev *subdev)
{
struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
Expand All @@ -88,7 +135,7 @@ static int smd_subdev_probe(struct rproc_subdev *subdev)
return PTR_ERR_OR_ZERO(smd->edge);
}

static void smd_subdev_remove(struct rproc_subdev *subdev)
static void smd_subdev_remove(struct rproc_subdev *subdev, bool crashed)
{
struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);

Expand Down Expand Up @@ -121,6 +168,9 @@ EXPORT_SYMBOL_GPL(qcom_add_smd_subdev);
*/
void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd)
{
if (!smd->node)
return;

rproc_remove_subdev(rproc, &smd->subdev);
of_node_put(smd->node);
}
Expand Down Expand Up @@ -157,7 +207,7 @@ static int ssr_notify_start(struct rproc_subdev *subdev)
return 0;
}

static void ssr_notify_stop(struct rproc_subdev *subdev)
static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed)
{
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);

Expand Down
23 changes: 23 additions & 0 deletions drivers/remoteproc/qcom_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

#include <linux/remoteproc.h>
#include "remoteproc_internal.h"
#include <linux/soc/qcom/qmi.h>

struct qcom_sysmon;

struct qcom_rproc_glink {
struct rproc_subdev subdev;
Expand All @@ -30,11 +33,31 @@ struct qcom_rproc_ssr {
void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);

int qcom_register_dump_segments(struct rproc *rproc, const struct firmware *fw);

void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);

void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
const char *ssr_name);
void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);

#if IS_ENABLED(CONFIG_QCOM_SYSMON)
struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
const char *name,
int ssctl_instance);
void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon);
#else
static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
const char *name,
int ssctl_instance)
{
return NULL;
}

static inline void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon)
{
}
#endif

#endif
Loading

0 comments on commit 92589cb

Please sign in to comment.