For rproc that doing attach, rproc_start_subdevices() is called only when attach successfully. If rproc_report_crash() is called in the attach function, rproc_boot_recovery()->rproc_stop()->rproc_stop_subdevices()-> glink_subdev_stop() could be called and cause NULL pointer dereference:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000300 Mem abort info: ... pc : qcom_glink_smem_unregister+0x14/0x48 [qcom_glink_smem] lr : glink_subdev_stop+0x1c/0x30 [qcom_common] ... Call trace: qcom_glink_smem_unregister+0x14/0x48 [qcom_glink_smem] (P) glink_subdev_stop+0x1c/0x30 [qcom_common] rproc_stop+0x58/0x17c rproc_trigger_recovery+0xb0/0x150 rproc_crash_handler_work+0xa4/0xc4 process_scheduled_works+0x18c/0x2d8 worker_thread+0x144/0x280 kthread+0x124/0x138 ret_from_fork+0x10/0x20 Code: a9be7bfd 910003fd a90153f3 aa0003f3 (b9430000) ---[ end trace 0000000000000000 ]--- Introduce "subdevs_started" flag to indicate rproc_start_subdevices() has been called successfully. Ensure subdevices are only stopped if they have been started. Signed-off-by: Jingyi Wang <[email protected]> --- drivers/remoteproc/remoteproc_core.c | 4 +++- include/linux/remoteproc.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index f02db1113fae..6e23cb11e515 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1308,6 +1308,7 @@ static int rproc_start(struct rproc *rproc, const struct firmware *fw) goto stop_rproc; } + rproc->subdevs_started = true; rproc->state = RPROC_RUNNING; dev_info(dev, "remote processor %s is now up\n", rproc->name); @@ -1712,7 +1713,8 @@ static int rproc_stop(struct rproc *rproc, bool crashed) return -EINVAL; /* Stop any subdevices for the remote processor */ - rproc_stop_subdevices(rproc, crashed); + if (rproc->subdevs_started) + rproc_stop_subdevices(rproc, crashed); /* the installed resource table is no longer accessible */ ret = rproc_reset_rsc_table_on_stop(rproc); diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 580d324a1e8f..bc6adbd23827 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -539,6 +539,7 @@ enum rproc_features { * @has_iommu: flag to indicate if remote processor is behind an MMU * @auto_boot: flag to indicate if remote processor should be auto-started * @sysfs_read_only: flag to make remoteproc sysfs files read only + * @subdevs_started: flag to indicate if subdevs have started * @dump_segments: list of segments in the firmware * @nb_vdev: number of vdev currently handled by rproc * @elf_class: firmware ELF class @@ -581,6 +582,7 @@ struct rproc { bool has_iommu; bool auto_boot; bool sysfs_read_only; + bool subdevs_started; struct list_head dump_segments; int nb_vdev; u8 elf_class; -- 2.34.1

