[PATCH] remoteproc: Create a separate workqueue for recovery tasks

2020-12-12 Thread Rishabh Bhatnagar
Create an unbound high priority workqueue for recovery tasks.
Recovery time is an important parameter for a subsystem and there
might be situations where multiple subsystems crash around the same
time. Scheduling into an unbound workqueue increases parallelization
and avoids time impact. Also creating a high priority workqueue
will utilize separate worker threads with higher nice values than
normal ones.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/remoteproc_core.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 46c2937..8fd8166 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -48,6 +48,8 @@ static DEFINE_MUTEX(rproc_list_mutex);
 static LIST_HEAD(rproc_list);
 static struct notifier_block rproc_panic_nb;
 
+static struct workqueue_struct *rproc_wq;
+
 typedef int (*rproc_handle_resource_t)(struct rproc *rproc,
 void *, int offset, int avail);
 
@@ -2475,7 +2477,7 @@ void rproc_report_crash(struct rproc *rproc, enum 
rproc_crash_type type)
rproc->name, rproc_crash_to_string(type));
 
/* create a new task to handle the error */
-   schedule_work(>crash_handler);
+   queue_work(rproc_wq, >crash_handler);
 }
 EXPORT_SYMBOL(rproc_report_crash);
 
@@ -2520,6 +2522,10 @@ static void __exit rproc_exit_panic(void)
 
 static int __init remoteproc_init(void)
 {
+   rproc_wq = alloc_workqueue("rproc_wq", WQ_UNBOUND | WQ_HIGHPRI, 0);
+   if (!rproc_wq)
+   return -ENOMEM;
+
rproc_init_sysfs();
rproc_init_debugfs();
rproc_init_cdev();
@@ -2536,6 +2542,7 @@ static void __exit remoteproc_exit(void)
rproc_exit_panic();
rproc_exit_debugfs();
rproc_exit_sysfs();
+   destroy_workqueue(rproc_wq);
 }
 module_exit(remoteproc_exit);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] drivers: mdt_loader: Add parallel blobs loading capability

2020-12-09 Thread Rishabh Bhatnagar
Add capability to load blobs parallely during loading
of firmware. Create a high priority unbound workqueue and
schedule work items to load the firmware blobs parallely.
This helps in improving firmware loading times.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/soc/qcom/mdt_loader.c | 147 ++
 1 file changed, 107 insertions(+), 40 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 24cd193..4e5d2aa 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -17,6 +17,26 @@
 #include 
 #include 
 
+static struct workqueue_struct *mdt_wq;
+
+struct fw_desc {
+   size_t mem_size;
+   void *mem_region;
+   const struct firmware *fw;
+   char *fw_name;
+   struct device *dev;
+   size_t fw_name_len;
+   phys_addr_t mem_reloc;
+};
+
+struct mdt_seg_data {
+   struct work_struct load_seg_work;
+   const struct elf32_phdr *phdr;
+   int seg_num;
+   int result;
+   struct fw_desc *desc;
+};
+
 static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
 {
if (phdr->p_type != PT_LOAD)
@@ -126,6 +146,62 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, 
size_t *data_len)
 }
 EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);
 
+static void mdt_load_seg_work_fn(struct work_struct *work)
+{
+   struct mdt_seg_data *mdt_seg_data = container_of(work, struct 
mdt_seg_data, load_seg_work);
+   struct fw_desc *desc = mdt_seg_data->desc;
+   int seg_num = mdt_seg_data->seg_num;
+   const struct elf32_phdr *phdr = mdt_seg_data->phdr;
+   const struct firmware *seg_fw;
+   ssize_t offset;
+   void *ptr;
+   int ret;
+   char *fw_name = kstrdup(desc->fw_name, GFP_KERNEL);
+
+   if (!mdt_phdr_valid(phdr))
+   goto fw_free;
+
+   offset = phdr->p_paddr - desc->mem_reloc;
+   if (offset < 0 || offset + phdr->p_memsz > desc->mem_size) {
+   dev_err(desc->dev, "segment outside memory range\n");
+   mdt_seg_data->result = -EINVAL;
+   goto fw_free;
+   }
+
+   ptr = desc->mem_region + offset;
+
+   if (phdr->p_filesz && phdr->p_offset < desc->fw->size) {
+   /* Firmware is large enough to be non-split */
+   if (phdr->p_offset + phdr->p_filesz > desc->fw->size) {
+   dev_err(desc->dev,
+   "failed to load segment %d from truncated file 
%s\n",
+   seg_num, desc->fw_name);
+   mdt_seg_data->result = -EINVAL;
+   goto fw_free;
+   }
+
+   memcpy(ptr, desc->fw->data + phdr->p_offset, phdr->p_filesz);
+   } else if (phdr->p_filesz) {
+   /* Firmware not large enough, load split-out segments */
+   sprintf(fw_name + desc->fw_name_len - 3, "b%02d", seg_num);
+   ret = request_firmware_into_buf(_fw, fw_name, desc->dev,
+   ptr, phdr->p_filesz);
+   if (ret) {
+   dev_err(desc->dev, "failed to load %s\n", fw_name);
+   mdt_seg_data->result = -EINVAL;
+   goto fw_free;
+   }
+
+   release_firmware(seg_fw);
+   }
+
+   if (phdr->p_memsz > phdr->p_filesz)
+   memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
+
+fw_free:
+   kfree(fw_name);
+}
+
 static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
   const char *firmware, int pas_id, void *mem_region,
   phys_addr_t mem_phys, size_t mem_size,
@@ -134,19 +210,18 @@ static int __qcom_mdt_load(struct device *dev, const 
struct firmware *fw,
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
const struct elf32_hdr *ehdr;
-   const struct firmware *seg_fw;
+   struct mdt_seg_data *segs;
phys_addr_t mem_reloc;
phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
size_t metadata_len;
size_t fw_name_len;
-   ssize_t offset;
void *metadata;
char *fw_name;
bool relocate = false;
-   void *ptr;
int ret = 0;
int i;
+   struct fw_desc *desc = kzalloc(sizeof(*desc), GFP_KERNEL);
 
if (!fw || !mem_region || !mem_phys || !mem_size)
return -EINVAL;
@@ -217,54 +292,46 @@ static int __qcom_mdt_load(struct device *dev, const 
struct firmware *fw,
mem_reloc = mem_phys;
}
 
-   for (i = 0; i < ehdr->e_phnum; i++) {
-   phdr = [i];
+   if (!mdt_wq)
+   mdt_wq = alloc_workqueue("mdt_workqueue&

[PATCH v2 1/3] soc: qcom: Add tracepoints to mdt loader

2020-11-16 Thread Rishabh Bhatnagar
Add trace events to the mdt loader driver. These events
can help us trace the region where we are loading the
segments and the time it takes to initialize the image
and setup the memory region.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/soc/qcom/mdt_loader.c |  7 +++
 include/trace/events/mdt_loader.h | 38 ++
 2 files changed, 45 insertions(+)
 create mode 100644 include/trace/events/mdt_loader.h

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 24cd193..96dc912 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -17,6 +17,9 @@
 #include 
 #include 
 
+#define CREATE_TRACE_POINTS
+#include 
+
 static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
 {
if (phdr->p_type != PT_LOAD)
@@ -198,6 +201,7 @@ static int __qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
if (pas_init) {
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
 max_addr - min_addr);
+
if (ret) {
dev_err(dev, "unable to setup relocation\n");
goto out;
@@ -232,6 +236,7 @@ static int __qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
 
ptr = mem_region + offset;
 
+
if (phdr->p_filesz && phdr->p_offset < fw->size) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
@@ -256,6 +261,8 @@ static int __qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
release_firmware(seg_fw);
}
 
+   trace_qcom_mdt_load_segment(mem_phys + offset, phdr->p_filesz,
+   fw_name);
if (phdr->p_memsz > phdr->p_filesz)
memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - 
phdr->p_filesz);
}
diff --git a/include/trace/events/mdt_loader.h 
b/include/trace/events/mdt_loader.h
new file mode 100644
index 000..01c2461
--- /dev/null
+++ b/include/trace/events/mdt_loader.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mdt_loader
+
+#if !defined(_TRACE_MDT_LOADER_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MDT_LOADER_H
+
+#include 
+#include 
+
+TRACE_EVENT(qcom_mdt_load_segment,
+
+   TP_PROTO(phys_addr_t region_start, size_t region_size, const char *fw),
+
+   TP_ARGS(region_start, region_size, fw),
+
+   TP_STRUCT__entry(
+   __field(phys_addr_t, region_start)
+   __field(size_t, region_size)
+   __string(fw, fw)
+   ),
+
+   TP_fast_assign(
+   __entry->region_start = region_start;
+   __entry->region_size = region_size;
+   __assign_str(fw, fw);
+   ),
+
+   TP_printk("firmware:%s region start=%pa size=%zx",
+ __get_str(fw), __entry->region_start, __entry->region_size)
+);
+
+#endif
+#include 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 0/3] Add events to trace remoteproc lifecycle

2020-11-16 Thread Rishabh Bhatnagar
Insert tracepoints in mdt_loader, qcom_scm and remoteproc_core drivers.
These tracepoints will be used to analyze the time taken
at each step during bootup/shutdown of the remoteproc. Tracepoints
in mdt_loader driver provides information about location and size
of firmware segments being loaded. Also trace the scm pas calls
used to boot/load remote processors.

Changelog:

v2 -> v1:
- Add traces in qcom_scm driver
- Add traces in remoteproc core to trace the remoteproc state
- Trace the physical address where segment is loaded in mdt_loader

Rishabh Bhatnagar (3):
  soc: qcom: Add tracepoints to mdt loader
  firmware: scm: Add tracepoints to scm driver for pas calls
  remoteproc: Add ftrace events to trace lifecycle of remoteprocs

 drivers/firmware/qcom_scm.c  |  9 
 drivers/remoteproc/remoteproc_core.c | 19 +++-
 drivers/soc/qcom/mdt_loader.c|  7 +++
 include/trace/events/mdt_loader.h| 38 +++
 include/trace/events/qcom_scm.h  | 34 ++
 include/trace/events/remoteproc.h| 91 
 6 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 include/trace/events/mdt_loader.h
 create mode 100644 include/trace/events/qcom_scm.h
 create mode 100644 include/trace/events/remoteproc.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 2/3] firmware: scm: Add tracepoints to scm driver for pas calls

2020-11-16 Thread Rishabh Bhatnagar
Add trace events to the qcom_scm driver to trace pas calls.
These events can help us analyze the time impact for each scm
operation and can also serve as standard checkpoints in code.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/firmware/qcom_scm.c |  9 +
 include/trace/events/qcom_scm.h | 34 ++
 2 files changed, 43 insertions(+)
 create mode 100644 include/trace/events/qcom_scm.h

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 7be48c1..5bc9b65 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -19,6 +19,9 @@
 
 #include "qcom_scm.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 static bool download_mode = IS_ENABLED(CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT);
 module_param(download_mode, bool, 0);
 
@@ -442,6 +445,7 @@ int qcom_scm_pas_init_image(u32 peripheral, const void 
*metadata, size_t size)
};
struct qcom_scm_res res;
 
+   trace_qcom_scm_call("Start scm_pas_init_image");
/*
 * During the scm call memory protection will be enabled for the meta
 * data blob, so make sure it's physically contiguous, 4K aligned and
@@ -467,6 +471,7 @@ int qcom_scm_pas_init_image(u32 peripheral, const void 
*metadata, size_t size)
 
 free_metadata:
dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
+   trace_qcom_scm_call("Complete scm_pas_init_image");
 
return ret ? : res.result[0];
 }
@@ -495,6 +500,7 @@ int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t 
addr, phys_addr_t size)
};
struct qcom_scm_res res;
 
+   trace_qcom_scm_call("Start scm_pas_mem_setup");
ret = qcom_scm_clk_enable();
if (ret)
return ret;
@@ -502,6 +508,7 @@ int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t 
addr, phys_addr_t size)
ret = qcom_scm_call(__scm->dev, , );
qcom_scm_clk_disable();
 
+   trace_qcom_scm_call("Complete scm_pas_mem_setup");
return ret ? : res.result[0];
 }
 EXPORT_SYMBOL(qcom_scm_pas_mem_setup);
@@ -525,6 +532,7 @@ int qcom_scm_pas_auth_and_reset(u32 peripheral)
};
struct qcom_scm_res res;
 
+   trace_qcom_scm_call("Start auth_and_reset");
ret = qcom_scm_clk_enable();
if (ret)
return ret;
@@ -532,6 +540,7 @@ int qcom_scm_pas_auth_and_reset(u32 peripheral)
ret = qcom_scm_call(__scm->dev, , );
qcom_scm_clk_disable();
 
+   trace_qcom_scm_call("Complete  auth_and_reset");
return ret ? : res.result[0];
 }
 EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);
diff --git a/include/trace/events/qcom_scm.h b/include/trace/events/qcom_scm.h
new file mode 100644
index 000..d918332
--- /dev/null
+++ b/include/trace/events/qcom_scm.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_scm
+
+#if !defined(_TRACE_QCOM_SCM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_QCOM_SCM_H
+
+#include 
+#include 
+
+TRACE_EVENT(qcom_scm_call,
+
+   TP_PROTO(const char *event),
+
+   TP_ARGS(event),
+
+   TP_STRUCT__entry(
+   __string(event, event)
+   ),
+
+   TP_fast_assign(
+   __assign_str(event, event);
+   ),
+
+   TP_printk("qcom_scm_call event:%s", __get_str(event))
+);
+
+#endif
+#include 
+
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 3/3] remoteproc: Add ftrace events to trace lifecycle of remoteprocs

2020-11-16 Thread Rishabh Bhatnagar
Add trace events to trace bootup/shutdown/recovery of remote
processors. These events are useful in analyzing the time
spent in each step in the life cycle and can be used for
performace analysis. Also these serve as standard checkpoints
in debugging.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/remoteproc_core.c | 19 +++-
 include/trace/events/remoteproc.h| 91 
 2 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 include/trace/events/remoteproc.h

diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index dab2c0f..39da409 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -42,6 +42,9 @@
 
 #include "remoteproc_internal.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 #define HIGH_BITS_MASK 0xULL
 
 static DEFINE_MUTEX(rproc_list_mutex);
@@ -1164,6 +1167,7 @@ static int rproc_prepare_subdevices(struct rproc *rproc)
struct rproc_subdev *subdev;
int ret;
 
+   trace_rproc_subdevices("Prepare subdevices", rproc->name);
list_for_each_entry(subdev, >subdevs, node) {
if (subdev->prepare) {
ret = subdev->prepare(subdev);
@@ -1188,6 +1192,7 @@ static int rproc_start_subdevices(struct rproc *rproc)
struct rproc_subdev *subdev;
int ret;
 
+   trace_rproc_subdevices("Start subdevices", rproc->name);
list_for_each_entry(subdev, >subdevs, node) {
if (subdev->start) {
ret = subdev->start(subdev);
@@ -1211,6 +1216,7 @@ static void rproc_stop_subdevices(struct rproc *rproc, 
bool crashed)
 {
struct rproc_subdev *subdev;
 
+   trace_rproc_subdevices("Stop subdevices", rproc->name);
list_for_each_entry_reverse(subdev, >subdevs, node) {
if (subdev->stop)
subdev->stop(subdev, crashed);
@@ -1221,6 +1227,7 @@ static void rproc_unprepare_subdevices(struct rproc 
*rproc)
 {
struct rproc_subdev *subdev;
 
+   trace_rproc_subdevices("Unprepare subdevices", rproc->name);
list_for_each_entry_reverse(subdev, >subdevs, node) {
if (subdev->unprepare)
subdev->unprepare(subdev);
@@ -1357,6 +1364,7 @@ static int rproc_start(struct rproc *rproc, const struct 
firmware *fw)
struct device *dev = >dev;
int ret;
 
+   trace_rproc_boot("loading firmware segments into memory", rproc->name);
/* load the ELF segments to memory */
ret = rproc_load_segments(rproc, fw);
if (ret) {
@@ -1385,6 +1393,7 @@ static int rproc_start(struct rproc *rproc, const struct 
firmware *fw)
goto reset_table_ptr;
}
 
+   trace_rproc_boot("starting remoteproc", rproc->name);
/* power up the remote processor */
ret = rproc->ops->start(rproc);
if (ret) {
@@ -1402,6 +1411,7 @@ static int rproc_start(struct rproc *rproc, const struct 
firmware *fw)
 
rproc->state = RPROC_RUNNING;
 
+   trace_rproc_boot("remoteproc is up", rproc->name);
dev_info(dev, "remote processor %s is now up\n", rproc->name);
 
return 0;
@@ -1648,6 +1658,7 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
/* the installed resource table is no longer accessible */
rproc->table_ptr = rproc->cached_table;
 
+   trace_rproc_shutdown("Stopping the remoteproc", rproc->name);
/* power off the remote processor */
ret = rproc->ops->stop(rproc);
if (ret) {
@@ -1697,6 +1708,7 @@ int rproc_trigger_recovery(struct rproc *rproc)
if (rproc->state != RPROC_CRASHED)
goto unlock_mutex;
 
+   trace_rproc_recovery("Recover remoteproc", rproc->name);
dev_err(dev, "recovering %s\n", rproc->name);
 
ret = rproc_stop(rproc, true);
@@ -1716,6 +1728,7 @@ int rproc_trigger_recovery(struct rproc *rproc)
/* boot the remote processor up again */
ret = rproc_start(rproc, firmware_p);
 
+   trace_rproc_recovery("Recovery completed", rproc->name);
release_firmware(firmware_p);
 
 unlock_mutex:
@@ -1796,6 +1809,7 @@ int rproc_boot(struct rproc *rproc)
/* skip the boot or attach process if rproc is already powered up */
if (atomic_inc_return(>power) > 1) {
ret = 0;
+   trace_rproc_boot("Incrementing ref count and exiting", 
rproc->name);
goto unlock_mutex;
}
 
@@ -1804,6 +1818,7 @@ int rproc_boot(struct rproc *rproc)
 
ret = rproc_actuate(rproc);
} else {
+   trace_rproc_boot("requesting firmw

[PATCH 2/2] remoteproc: qcom: Add trace events for q6v5_pas driver

2020-11-09 Thread Rishabh Bhatnagar
Add tracepoints for q6v5_pas driver. These will help in
analyzing the time taken by each step in remoteproc
bootup/shutdown process and also serve as standard
checkpoints in code.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_q6v5_pas.c | 11 +++
 include/trace/events/q6v5_pas.h| 34 ++
 2 files changed, 45 insertions(+)
 create mode 100644 include/trace/events/q6v5_pas.h

diff --git a/drivers/remoteproc/qcom_q6v5_pas.c 
b/drivers/remoteproc/qcom_q6v5_pas.c
index 3837f23..b3c0a6a 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -29,6 +29,9 @@
 #include "qcom_q6v5.h"
 #include "remoteproc_internal.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 struct adsp_data {
int crash_reason_smem;
const char *firmware_name;
@@ -121,12 +124,14 @@ static int adsp_load(struct rproc *rproc, const struct 
firmware *fw)
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
int ret;
 
+   trace_q6v5_pas("setting up memory and loading segments", rproc->name);
ret = qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id,
adsp->mem_region, adsp->mem_phys, adsp->mem_size,
>mem_reloc);
if (ret)
return ret;
 
+   trace_q6v5_pas("done loading segments", rproc->name);
qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
 
return 0;
@@ -137,6 +142,7 @@ static int adsp_start(struct rproc *rproc)
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
int ret;
 
+   trace_q6v5_pas("Voting for resources", rproc->name);
qcom_q6v5_prepare(>q6v5);
 
ret = adsp_pds_enable(adsp, adsp->active_pds, adsp->active_pd_count);
@@ -163,12 +169,14 @@ static int adsp_start(struct rproc *rproc)
if (ret)
goto disable_cx_supply;
 
+   trace_q6v5_pas("Before authenticate and reset", rproc->name);
ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
if (ret) {
dev_err(adsp->dev,
"failed to authenticate image and release reset\n");
goto disable_px_supply;
}
+   trace_q6v5_pas("After authenticate and reset", rproc->name);
 
ret = qcom_q6v5_wait_for_start(>q6v5, msecs_to_jiffies(5000));
if (ret == -ETIMEDOUT) {
@@ -177,6 +185,7 @@ static int adsp_start(struct rproc *rproc)
goto disable_px_supply;
}
 
+   trace_q6v5_pas("Remoteproc is up", rproc->name);
return 0;
 
 disable_px_supply:
@@ -214,6 +223,7 @@ static int adsp_stop(struct rproc *rproc)
int handover;
int ret;
 
+   trace_q6v5_pas("Request stop", rproc->name);
ret = qcom_q6v5_request_stop(>q6v5);
if (ret == -ETIMEDOUT)
dev_err(adsp->dev, "timed out on wait\n");
@@ -227,6 +237,7 @@ static int adsp_stop(struct rproc *rproc)
if (handover)
qcom_pas_handover(>q6v5);
 
+   trace_q6v5_pas("Remoteproc is down", rproc->name);
return ret;
 }
 
diff --git a/include/trace/events/q6v5_pas.h b/include/trace/events/q6v5_pas.h
new file mode 100644
index 000..38ee5e2
--- /dev/null
+++ b/include/trace/events/q6v5_pas.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM q6v5_pas
+
+#if !defined(_TRACE_Q6V5_PAS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_Q6V5_PAS_H
+
+#include 
+
+TRACE_EVENT(q6v5_pas,
+
+   TP_PROTO(const char *event, const char *rproc_name),
+
+   TP_ARGS(event, rproc_name),
+
+   TP_STRUCT__entry(
+   __string(event, event)
+   __string(rproc_name, rproc_name)
+   ),
+
+   TP_fast_assign(
+   __assign_str(event, event);
+   __assign_str(rproc_name, rproc_name);
+   ),
+
+   TP_printk("event=%s remoteproc:%s", __get_str(event), 
__get_str(rproc_name))
+);
+
+#endif
+#include 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/2] Add trace events to q6v5_pas and mdt_loader driver

2020-11-09 Thread Rishabh Bhatnagar
Create and insert trace points in mdt_loader and qcom_q6v5_pas
drivers. These tracepoints will be used to analyze the time taken
at each step during bootup/shutdown of the remoteproc. Also 
provide information about location and size of firmware segments
being loaded.

Rishabh Bhatnagar (2):
  soc: qcom: Add tracepoints to mdt loader
  remoteproc: qcom: Add trace events for q6v5_pas driver

 drivers/remoteproc/qcom_q6v5_pas.c | 11 
 drivers/soc/qcom/mdt_loader.c  |  8 ++
 include/trace/events/mdt_loader.h  | 57 ++
 include/trace/events/q6v5_pas.h| 34 +++
 4 files changed, 110 insertions(+)
 create mode 100644 include/trace/events/mdt_loader.h
 create mode 100644 include/trace/events/q6v5_pas.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 1/2] soc: qcom: Add tracepoints to mdt loader

2020-11-09 Thread Rishabh Bhatnagar
Add trace events to the mdt loader driver. These events
can help us trace the region where we are loading the
segments and the time it takes to initialize the image
and setup the memory region.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/soc/qcom/mdt_loader.c |  8 ++
 include/trace/events/mdt_loader.h | 57 +++
 2 files changed, 65 insertions(+)
 create mode 100644 include/trace/events/mdt_loader.h

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 24cd193..df69e23 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -17,6 +17,9 @@
 #include 
 #include 
 
+#define CREATE_TRACE_POINTS
+#include 
+
 static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
 {
if (phdr->p_type != PT_LOAD)
@@ -169,6 +172,7 @@ static int __qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
goto out;
}
 
+   trace_memory_setup("pas_init_image", fw_name);
ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len);
 
kfree(metadata);
@@ -196,8 +200,10 @@ static int __qcom_mdt_load(struct device *dev, const 
struct firmware *fw,
 
if (relocate) {
if (pas_init) {
+   trace_memory_setup("pas_mem_setup", fw_name);
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
 max_addr - min_addr);
+
if (ret) {
dev_err(dev, "unable to setup relocation\n");
goto out;
@@ -232,6 +238,8 @@ static int __qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
 
ptr = mem_region + offset;
 
+   trace_regions(ptr, phdr->p_filesz, i);
+
if (phdr->p_filesz && phdr->p_offset < fw->size) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
diff --git a/include/trace/events/mdt_loader.h 
b/include/trace/events/mdt_loader.h
new file mode 100644
index 000..6299f65
--- /dev/null
+++ b/include/trace/events/mdt_loader.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mdt_loader
+
+#if !defined(_TRACE_MDT_LOADER_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MDT_LOADER_H
+
+#include 
+#include 
+
+TRACE_EVENT(memory_setup,
+
+   TP_PROTO(const char *event, char *fw_name),
+
+   TP_ARGS(event, fw_name),
+
+   TP_STRUCT__entry(
+   __string(event, event)
+   __string(fw_name, fw_name)
+   ),
+
+   TP_fast_assign(
+   __assign_str(event, event);
+   __assign_str(fw_name, fw_name);
+   ),
+
+   TP_printk("doing %s for %s", __get_str(event), __get_str(fw_name))
+);
+
+TRACE_EVENT(regions,
+
+   TP_PROTO(void *region_start, size_t region_size, int i),
+
+   TP_ARGS(region_start, region_size, i),
+
+   TP_STRUCT__entry(
+   __field(void *, region_start)
+   __field(size_t, region_size)
+   __field(int, index)
+   ),
+
+   TP_fast_assign(
+   __entry->region_start = region_start;
+   __entry->region_size = region_size;
+   __entry->index = i;
+   ),
+
+   TP_printk("segment %d: region start=%pK size=%zx", __entry->index,
+ __entry->region_start, __entry->region_size)
+);
+
+#endif
+#include 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] remoteproc: qcom: Add notification timeouts

2020-10-29 Thread Rishabh Bhatnagar
Clients can register their callbacks for power-on/off notifications
of remote processors. While executing the notifier chain sometimes
these callbacks may get stuck or take a long time which is not desired.
To detect such cases this patch introduces a timeout and prints out a
warning indicating that notifier chain is taking a long time.
The timeout is set to 20secs by default and can be adjusted.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/Kconfig   | 16 
 drivers/remoteproc/qcom_common.c | 41 
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index d99548f..e1e623e 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -234,6 +234,22 @@ config QCOM_WCNSS_PIL
  Say y here to support the Peripheral Image Loader for the Qualcomm
  Wireless Connectivity Subsystem.
 
+config QCOM_NOTIFY_TIMEOUT
+   int "Default timeout for ssr notifications to complete (in 
milliseconds)"
+   depends on QCOM_RPROC_COMMON
+   default 2
+   help
+ As part of ssr notification clients can register their callbacks
+ to a notifier chain which is invoked whenever the remoteproc
+ powers-on/off. This option controls the timeout for ssr notifications
+ to complete.
+ This is a good to have debug feature as sometimes callbacks
+ can get stuck or take a long time. This feature helps in identifying
+ such scenarios.
+
+ The default value is kept as 20 secs and should be left as it is
+ in most cases.
+
 config ST_REMOTEPROC
tristate "ST remoteproc support"
depends on ARCH_STI
diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 085fd73..d72c4f5 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -29,6 +29,8 @@ struct qcom_ssr_subsystem {
const char *name;
struct srcu_notifier_head notifier_list;
struct list_head list;
+   struct timer_list notify_timer;
+   const char *notify_type;
 };
 
 static LIST_HEAD(qcom_ssr_subsystem_list);
@@ -198,6 +200,14 @@ void qcom_remove_smd_subdev(struct rproc *rproc, struct 
qcom_rproc_subdev *smd)
 }
 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
 
+static void notify_timeout_handler(struct timer_list *t)
+{
+   struct qcom_ssr_subsystem *info = from_timer(info, t, notify_timer);
+
+   WARN(1, "srcu notifier chain for %s:%s taking too long", info->name,
+info->notify_type);
+}
+
 static struct qcom_ssr_subsystem *qcom_ssr_get_subsys(const char *name)
 {
struct qcom_ssr_subsystem *info;
@@ -216,6 +226,9 @@ static struct qcom_ssr_subsystem *qcom_ssr_get_subsys(const 
char *name)
info->name = kstrdup_const(name, GFP_KERNEL);
srcu_init_notifier_head(>notifier_list);
 
+   /* Setup the notification timer */
+   timer_setup(>notify_timer, notify_timeout_handler, 0);
+
/* Add to global notification list */
list_add_tail(>list, _ssr_subsystem_list);
 
@@ -266,6 +279,18 @@ int qcom_unregister_ssr_notifier(void *notify, struct 
notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
+static inline void notify_ssr_clients(struct qcom_rproc_ssr *ssr,
+ enum qcom_ssr_notify_type type,
+ struct qcom_ssr_notify_data *data)
+{
+   unsigned long timeout;
+
+   timeout = jiffies + msecs_to_jiffies(CONFIG_QCOM_NOTIFY_TIMEOUT);
+   mod_timer(>info->notify_timer, timeout);
+   srcu_notifier_call_chain(>info->notifier_list, type, data);
+   del_timer_sync(>info->notify_timer);
+}
+
 static int ssr_notify_prepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
@@ -274,8 +299,8 @@ static int ssr_notify_prepare(struct rproc_subdev *subdev)
.crashed = false,
};
 
-   srcu_notifier_call_chain(>info->notifier_list,
-QCOM_SSR_BEFORE_POWERUP, );
+   ssr->info->notify_type = "BEFORE_POWERUP";
+   notify_ssr_clients(ssr, QCOM_SSR_BEFORE_POWERUP, );
return 0;
 }
 
@@ -287,8 +312,8 @@ static int ssr_notify_start(struct rproc_subdev *subdev)
.crashed = false,
};
 
-   srcu_notifier_call_chain(>info->notifier_list,
-QCOM_SSR_AFTER_POWERUP, );
+   ssr->info->notify_type = "AFTER_POWERUP";
+   notify_ssr_clients(ssr, QCOM_SSR_AFTER_POWERUP, );
return 0;
 }
 
@@ -300,8 +325,8 @@ static void ssr_notify_stop(struct rproc_subdev *subdev, 
bool crashed)
.crashed = crashed,
};
 
-   srcu_notifier_call_chain(>info->notifier_list,
-   

[PATCH v7 0/3] Move recovery/coredump configuration to sysfs

2020-10-02 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. 'Coredump' and 'Recovery' are critical
interfaces that are required for remoteproc to work on Qualcomm Chipsets.
This patch series adds recovery/coredump configuration to sysfs interface
and disables coredump collection by default. Having coredump disabled by
default on production devices makes sense.

Changelog:

v7 -> v6:
- Keep the debugfs entries intact for now.
- Reorder the patches to have a consistent sysfs interface.

v6 -> v5:
- Disable coredump collection by default
- Rename the "default" configuration to "enabled" to avoid confusion

v5 -> v4:
- Fix the cover-letter of tha patch series.

v4 -> v3:
- Remove the feature flag to expose recovery/coredump

v3 -> v2:
- Remove the coredump/recovery entries from debugfs
- Expose recovery/coredump from sysfs under a feature flag

v1 -> v2:
- Correct the contact name in the sysfs documentation.
- Remove the redundant write documentation for coredump/recovery sysfs
- Add a feature flag to make this interface switch configurable.

Rishabh Bhatnagar (3):
  remoteproc: Change default dump configuration to "disabled"
  remoteproc: Add coredump as part of sysfs interface
  remoteproc: Add recovery configuration to the sysfs interface

 Documentation/ABI/testing/sysfs-class-remoteproc |  44 +
 drivers/remoteproc/remoteproc_coredump.c |   6 +-
 drivers/remoteproc/remoteproc_debugfs.c  |  23 +++--
 drivers/remoteproc/remoteproc_sysfs.c| 119 +++
 include/linux/remoteproc.h   |   8 +-
 5 files changed, 181 insertions(+), 19 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 1/3] remoteproc: Change default dump configuration to "disabled"

2020-10-02 Thread Rishabh Bhatnagar
Currently "default" configuration option means coredumps are
enabled. To avoid confusion rename the "default" configuration
option to "enabled" and disable collection of dumps by default
as doing so makes sense for production devices.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/remoteproc_coredump.c |  6 +++---
 drivers/remoteproc/remoteproc_debugfs.c  | 23 +++
 include/linux/remoteproc.h   |  8 
 3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index bb15a29..34530dc 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -257,7 +257,7 @@ void rproc_coredump(struct rproc *rproc)
 * directly read from device memory.
 */
data_size += elf_size_of_phdr(class);
-   if (dump_conf == RPROC_COREDUMP_DEFAULT)
+   if (dump_conf == RPROC_COREDUMP_ENABLED)
data_size += segment->size;
 
phnum++;
@@ -297,14 +297,14 @@ void rproc_coredump(struct rproc *rproc)
elf_phdr_set_p_flags(class, phdr, PF_R | PF_W | PF_X);
elf_phdr_set_p_align(class, phdr, 0);
 
-   if (dump_conf == RPROC_COREDUMP_DEFAULT)
+   if (dump_conf == RPROC_COREDUMP_ENABLED)
rproc_copy_segment(rproc, data + offset, segment, 0,
   segment->size);
 
offset += elf_phdr_get_p_filesz(class, phdr);
phdr += elf_size_of_phdr(class);
}
-   if (dump_conf == RPROC_COREDUMP_DEFAULT) {
+   if (dump_conf == RPROC_COREDUMP_ENABLED) {
dev_coredumpv(>dev, data, data_size, GFP_KERNEL);
return;
}
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..7e58453 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -33,9 +33,9 @@ static struct dentry *rproc_dbg;
  * enum rproc_coredump_mechanism
  */
 static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
[RPROC_COREDUMP_DISABLED]   = "disabled",
+   [RPROC_COREDUMP_ENABLED]= "enabled",
+   [RPROC_COREDUMP_INLINE] = "inline",
 };
 
 /* Expose the current coredump configuration via debugfs */
@@ -54,20 +54,19 @@ static ssize_t rproc_coredump_read(struct file *filp, char 
__user *userbuf,
 
 /*
  * By writing to the 'coredump' debugfs entry, we control the behavior of the
- * coredump mechanism dynamically. The default value of this entry is 
"default".
+ * coredump mechanism dynamically. The default value of this entry is 
"disabled".
  *
  * The 'coredump' debugfs entry supports these commands:
  *
- * default:This is the default coredump mechanism. When the remoteproc
- * crashes the entire coredump will be copied to a separate buffer
- * and exposed to userspace.
+ * disabled:   By default coredump collection is disabled. Recovery will
+ * proceed without collecting any dump.
+ *
+ * enabled:When the remoteproc crashes the entire coredump will be copied
+ * to a separate buffer and exposed to userspace.
  *
  * inline: The coredump will not be copied to a separate buffer and the
  * recovery process will have to wait until data is read by
  * userspace. But this avoid usage of extra memory.
- *
- * disabled:   This will disable coredump. Recovery will proceed without
- * collecting any dump.
  */
 static ssize_t rproc_coredump_write(struct file *filp,
const char __user *user_buf, size_t count,
@@ -94,12 +93,12 @@ static ssize_t rproc_coredump_write(struct file *filp,
goto out;
}
 
-   if (!strncmp(buf, "disable", count)) {
+   if (!strncmp(buf, "disabled", count)) {
rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (!strncmp(buf, "enabled", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_ENABLED;
} else if (!strncmp(buf, "inline", count)) {
rproc->dump_conf = RPROC_COREDUMP_INLINE;
-   } else if (!strncmp(buf, "default", count)) {
-   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
} else {
dev_err(>dev, "Invalid coredump configuration\n");
err = -EINVAL;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 2fa68bf..3fa3ba6 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc

[PATCH v7 3/3] remoteproc: Add recovery configuration to the sysfs interface

2020-10-02 Thread Rishabh Bhatnagar
Add recovery configuration to the sysfs interface. This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 20 +
 drivers/remoteproc/remoteproc_sysfs.c| 56 
 2 files changed, 76 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 050bd25..066b9b6 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -82,3 +82,23 @@ Description: Remote processor coredump configuration
processor's device memory. Extra buffer will not be used to
copy the dump. Also recovery process will not proceed until
all data is read by usersapce.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
diff --git a/drivers/remoteproc/remoteproc_sysfs.c 
b/drivers/remoteproc/remoteproc_sysfs.c
index 8500271..d1cf7bf 100644
--- a/drivers/remoteproc/remoteproc_sysfs.c
+++ b/drivers/remoteproc/remoteproc_sysfs.c
@@ -10,6 +10,61 @@
 
 #define to_rproc(d) container_of(d, struct rproc, dev)
 
+static ssize_t recovery_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rproc *rproc = to_rproc(dev);
+
+   return sprintf(buf, "%s", rproc->recovery_disabled ? "disabled\n" : 
"enabled\n");
+}
+
+/*
+ * By writing to the 'recovery' sysfs entry, we control the behavior of the
+ * recovery mechanism dynamically. The default value of this entry is 
"enabled".
+ *
+ * The 'recovery' sysfs entry supports these commands:
+ *
+ * enabled:When enabled, the remote processor will be automatically
+ * recovered whenever it crashes. Moreover, if the remote
+ * processor crashes while recovery is disabled, it will
+ * be automatically recovered too as soon as recovery is enabled.
+ *
+ * disabled:   When disabled, a remote processor will remain in a crashed
+ * state if it crashes. This is useful for debugging purposes;
+ * without it, debugging a crash is substantially harder.
+ *
+ * recover:This function will trigger an immediate recovery if the
+ * remote processor is in a crashed state, without changing
+ * or checking the recovery state (enabled/disabled).
+ * This is useful during debugging sessions, when one expects
+ * additional crashes to happen after enabling recovery. In this
+ * case, enabling recovery will make it hard to debug subsequent
+ * crashes, so it's recommended to keep recovery disabled, and
+ * instead use the "recover" command as needed.
+ */
+static ssize_t recovery_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct rproc *rproc = to_rproc(dev);
+
+   if (sysfs_streq(buf, "enabled")) {
+   /* change the flag and begin the recovery process if needed */
+   rproc->recovery_disabled = false;
+   rproc_trigger_recovery(rproc);
+   } else if (sysfs_streq(buf, "disabled")) {
+   rproc->recovery_disabled = true;
+   } else if (sysfs_streq(buf, "recover")) {
+   /* begin the recovery process without changing the flag */
+   rproc_trigger_recovery(rproc);
+   } else {
+   return -EINVAL;
+   }
+
+   return count;
+}
+static DEVICE_ATTR_RW(recovery);
+
 /*
  * A coredump-configuration-to-string lookup table, for exposing a
  * human readable configuration via sysfs. Always keep in sync with
@@ -201,6 +256,7 @@ static DEVICE_ATTR_RO(name);
 
 static struct attribute *rproc_attrs[] = {
_attr_coredump.attr,
+   _attr_recovery.attr,
_attr_firmware.attr,
_attr_state

[PATCH v7 2/3] remoteproc: Add coredump as part of sysfs interface

2020-10-02 Thread Rishabh Bhatnagar
Add coredump as part of the sysfs interface. This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 24 +
 drivers/remoteproc/remoteproc_sysfs.c| 63 
 2 files changed, 87 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..050bd25 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,27 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "disabled"
+   "enabled"
+   "inline"
+
+   "disabled" means no dump will be collected.
+
+   "enabled" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
diff --git a/drivers/remoteproc/remoteproc_sysfs.c 
b/drivers/remoteproc/remoteproc_sysfs.c
index eea514c..8500271 100644
--- a/drivers/remoteproc/remoteproc_sysfs.c
+++ b/drivers/remoteproc/remoteproc_sysfs.c
@@ -10,6 +10,68 @@
 
 #define to_rproc(d) container_of(d, struct rproc, dev)
 
+/*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via sysfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+   [RPROC_COREDUMP_ENABLED]= "enabled",
+   [RPROC_COREDUMP_INLINE] = "inline",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t coredump_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rproc *rproc = to_rproc(dev);
+
+   return sprintf(buf, "%s\n", rproc_coredump_str[rproc->dump_conf]);
+}
+
+/*
+ * By writing to the 'coredump' sysfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' sysfs entry supports these commands:
+ *
+ * disabled:   This is the default coredump mechanism. Recovery will proceed
+ * without collecting any dump.
+ *
+ * default:When the remoteproc crashes the entire coredump will be
+ * copied to a separate buffer and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ */
+static ssize_t coredump_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct rproc *rproc = to_rproc(dev);
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   return -EBUSY;
+   }
+
+   if (sysfs_streq(buf, "disabled")) {
+   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (sysfs_streq(buf, "enabled")) {
+   rproc->dump_conf = RPROC_COREDUMP_ENABLED;
+   } else if (sysfs_streq(buf, "inline")) {
+   rproc->dump_conf = RPROC_COREDUMP_INLINE;
+   } else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   return -EINVAL;
+   }
+
+   return count;
+}
+static DEVICE_ATTR_RW(coredump);
+
 /* Expose the loaded / running firmware name via sysfs */
 static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
  char *buf)
@@ -138,6 +200,7 @@ static ssize_t name_show(struct device *dev, struct 
device_attribute *attr,
 static DEVICE_ATTR_

[PATCH v6 0/3] Move recovery/coredump configuration to sysfs

2020-09-28 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. 'Coredump' and 'Recovery' are critical
interfaces that are required for remoteproc to work on Qualcomm Chipsets. 
Coredump configuration needs to be set to "inline" in debug/test builds
and "disabled" in production builds. Whereas recovery needs to be
"disabled" for debugging purposes and "enabled" on production builds.
This patch series removes the recovery/coredump entries from debugfs
and moves them to sysfs. Also, this disables the coredump collection
by default as this is a requirement for production devices.

Changelog:

v6 -> v5:
- Disable coredump collection by default
- Rename the "default" configuration to "enabled" to avoid confusion

v5 -> v4:
- Fix the cover-letter of tha patch series.

v4 -> v3:
- Remove the feature flag to expose recovery/coredump

v3 -> v2:
- Remove the coredump/recovery entries from debugfs
- Expose recovery/coredump from sysfs under a feature flag

v1 -> v2:
- Correct the contact name in the sysfs documentation.
- Remove the redundant write documentation for coredump/recovery sysfs
- Add a feature flag to make this interface switch configurable.

Rishabh Bhatnagar (3):
  remoteproc: Move coredump configuration to sysfs
  remoteproc: Move recovery configuration to sysfs
  remoteproc: Change default dump configuration to "disabled"

 Documentation/ABI/testing/sysfs-class-remoteproc |  46 +++
 drivers/remoteproc/remoteproc_coredump.c |   6 +-
 drivers/remoteproc/remoteproc_debugfs.c  | 168 ---
 drivers/remoteproc/remoteproc_sysfs.c| 120 
 include/linux/remoteproc.h   |   8 +-
 5 files changed, 173 insertions(+), 175 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 2/3] remoteproc: Move recovery configuration to sysfs

2020-09-28 Thread Rishabh Bhatnagar
Move recovery configuration from debugfs to sysfs.This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 20 ++
 drivers/remoteproc/remoteproc_debugfs.c  | 78 
 drivers/remoteproc/remoteproc_sysfs.c| 56 +
 3 files changed, 76 insertions(+), 78 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index f6c44fa..7368b50 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -82,3 +82,23 @@ Description: Remote processor coredump configuration
all data is read by usersapce.
 
"disabled" means no dump will be collected.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..c505f0e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -84,82 +84,6 @@ static const struct file_operations rproc_name_ops = {
.llseek = generic_file_llseek,
 };
 
-/* expose recovery flag via debugfs */
-static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n";
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
-}
-
-/*
- * By writing to the 'recovery' debugfs entry, we control the behavior of the
- * recovery mechanism dynamically. The default value of this entry is 
"enabled".
- *
- * The 'recovery' debugfs entry supports these commands:
- *
- * enabled:When enabled, the remote processor will be automatically
- * recovered whenever it crashes. Moreover, if the remote
- * processor crashes while recovery is disabled, it will
- * be automatically recovered too as soon as recovery is enabled.
- *
- * disabled:   When disabled, a remote processor will remain in a crashed
- * state if it crashes. This is useful for debugging purposes;
- * without it, debugging a crash is substantially harder.
- *
- * recover:This function will trigger an immediate recovery if the
- * remote processor is in a crashed state, without changing
- * or checking the recovery state (enabled/disabled).
- * This is useful during debugging sessions, when one expects
- * additional crashes to happen after enabling recovery. In this
- * case, enabling recovery will make it hard to debug subsequent
- * crashes, so it's recommended to keep recovery disabled, and
- * instead use the "recover" command as needed.
- */
-static ssize_t
-rproc_recovery_write(struct file *filp, const char __user *user_buf,
-size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[10];
-   int ret;
-
-   if (count < 1 || count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (!strncmp(buf, "enabled", count)) {
-   /* change the flag and begin the recovery process if needed */
-   rproc->recovery_disabled = false;
-   rproc_trigger_recovery(rproc);
-   } else if (!strncmp(buf, "disabled", count)) {
-   rproc->recovery_disabled = true;
-   } else if (!strncmp(buf, "recover", count)) {
-   /* begin the recovery process without changing the flag */
- 

[PATCH v6 1/3] remoteproc: Move coredump configuration to sysfs

2020-09-28 Thread Rishabh Bhatnagar
Move coredump configuration from debugfs to sysfs.This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 24 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 90 
 drivers/remoteproc/remoteproc_sysfs.c| 64 +
 3 files changed, 88 insertions(+), 90 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..f6c44fa 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,27 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "default"
+   "inline"
+   "disabled"
+
+   "default" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
+
+   "disabled" means no dump will be collected.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..732770e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,94 +28,6 @@
 static struct dentry *rproc_dbg;
 
 /*
- * A coredump-configuration-to-string lookup table, for exposing a
- * human readable configuration via debugfs. Always keep in sync with
- * enum rproc_coredump_mechanism
- */
-static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
-   [RPROC_COREDUMP_DISABLED]   = "disabled",
-};
-
-/* Expose the current coredump configuration via debugfs */
-static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[20];
-   int len;
-
-   len = scnprintf(buf, sizeof(buf), "%s\n",
-   rproc_coredump_str[rproc->dump_conf]);
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-/*
- * By writing to the 'coredump' debugfs entry, we control the behavior of the
- * coredump mechanism dynamically. The default value of this entry is 
"default".
- *
- * The 'coredump' debugfs entry supports these commands:
- *
- * default:This is the default coredump mechanism. When the remoteproc
- * crashes the entire coredump will be copied to a separate buffer
- * and exposed to userspace.
- *
- * inline: The coredump will not be copied to a separate buffer and the
- * recovery process will have to wait until data is read by
- * userspace. But this avoid usage of extra memory.
- *
- * disabled:   This will disable coredump. Recovery will proceed without
- * collecting any dump.
- */
-static ssize_t rproc_coredump_write(struct file *filp,
-   const char __user *user_buf, size_t count,
-   loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   int ret, err = 0;
-   char buf[20];
-
-   if (count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (rproc->state == RPROC_CRASHED) {
-   dev_err(>dev, "can't change coredump configuration\n");
-   err = -EBUSY;
-   goto out;
-   }
-
-   if (!strncmp(buf, "disable", count)) {
-   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
-   } else if (!strncmp(buf, "inline&

[PATCH v6 3/3] remoteproc: Change default dump configuration to "disabled"

2020-09-28 Thread Rishabh Bhatnagar
Disable the coredump collection by default as doing so makes sense
for production devices. Also rename the "default" configuration
option to "enabled" to avoid confusion.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 10 ++
 drivers/remoteproc/remoteproc_coredump.c |  6 +++---
 drivers/remoteproc/remoteproc_sysfs.c| 10 +-
 include/linux/remoteproc.h   |  8 
 4 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 7368b50..dec1686 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -67,11 +67,14 @@ Description:Remote processor coredump configuration
Reports the coredump configuration of the remote processor,
which will be one of:
 
-   "default"
-   "inline"
"disabled"
+   "enabled"
+   "inline"
+
+   "disabled" means no dump will be collected. This is the
+   default remoteproc coredump configuration.
 
-   "default" means when the remote processor's coredump is
+   "enabled" means when the remote processor's coredump is
collected it will be copied to a separate buffer and that
buffer is exposed to userspace.
 
@@ -81,7 +84,6 @@ Description:  Remote processor coredump configuration
copy the dump. Also recovery process will not proceed until
all data is read by usersapce.
 
-   "disabled" means no dump will be collected.
 
 What:  /sys/class/remoteproc/.../recovery
 Date:  July 2020
diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index bb15a29..34530dc 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -257,7 +257,7 @@ void rproc_coredump(struct rproc *rproc)
 * directly read from device memory.
 */
data_size += elf_size_of_phdr(class);
-   if (dump_conf == RPROC_COREDUMP_DEFAULT)
+   if (dump_conf == RPROC_COREDUMP_ENABLED)
data_size += segment->size;
 
phnum++;
@@ -297,14 +297,14 @@ void rproc_coredump(struct rproc *rproc)
elf_phdr_set_p_flags(class, phdr, PF_R | PF_W | PF_X);
elf_phdr_set_p_align(class, phdr, 0);
 
-   if (dump_conf == RPROC_COREDUMP_DEFAULT)
+   if (dump_conf == RPROC_COREDUMP_ENABLED)
rproc_copy_segment(rproc, data + offset, segment, 0,
   segment->size);
 
offset += elf_phdr_get_p_filesz(class, phdr);
phdr += elf_size_of_phdr(class);
}
-   if (dump_conf == RPROC_COREDUMP_DEFAULT) {
+   if (dump_conf == RPROC_COREDUMP_ENABLED) {
dev_coredumpv(>dev, data, data_size, GFP_KERNEL);
return;
}
diff --git a/drivers/remoteproc/remoteproc_sysfs.c 
b/drivers/remoteproc/remoteproc_sysfs.c
index e60a014..eb98ed2 100644
--- a/drivers/remoteproc/remoteproc_sysfs.c
+++ b/drivers/remoteproc/remoteproc_sysfs.c
@@ -68,12 +68,12 @@ static DEVICE_ATTR_RW(recovery);
 /*
  * A coredump-configuration-to-string lookup table, for exposing a
  * human readable configuration via sysfs. Always keep in sync with
- * enum rproc_coredump_mechanism
+ * enum rproc_dump_mechanism
  */
 static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
[RPROC_COREDUMP_DISABLED]   = "disabled",
+   [RPROC_COREDUMP_ENABLED]= "enabled",
+   [RPROC_COREDUMP_INLINE] = "inline",
 };
 
 /* Expose the current coredump configuration via debugfs */
@@ -115,10 +115,10 @@ static ssize_t coredump_store(struct device *dev,
 
if (sysfs_streq(buf, "disabled")) {
rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (sysfs_streq(buf, "enabled")) {
+   rproc->dump_conf = RPROC_COREDUMP_ENABLED;
} else if (sysfs_streq(buf, "inline")) {
rproc->dump_conf = RPROC_COREDUMP_INLINE;
-   } else if (sysfs_streq(buf, "default")) {
-   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
} else {
dev_err(>dev, "Invalid coredump configuration\n");
return -EINVAL;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 2fa

[PATCH v5 0/2] Move recovery/coredump configuration to sysfs

2020-09-18 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. This patch series removes the recovery/coredump
entries from debugfs and moves them to sysfs. 
'Coredump' and 'Recovery' are critical interfaces that are required
for remoteproc to work on Qualcomm Chipsets. Coredump configuration
needs to be set to "inline" in debug/test build and "disabled" in
production builds. Whereas recovery needs to be "disabled" for
debugging purposes and "enabled" on production builds.

Changelog:

v5 -> v4:
- Fix the cover-letter of tha patch series.

v4 -> v3:
- Remove the feature flag to expose recovery/coredump

v3 -> v2:
- Remove the coredump/recovery entries from debugfs
- Expose recovery/coredump from sysfs under a feature flag

v1 -> v2:
- Correct the contact name in the sysfs documentation.
- Remove the redundant write documentation for coredump/recovery sysfs
- Add a feature flag to make this interface switch configurable.

Rishabh Bhatnagar (2):
  remoteproc: Move coredump configuration to sysfs
  remoteproc: Move recovery configuration to sysfs

 Documentation/ABI/testing/sysfs-class-remoteproc |  44 ++
 drivers/remoteproc/remoteproc_debugfs.c  | 168 ---
 drivers/remoteproc/remoteproc_sysfs.c| 120 
 3 files changed, 164 insertions(+), 168 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v5 1/2] remoteproc: Move coredump configuration to sysfs

2020-09-18 Thread Rishabh Bhatnagar
Move coredump configuration from debugfs to sysfs.This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 24 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 90 
 drivers/remoteproc/remoteproc_sysfs.c| 64 +
 3 files changed, 88 insertions(+), 90 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..f6c44fa 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,27 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "default"
+   "inline"
+   "disabled"
+
+   "default" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
+
+   "disabled" means no dump will be collected.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..732770e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,94 +28,6 @@
 static struct dentry *rproc_dbg;
 
 /*
- * A coredump-configuration-to-string lookup table, for exposing a
- * human readable configuration via debugfs. Always keep in sync with
- * enum rproc_coredump_mechanism
- */
-static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
-   [RPROC_COREDUMP_DISABLED]   = "disabled",
-};
-
-/* Expose the current coredump configuration via debugfs */
-static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[20];
-   int len;
-
-   len = scnprintf(buf, sizeof(buf), "%s\n",
-   rproc_coredump_str[rproc->dump_conf]);
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-/*
- * By writing to the 'coredump' debugfs entry, we control the behavior of the
- * coredump mechanism dynamically. The default value of this entry is 
"default".
- *
- * The 'coredump' debugfs entry supports these commands:
- *
- * default:This is the default coredump mechanism. When the remoteproc
- * crashes the entire coredump will be copied to a separate buffer
- * and exposed to userspace.
- *
- * inline: The coredump will not be copied to a separate buffer and the
- * recovery process will have to wait until data is read by
- * userspace. But this avoid usage of extra memory.
- *
- * disabled:   This will disable coredump. Recovery will proceed without
- * collecting any dump.
- */
-static ssize_t rproc_coredump_write(struct file *filp,
-   const char __user *user_buf, size_t count,
-   loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   int ret, err = 0;
-   char buf[20];
-
-   if (count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (rproc->state == RPROC_CRASHED) {
-   dev_err(>dev, "can't change coredump configuration\n");
-   err = -EBUSY;
-   goto out;
-   }
-
-   if (!strncmp(buf, "disable", count)) {
-   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
-   } else if (!strncmp(buf, "inline&

[PATCH v5 2/2] remoteproc: Move recovery configuration to sysfs

2020-09-18 Thread Rishabh Bhatnagar
Move recovery configuration from debugfs to sysfs.This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 20 ++
 drivers/remoteproc/remoteproc_debugfs.c  | 78 
 drivers/remoteproc/remoteproc_sysfs.c| 56 +
 3 files changed, 76 insertions(+), 78 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index f6c44fa..7368b50 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -82,3 +82,23 @@ Description: Remote processor coredump configuration
all data is read by usersapce.
 
"disabled" means no dump will be collected.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..c505f0e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -84,82 +84,6 @@ static const struct file_operations rproc_name_ops = {
.llseek = generic_file_llseek,
 };
 
-/* expose recovery flag via debugfs */
-static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n";
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
-}
-
-/*
- * By writing to the 'recovery' debugfs entry, we control the behavior of the
- * recovery mechanism dynamically. The default value of this entry is 
"enabled".
- *
- * The 'recovery' debugfs entry supports these commands:
- *
- * enabled:When enabled, the remote processor will be automatically
- * recovered whenever it crashes. Moreover, if the remote
- * processor crashes while recovery is disabled, it will
- * be automatically recovered too as soon as recovery is enabled.
- *
- * disabled:   When disabled, a remote processor will remain in a crashed
- * state if it crashes. This is useful for debugging purposes;
- * without it, debugging a crash is substantially harder.
- *
- * recover:This function will trigger an immediate recovery if the
- * remote processor is in a crashed state, without changing
- * or checking the recovery state (enabled/disabled).
- * This is useful during debugging sessions, when one expects
- * additional crashes to happen after enabling recovery. In this
- * case, enabling recovery will make it hard to debug subsequent
- * crashes, so it's recommended to keep recovery disabled, and
- * instead use the "recover" command as needed.
- */
-static ssize_t
-rproc_recovery_write(struct file *filp, const char __user *user_buf,
-size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[10];
-   int ret;
-
-   if (count < 1 || count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (!strncmp(buf, "enabled", count)) {
-   /* change the flag and begin the recovery process if needed */
-   rproc->recovery_disabled = false;
-   rproc_trigger_recovery(rproc);
-   } else if (!strncmp(buf, "disabled", count)) {
-   rproc->recovery_disabled = true;
-   } else if (!strncmp(buf, "recover", count)) {
-   /* begin the recovery process without changing the flag */
- 

[PATCH v4 0/3] Move recovery/coredump configuration to sysfs

2020-09-17 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. This patch series removes the recovery/coredump
entries from debugfs and moves them to sysfs. 
'Coredump' and 'Recovery' are critical interfaces that are required
for remoteproc to work on Qualcomm Chipsets. Coredump configuration
needs to be set to "inline" in debug/test build and "disabled" in
production builds. Whereas recovery needs to be "disabled" for
debugging purposes and "enabled" on production builds.

Changelog:

v4 -> v3:
- Remove the feature flag to expose recovery/coredump

v3 -> v2:
- Remove the coredump/recovery entries from debugfs
- Expose recovery/coredump from sysfs under a feature flag

v1 -> v2:
- Correct the contact name in the sysfs documentation.
- Remove the redundant write documentation for coredump/recovery sysfs
- Add a feature flag to make this interface switch configurable.

Rishabh Bhatnagar (3):
  remoteproc: Expose remoteproc configuration through sysfs
  remoteproc: Add coredump configuration to sysfs
  remoteproc: Add recovery configuration to sysfs

 Documentation/ABI/testing/sysfs-class-remoteproc |  44 
 drivers/remoteproc/Kconfig   |  12 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  10 +-
 drivers/remoteproc/remoteproc_sysfs.c| 126 +++
 4 files changed, 190 insertions(+), 2 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v4 2/2] remoteproc: Move recovery configuration to sysfs

2020-09-17 Thread Rishabh Bhatnagar
Move recovery configuration from debugfs to sysfs. This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 20 ++
 drivers/remoteproc/remoteproc_debugfs.c  | 78 
 drivers/remoteproc/remoteproc_sysfs.c| 56 +
 3 files changed, 76 insertions(+), 78 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index f6c44fa..7368b50 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -82,3 +82,23 @@ Description: Remote processor coredump configuration
all data is read by usersapce.
 
"disabled" means no dump will be collected.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..c505f0e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -84,82 +84,6 @@ static const struct file_operations rproc_name_ops = {
.llseek = generic_file_llseek,
 };
 
-/* expose recovery flag via debugfs */
-static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n";
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
-}
-
-/*
- * By writing to the 'recovery' debugfs entry, we control the behavior of the
- * recovery mechanism dynamically. The default value of this entry is 
"enabled".
- *
- * The 'recovery' debugfs entry supports these commands:
- *
- * enabled:When enabled, the remote processor will be automatically
- * recovered whenever it crashes. Moreover, if the remote
- * processor crashes while recovery is disabled, it will
- * be automatically recovered too as soon as recovery is enabled.
- *
- * disabled:   When disabled, a remote processor will remain in a crashed
- * state if it crashes. This is useful for debugging purposes;
- * without it, debugging a crash is substantially harder.
- *
- * recover:This function will trigger an immediate recovery if the
- * remote processor is in a crashed state, without changing
- * or checking the recovery state (enabled/disabled).
- * This is useful during debugging sessions, when one expects
- * additional crashes to happen after enabling recovery. In this
- * case, enabling recovery will make it hard to debug subsequent
- * crashes, so it's recommended to keep recovery disabled, and
- * instead use the "recover" command as needed.
- */
-static ssize_t
-rproc_recovery_write(struct file *filp, const char __user *user_buf,
-size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[10];
-   int ret;
-
-   if (count < 1 || count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (!strncmp(buf, "enabled", count)) {
-   /* change the flag and begin the recovery process if needed */
-   rproc->recovery_disabled = false;
-   rproc_trigger_recovery(rproc);
-   } else if (!strncmp(buf, "disabled", count)) {
-   rproc->recovery_disabled = true;
-   } else if (!strncmp(buf, "recover", count)) {
-   /* begin the recovery process without changing the flag */
- 

[PATCH v4 1/2] remoteproc: Move coredump configuration to sysfs

2020-09-17 Thread Rishabh Bhatnagar
Move coredump configuration from debugfs to sysfs. This will
allow usage of this configuration feature in production
devices where access to debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 24 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 90 
 drivers/remoteproc/remoteproc_sysfs.c| 64 +
 3 files changed, 88 insertions(+), 90 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..f6c44fa 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,27 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "default"
+   "inline"
+   "disabled"
+
+   "default" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
+
+   "disabled" means no dump will be collected.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..732770e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,94 +28,6 @@
 static struct dentry *rproc_dbg;
 
 /*
- * A coredump-configuration-to-string lookup table, for exposing a
- * human readable configuration via debugfs. Always keep in sync with
- * enum rproc_coredump_mechanism
- */
-static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
-   [RPROC_COREDUMP_DISABLED]   = "disabled",
-};
-
-/* Expose the current coredump configuration via debugfs */
-static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[20];
-   int len;
-
-   len = scnprintf(buf, sizeof(buf), "%s\n",
-   rproc_coredump_str[rproc->dump_conf]);
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-/*
- * By writing to the 'coredump' debugfs entry, we control the behavior of the
- * coredump mechanism dynamically. The default value of this entry is 
"default".
- *
- * The 'coredump' debugfs entry supports these commands:
- *
- * default:This is the default coredump mechanism. When the remoteproc
- * crashes the entire coredump will be copied to a separate buffer
- * and exposed to userspace.
- *
- * inline: The coredump will not be copied to a separate buffer and the
- * recovery process will have to wait until data is read by
- * userspace. But this avoid usage of extra memory.
- *
- * disabled:   This will disable coredump. Recovery will proceed without
- * collecting any dump.
- */
-static ssize_t rproc_coredump_write(struct file *filp,
-   const char __user *user_buf, size_t count,
-   loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   int ret, err = 0;
-   char buf[20];
-
-   if (count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (rproc->state == RPROC_CRASHED) {
-   dev_err(>dev, "can't change coredump configuration\n");
-   err = -EBUSY;
-   goto out;
-   }
-
-   if (!strncmp(buf, "disable", count)) {
-   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
-   } else if (!strncmp(buf, "inline&

[PATCH v3 1/3] remoteproc: Expose remoteproc configuration through sysfs

2020-09-03 Thread Rishabh Bhatnagar
Add a feature flag to expose some of the remoteproc configuration
through sysfs. This feature is helpful in systems where debugfs is
not available/mounted. Currently the recovery and coredump
configuration is exposed through sysfs rather than debugfs when
this feature is selected.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/Kconfig | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index c6659dfe..98d52cbe 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -275,6 +275,17 @@ config TI_K3_DSP_REMOTEPROC
  It's safe to say N here if you're not interested in utilizing
  the DSP slave processors.
 
+config RPROC_SYSFS_CONFIGURATION_SUPPORT
+   bool "Expose remoteproc configuration sysfs entries"
+   default y
+   help
+ Say y here to expose recovery and coredump configuration sysfs
+ entries. This is helpful in operating systems where debugfs is
+ not available/mounted.
+
+ It's safe to say N here if you are not interested in accessing
+ recovery and coredump configuration through sysfs.
+
 endif # REMOTEPROC
 
 endmenu
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v3 2/3] remoteproc: Add coredump configuration to sysfs

2020-09-03 Thread Rishabh Bhatnagar
Expose coredump configuration in sysfs under a feature
flag. This is useful for systems where access to
debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 24 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 90 
 drivers/remoteproc/remoteproc_sysfs.c| 68 ++
 3 files changed, 92 insertions(+), 90 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..f6c44fa 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,27 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "default"
+   "inline"
+   "disabled"
+
+   "default" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
+
+   "disabled" means no dump will be collected.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..732770e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,94 +28,6 @@
 static struct dentry *rproc_dbg;
 
 /*
- * A coredump-configuration-to-string lookup table, for exposing a
- * human readable configuration via debugfs. Always keep in sync with
- * enum rproc_coredump_mechanism
- */
-static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
-   [RPROC_COREDUMP_DISABLED]   = "disabled",
-};
-
-/* Expose the current coredump configuration via debugfs */
-static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[20];
-   int len;
-
-   len = scnprintf(buf, sizeof(buf), "%s\n",
-   rproc_coredump_str[rproc->dump_conf]);
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-/*
- * By writing to the 'coredump' debugfs entry, we control the behavior of the
- * coredump mechanism dynamically. The default value of this entry is 
"default".
- *
- * The 'coredump' debugfs entry supports these commands:
- *
- * default:This is the default coredump mechanism. When the remoteproc
- * crashes the entire coredump will be copied to a separate buffer
- * and exposed to userspace.
- *
- * inline: The coredump will not be copied to a separate buffer and the
- * recovery process will have to wait until data is read by
- * userspace. But this avoid usage of extra memory.
- *
- * disabled:   This will disable coredump. Recovery will proceed without
- * collecting any dump.
- */
-static ssize_t rproc_coredump_write(struct file *filp,
-   const char __user *user_buf, size_t count,
-   loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   int ret, err = 0;
-   char buf[20];
-
-   if (count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (rproc->state == RPROC_CRASHED) {
-   dev_err(>dev, "can't change coredump configuration\n");
-   err = -EBUSY;
-   goto out;
-   }
-
-   if (!strncmp(buf, "disable", count)) {
-   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
-   } else if (!strncmp(buf, "inline", count)) {
-   rproc-&g

[PATCH v3 3/3] remoteproc: Add recovery configuration to sysfs

2020-09-03 Thread Rishabh Bhatnagar
Expose recovery configuration in sysfs under a feature
flag. This is useful for systems where access to
debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 20 ++
 drivers/remoteproc/remoteproc_debugfs.c  | 78 
 drivers/remoteproc/remoteproc_sysfs.c| 58 ++
 3 files changed, 78 insertions(+), 78 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index f6c44fa..7368b50 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -82,3 +82,23 @@ Description: Remote processor coredump configuration
all data is read by usersapce.
 
"disabled" means no dump will be collected.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..c505f0e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -84,82 +84,6 @@ static const struct file_operations rproc_name_ops = {
.llseek = generic_file_llseek,
 };
 
-/* expose recovery flag via debugfs */
-static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n";
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
-}
-
-/*
- * By writing to the 'recovery' debugfs entry, we control the behavior of the
- * recovery mechanism dynamically. The default value of this entry is 
"enabled".
- *
- * The 'recovery' debugfs entry supports these commands:
- *
- * enabled:When enabled, the remote processor will be automatically
- * recovered whenever it crashes. Moreover, if the remote
- * processor crashes while recovery is disabled, it will
- * be automatically recovered too as soon as recovery is enabled.
- *
- * disabled:   When disabled, a remote processor will remain in a crashed
- * state if it crashes. This is useful for debugging purposes;
- * without it, debugging a crash is substantially harder.
- *
- * recover:This function will trigger an immediate recovery if the
- * remote processor is in a crashed state, without changing
- * or checking the recovery state (enabled/disabled).
- * This is useful during debugging sessions, when one expects
- * additional crashes to happen after enabling recovery. In this
- * case, enabling recovery will make it hard to debug subsequent
- * crashes, so it's recommended to keep recovery disabled, and
- * instead use the "recover" command as needed.
- */
-static ssize_t
-rproc_recovery_write(struct file *filp, const char __user *user_buf,
-size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[10];
-   int ret;
-
-   if (count < 1 || count > sizeof(buf))
-   return -EINVAL;
-
-   ret = copy_from_user(buf, user_buf, count);
-   if (ret)
-   return -EFAULT;
-
-   /* remove end of line */
-   if (buf[count - 1] == '\n')
-   buf[count - 1] = '\0';
-
-   if (!strncmp(buf, "enabled", count)) {
-   /* change the flag and begin the recovery process if needed */
-   rproc->recovery_disabled = false;
-   rproc_trigger_recovery(rproc);
-   } else if (!strncmp(buf, "disabled", count)) {
-   rproc->recovery_disabled = true;
-   } else if (!strncmp(buf, "recover", count)) {
-   /* begin the recovery process without changing the flag */
-   rproc_trigger_recovery(rproc);
- 

[PATCH v3 0/3] Expose recovery/coredump configuration from sysfs

2020-09-03 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. This patch series removes the recovery/coredump
entries from debugfs and adds a configurable option to expose these
interfaces from sysfs. 
'Coredump' and 'Recovery' are critical interfaces that are required
for remoteproc to work on Qualcomm Chipsets. Coredump configuration
needs to be set to "inline" in debug/test build and "disabled" in
production builds. Whereas recovery needs to be "disabled" for
debugging purposes and "enabled" on production builds.

Changelog:

v3 -> v2:
- Remove the coredump/recovery entries from debugfs
- Expose recovery/coredump from sysfs under a feature flag

v1 -> v2:
- Correct the contact name in the sysfs documentation.
- Remove the redundant write documentation for coredump/recovery sysfs
- Add a feature flag to make this interface switch configurable.

Rishabh Bhatnagar (3):
  remoteproc: Expose remoteproc configuration through sysfs
  remoteproc: Add coredump configuration to sysfs
  remoteproc: Add recovery configuration to sysfs

 Documentation/ABI/testing/sysfs-class-remoteproc |  44 
 drivers/remoteproc/Kconfig   |  12 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  10 +-
 drivers/remoteproc/remoteproc_sysfs.c| 126 +++
 4 files changed, 190 insertions(+), 2 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 2/3] remoteproc: Add coredump configuration to sysfs

2020-08-27 Thread Rishabh Bhatnagar
Expose coredump configuration in sysfs under a feature
flag. This is useful for systems where access to
debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 24 +
 drivers/remoteproc/remoteproc_debugfs.c  |  4 ++
 drivers/remoteproc/remoteproc_sysfs.c| 68 
 3 files changed, 96 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..f6c44fa 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,27 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "default"
+   "inline"
+   "disabled"
+
+   "default" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
+
+   "disabled" means no dump will be collected.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..48dfd0a 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -27,6 +27,7 @@
 /* remoteproc debugfs parent dir */
 static struct dentry *rproc_dbg;
 
+#if (!IS_ENABLED(CONFIG_RPROC_SYSFS_CONFIGURATION_SUPPORT))
 /*
  * A coredump-configuration-to-string lookup table, for exposing a
  * human readable configuration via debugfs. Always keep in sync with
@@ -114,6 +115,7 @@ static const struct file_operations rproc_coredump_fops = {
.open = simple_open,
.llseek = generic_file_llseek,
 };
+#endif
 
 /*
  * Some remote processors may support dumping trace logs into a shared
@@ -425,8 +427,10 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+#if (!IS_ENABLED(CONFIG_RPROC_SYSFS_CONFIGURATION_SUPPORT))
debugfs_create_file("coredump", 0600, rproc->dbg_dir,
rproc, _coredump_fops);
+#endif
 }
 
 void __init rproc_init_debugfs(void)
diff --git a/drivers/remoteproc/remoteproc_sysfs.c 
b/drivers/remoteproc/remoteproc_sysfs.c
index eea514c..89b301a 100644
--- a/drivers/remoteproc/remoteproc_sysfs.c
+++ b/drivers/remoteproc/remoteproc_sysfs.c
@@ -10,6 +10,71 @@
 
 #define to_rproc(d) container_of(d, struct rproc, dev)
 
+#if IS_ENABLED(CONFIG_RPROC_SYSFS_CONFIGURATION_SUPPORT)
+/*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via sysfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DEFAULT]= "default",
+   [RPROC_COREDUMP_INLINE] = "inline",
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t coredump_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rproc *rproc = to_rproc(dev);
+
+   return sprintf(buf, "%s\n", rproc_coredump_str[rproc->dump_conf]);
+}
+
+/*
+ * By writing to the 'coredump' sysfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' sysfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memo

[PATCH v2 1/3] remoteproc: Expose remoteproc configuration through sysfs

2020-08-27 Thread Rishabh Bhatnagar
Add a feature flag to expose some of the remoteproc configuration
through sysfs. This feature is helpful in systems where debugfs is
not available/mounted. Currently the recovery and coredump
configuration is exposed through sysfs rather than debugfs when
this feature is selected.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/Kconfig | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index c6659dfe..8aecf70 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -275,6 +275,18 @@ config TI_K3_DSP_REMOTEPROC
  It's safe to say N here if you're not interested in utilizing
  the DSP slave processors.
 
+config RPROC_SYSFS_CONFIGURATION_SUPPORT
+   bool "Expose remoteproc configuration sysfs entries"
+   default n
+   help
+ Say y here to expose recovery and coredump configuration sysfs
+ entries. This will remove the corresponding entries from debugfs
+ and expose it through sysfs. This is helpful in operating systems
+ where debugfs is not available.
+
+ It's safe to say N here if you are not interested in accessing
+ recovery and coredump configuration through sysfs.
+
 endif # REMOTEPROC
 
 endmenu
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 0/3] Expose recovery/coredump configuration from sysfs

2020-08-27 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. This patch series adds a configurable option
to move the recovery/coredump interfaces to sysfs. If the feature
flag is selected it would move these interfaces to sysfs and remove
the equivalent debugfs interface. 'Coredump' and 'Recovery' are critical
interfaces that are required for remoteproc to work on Qualcomm Chipsets.
Coredump configuration needs to be set to "inline" in debug/test build
and "disabled" in production builds. Whereas recovery needs to be
"disabled" for debugging purposes and "enabled" on production builds.

Changelog:

v1 -> v2:
- Correct the contact name in the sysfs documentation.
- Remove the redundant write documentation for coredump/recovery sysfs
- Add a feature flag to make this interface switch configurable.

Rishabh Bhatnagar (3):
  remoteproc: Expose remoteproc configuration through sysfs
  remoteproc: Add coredump configuration to sysfs
  remoteproc: Add recovery configuration to sysfs

 Documentation/ABI/testing/sysfs-class-remoteproc |  44 
 drivers/remoteproc/Kconfig   |  12 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  10 +-
 drivers/remoteproc/remoteproc_sysfs.c| 126 +++
 4 files changed, 190 insertions(+), 2 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 3/3] remoteproc: Add recovery configuration to sysfs

2020-08-27 Thread Rishabh Bhatnagar
Expose recovery configuration in sysfs under a feature
flag. This is useful for systems where access to
debugfs might be limited.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 20 
 drivers/remoteproc/remoteproc_debugfs.c  |  6 ++-
 drivers/remoteproc/remoteproc_sysfs.c| 58 
 3 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index f6c44fa..7368b50 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -82,3 +82,23 @@ Description: Remote processor coredump configuration
all data is read by usersapce.
 
"disabled" means no dump will be collected.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Bjorn Andersson , Ohad Ben-Cohen 

+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 48dfd0a..415a9ff 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -174,6 +174,7 @@ static const struct file_operations rproc_name_ops = {
.llseek = generic_file_llseek,
 };
 
+#if (!IS_ENABLED(CONFIG_RPROC_SYSFS_CONFIGURATION_SUPPORT))
 /* expose recovery flag via debugfs */
 static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf,
   size_t count, loff_t *ppos)
@@ -249,6 +250,7 @@ static const struct file_operations rproc_recovery_ops = {
.open = simple_open,
.llseek = generic_file_llseek,
 };
+#endif
 
 /* expose the crash trigger via debugfs */
 static ssize_t
@@ -419,8 +421,6 @@ void rproc_create_debug_dir(struct rproc *rproc)
 
debugfs_create_file("name", 0400, rproc->dbg_dir,
rproc, _name_ops);
-   debugfs_create_file("recovery", 0600, rproc->dbg_dir,
-   rproc, _recovery_ops);
debugfs_create_file("crash", 0200, rproc->dbg_dir,
rproc, _crash_ops);
debugfs_create_file("resource_table", 0400, rproc->dbg_dir,
@@ -430,6 +430,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
 #if (!IS_ENABLED(CONFIG_RPROC_SYSFS_CONFIGURATION_SUPPORT))
debugfs_create_file("coredump", 0600, rproc->dbg_dir,
rproc, _coredump_fops);
+   debugfs_create_file("recovery", 0600, rproc->dbg_dir,
+   rproc, _recovery_ops);
 #endif
 }
 
diff --git a/drivers/remoteproc/remoteproc_sysfs.c 
b/drivers/remoteproc/remoteproc_sysfs.c
index 89b301a..45cae4f 100644
--- a/drivers/remoteproc/remoteproc_sysfs.c
+++ b/drivers/remoteproc/remoteproc_sysfs.c
@@ -11,6 +11,63 @@
 #define to_rproc(d) container_of(d, struct rproc, dev)
 
 #if IS_ENABLED(CONFIG_RPROC_SYSFS_CONFIGURATION_SUPPORT)
+
+/* expose recovery flag via sysfs */
+static ssize_t recovery_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rproc *rproc = to_rproc(dev);
+
+   return sprintf(buf, "%s", rproc->recovery_disabled ? "disabled\n" : 
"enabled\n");
+}
+
+/*
+ * By writing to the 'recovery' sysfs entry, we control the behavior of the
+ * recovery mechanism dynamically. The default value of this entry is 
"enabled".
+ *
+ * The 'recovery' sysfs entry supports these commands:
+ *
+ * enabled:When enabled, the remote processor will be automatically
+ * recovered whenever it crashes. Moreover, if the remote
+ * processor crashes while recovery is disabled, it will
+ * be automatically recovered too as soon as recovery is enabled.
+ *
+ * disabled:   When disabled, a remote processor will remain in a crashed
+ * state if it crashes. This is useful for debugging purposes;
+ * without it, debugging a crash is substantially harder.
+ *
+ * recover:This function will tri

[PATCH 2/2] remoteproc: Move recovery debugfs entry to sysfs

2020-07-28 Thread Rishabh Bhatnagar
Expose recovery mechanism through sysfs rather than exposing through
debugfs. Some operating systems may limit access to debugfs through
access policies. This restricts user access to recovery mechanism,
hence move it to sysfs.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 36 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 77 
 drivers/remoteproc/remoteproc_sysfs.c| 57 ++
 3 files changed, 93 insertions(+), 77 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 812582a..16c5267 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -98,3 +98,39 @@ Description: Remote processor coredump configuration
 
Writing "disable" will disable the coredump collection for
that remoteproc.
+
+What:  /sys/class/remoteproc/.../recovery
+Date:  July 2020
+Contact:   Rishabh Bhatnagar 
+Description:   Remote processor recovery mechanism
+
+   Reports the recovery mechanism of the remote processor,
+   which will be one of:
+
+   "enabled"
+   "disabled"
+
+   "enabled" means, the remote processor will be automatically
+   recovered whenever it crashes. Moreover, if the remote
+   processor crashes while recovery is disabled, it will
+   be automatically recovered too as soon as recovery is enabled.
+
+   "disabled" means, a remote processor will remain in a crashed
+   state if it crashes. This is useful for debugging purposes;
+   without it, debugging a crash is substantially harder.
+
+   Writing this file controls the recovery mechanism of the
+   remote processor. The following options can be written:
+
+   "enabled"
+   "disabled"
+   "recover"
+
+   Writing "enabled" will enable recovery and recover the remote
+   processor if its crashed.
+
+   Writing "disabled" will disable recovery and if crashed the
+   remote processor will remain in crashed state.
+
+   Writing "recover" will trigger an immediate recovery if the
+   remote processor is in crashed state.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..71194a0 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -84,81 +84,6 @@ static const struct file_operations rproc_name_ops = {
.llseek = generic_file_llseek,
 };
 
-/* expose recovery flag via debugfs */
-static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n";
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
-}
-
-/*
- * By writing to the 'recovery' debugfs entry, we control the behavior of the
- * recovery mechanism dynamically. The default value of this entry is 
"enabled".
- *
- * The 'recovery' debugfs entry supports these commands:
- *
- * enabled:When enabled, the remote processor will be automatically
- * recovered whenever it crashes. Moreover, if the remote
- * processor crashes while recovery is disabled, it will
- * be automatically recovered too as soon as recovery is enabled.
- *
- * disabled:   When disabled, a remote processor will remain in a crashed
- * state if it crashes. This is useful for debugging purposes;
- * without it, debugging a crash is substantially harder.
- *
- * recover:This function will trigger an immediate recovery if the
- * remote processor is in a crashed state, without changing
- * or checking the recovery state (enabled/disabled).
- * This is useful during debugging sessions, when one expects
- * additional crashes to happen after enabling recovery. In this
- * case, enabling recovery will make it hard to debug subsequent
- * crashes, so it's recommended to keep recovery disabled, and
- * instead use the "recover" command as needed.
- */
-static ssize_t
-rproc_recovery_write(struct file *filp, const char __user *user_buf,
-size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[10];
-   int ret;
-
-   if (count < 1 || count > sizeof(buf))
-   return -EI

[PATCH 1/2] remoteproc: Move coredump entry from debugfs to sysfs.

2020-07-28 Thread Rishabh Bhatnagar
Expose coredump configuration from sysfs instead of debugfs.
In some operating systems access to debugfs might be limited.
This restricts user from selecting the coredump configuration
at all, hence move this interface to sysfs.

Signed-off-by: Rishabh Bhatnagar 
---
 Documentation/ABI/testing/sysfs-class-remoteproc | 40 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 90 
 drivers/remoteproc/remoteproc_sysfs.c| 64 +
 3 files changed, 104 insertions(+), 90 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-remoteproc 
b/Documentation/ABI/testing/sysfs-class-remoteproc
index 36094fb..812582a 100644
--- a/Documentation/ABI/testing/sysfs-class-remoteproc
+++ b/Documentation/ABI/testing/sysfs-class-remoteproc
@@ -58,3 +58,43 @@ 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.
+
+What:  /sys/class/remoteproc/.../coredump
+Date:  July 2020
+Contact:   Rishabh Bhatnagar 
+Description:   Remote processor coredump configuration
+
+   Reports the coredump configuration of the remote processor,
+   which will be one of:
+
+   "default"
+   "inline"
+   "disabled"
+
+   "default" means when the remote processor's coredump is
+   collected it will be copied to a separate buffer and that
+   buffer is exposed to userspace.
+
+   "inline" means when the remote processor's coredump is
+   collected userspace will directly read from the remote
+   processor's device memory. Extra buffer will not be used to
+   copy the dump. Also recovery process will not proceed until
+   all data is read by usersapce.
+
+   "disabled" means no dump will be collected.
+
+   Writing this file controls the coredump configuration of the
+   remote processor. The following configurations can be written:
+
+   "default"
+   "inline"
+   "disable"
+
+   Writing "default" will change the coredump configuration to
+   default option.
+
+   Writing "inline" will change the coredump configuration to
+   inline.
+
+   Writing "disable" will disable the coredump collection for
+   that remoteproc.
diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 2e3b3e2..732770e 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,94 +28,6 @@
 static struct dentry *rproc_dbg;
 
 /*
- * A coredump-configuration-to-string lookup table, for exposing a
- * human readable configuration via debugfs. Always keep in sync with
- * enum rproc_coredump_mechanism
- */
-static const char * const rproc_coredump_str[] = {
-   [RPROC_COREDUMP_DEFAULT]= "default",
-   [RPROC_COREDUMP_INLINE] = "inline",
-   [RPROC_COREDUMP_DISABLED]   = "disabled",
-};
-
-/* Expose the current coredump configuration via debugfs */
-static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
-  size_t count, loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   char buf[20];
-   int len;
-
-   len = scnprintf(buf, sizeof(buf), "%s\n",
-   rproc_coredump_str[rproc->dump_conf]);
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-/*
- * By writing to the 'coredump' debugfs entry, we control the behavior of the
- * coredump mechanism dynamically. The default value of this entry is 
"default".
- *
- * The 'coredump' debugfs entry supports these commands:
- *
- * default:This is the default coredump mechanism. When the remoteproc
- * crashes the entire coredump will be copied to a separate buffer
- * and exposed to userspace.
- *
- * inline: The coredump will not be copied to a separate buffer and the
- * recovery process will have to wait until data is read by
- * userspace. But this avoid usage of extra memory.
- *
- * disabled:   This will disable coredump. Recovery will proceed without
- * collecting any dump.
- */
-static ssize_t rproc_coredump_write(struct file *filp,
-   const char __user *user_buf, size_t count,
-   loff_t *ppos)
-{
-   struct rproc *rproc = filp->private_data;
-   int ret, err = 0;
-   cha

[PATCH 0/2] Move recovery and coredump interface to sysfs

2020-07-28 Thread Rishabh Bhatnagar
>From Android R onwards Google has restricted access to debugfs in user
and user-debug builds. This restricts access to most of the features
exposed through debugfs. 'Coredump' and 'Recovery' are critical interfaces
that are required for remoteproc to work on Qualcomm Chipsets. Coredump
configuration needs to be set to "inline" in debug/test builds and
"disabled" in production builds. Whereas recovery needs to be "disabled"
for debugging purposes and "enabled" on production builds. Moving these
interfaces to sysfs will allow usage for these interfaces for 
production and debug builds.

Rishabh Bhatnagar (2):
  remoteproc: Move coredump entry from debugfs to sysfs.
  remoteproc: Move recovery debugfs entry to sysfs

 Documentation/ABI/testing/sysfs-class-remoteproc |  76 +++
 drivers/remoteproc/remoteproc_debugfs.c  | 167 ---
 drivers/remoteproc/remoteproc_sysfs.c| 123 +
 3 files changed, 199 insertions(+), 167 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 0/5] Extend coredump functionality

2020-07-16 Thread Rishabh Bhatnagar
This patch series moves the coredump functionality to a separate
file and adds "inline" coredump feature. Inline coredump directly
copies segments from device memory during coredump to userspace.
This avoids extra memory usage at the cost of speed. Recovery is
stalled until all data is read by userspace.
This patchset also includes Sibi Sankar's patch to deal with chunk sizes
lesser than segment size to make inline coredump work for modem.
https://patchwork.kernel.org/patch/11637157/

Changelog:

v8 -> v7:
- Split out the qcom_q6v5_mss refactoring into a new patch
- Remove zero size check in dump_segment function for mss
- Remove segment number being passed as private member for the segment
- Free the memory used by dump state header before signalling completion

v7 -> v6:
- Include Sibi's patch as part of this patchset
- Add a linefeed when displaying coredump conf in debugfs
- Fix a typo in remoteproc.h

v6 -> v5:
- Fix unsigned comaprison with negative bug found on gcc-9.3.0

v5 -> v4:
- Rebase on top of linux-next
- Modify qcom_q6v5_mss driver as a result of rebasing on latest tip.

v4 -> v3:
- Write a helper function to copy segment memory for every dump format
- Change segment dump fn to add offset and size adn covert mss driver

v3 -> v2:
- Move entire coredump functionality to remoteproc_coredump.c
- Modify rproc_coredump to perform dump according to conf. set by userspace
- Move the userspace configuration to debugfs from sysfs.
- Keep the default coredump implementation as is

v2 -> v1:
- Introduce new file for coredump.
- Add userspace sysfs configuration for dump type.

Rishabh Bhatnagar (4):
  remoteproc: Move coredump functionality to a new file
  remoteproc: Add size and offset arguments to segment dump function
  remoteproc: Add inline coredump functionality
  remoteproc: Add coredump debugfs entry

Sibi Sankar (1):
  remoteproc: qcom_q6v5_mss: Replace mask based tracking with size

 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/qcom_q6v5_mss.c   |  25 ++-
 drivers/remoteproc/remoteproc_core.c | 191 --
 drivers/remoteproc/remoteproc_coredump.c | 325 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  90 +
 drivers/remoteproc/remoteproc_internal.h |   4 +
 include/linux/remoteproc.h   |  21 +-
 7 files changed, 451 insertions(+), 206 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 1/5] remoteproc: Move coredump functionality to a new file

2020-07-16 Thread Rishabh Bhatnagar
Move all coredump functionality to an individual file. This is
being done so that the current functionality can be extended
in future patchsets.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
Reviewed-by: Sibi Sankar 
Tested-by: Sibi Sankar 
---
 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 -
 drivers/remoteproc/remoteproc_coredump.c | 204 +++
 drivers/remoteproc/remoteproc_internal.h |   4 +
 4 files changed, 209 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index e8b886e..8702a4e 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REMOTEPROC)   += remoteproc.o
 remoteproc-y   := remoteproc_core.o
+remoteproc-y   += remoteproc_coredump.o
 remoteproc-y   += remoteproc_debugfs.o
 remoteproc-y   += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 9f04c30..57db042 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -26,7 +26,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -41,7 +40,6 @@
 #include 
 
 #include "remoteproc_internal.h"
-#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xULL
 
@@ -1239,19 +1237,6 @@ static int rproc_alloc_registered_carveouts(struct rproc 
*rproc)
return 0;
 }
 
-/**
- * rproc_coredump_cleanup() - clean up dump_segments list
- * @rproc: the remote processor handle
- */
-static void rproc_coredump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, >dump_segments, node) {
-   list_del(>node);
-   kfree(entry);
-   }
-}
 
 /**
  * rproc_resource_cleanup() - clean up and free all acquired resources
@@ -1518,182 +1503,6 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
return 0;
 }
 
-/**
- * rproc_coredump_add_segment() - add segment of device memory to coredump
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- *
- * Add device memory to the list of segments to be included in a coredump for
- * the remoteproc.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_segment);
-
-/**
- * rproc_coredump_add_custom_segment() - add custom coredump segment
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- * @dumpfn:custom dump function called for each segment during coredump
- * @priv:  private data
- *
- * Add device memory to the list of segments to be included in the coredump
- * and associate the segment with the given custom dump function and private
- * data.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_custom_segment(struct rproc *rproc,
- dma_addr_t da, size_t size,
- void (*dumpfn)(struct rproc *rproc,
-struct rproc_dump_segment 
*segment,
-void *dest),
- void *priv)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-   segment->priv = priv;
-   segment->dump = dumpfn;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
-
-/**
- * rproc_coredump_set_elf_info() - set coredump elf information
- * @rproc: handle of a remote processor
- * @class: elf class for coredump elf file
- * @machine:   elf machine for coredump elf file
- *
- * Set elf information which will be used for coredump elf file.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine)
-{
-   if (class != ELFCLASS64 && class != ELFCLASS32)
- 

[PATCH v8 2/5] remoteproc: qcom_q6v5_mss: Replace mask based tracking with size

2020-07-16 Thread Rishabh Bhatnagar
From: Sibi Sankar 

In order to land inline coredump support for mss, the dump_segment
function would need to support granularities less than the segment
size. This is achieved by replacing mask based tracking with size.

Signed-off-by: Sibi Sankar 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_q6v5_mss.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index feb70283b..037cd45 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -181,8 +181,8 @@ struct q6v5 {
bool running;
 
bool dump_mba_loaded;
-   unsigned long dump_segment_mask;
-   unsigned long dump_complete_mask;
+   size_t current_dump_size;
+   size_t total_dump_size;
 
phys_addr_t mba_phys;
void *mba_region;
@@ -1203,7 +1203,6 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
-   unsigned long mask = BIT((unsigned long)segment->priv);
int offset = segment->da - qproc->mpss_reloc;
void *ptr = NULL;
 
@@ -1229,10 +1228,10 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
memset(dest, 0xff, segment->size);
}
 
-   qproc->dump_segment_mask |= mask;
+   qproc->current_dump_size += segment->size;
 
/* Reclaim mba after copying segments */
-   if (qproc->dump_segment_mask == qproc->dump_complete_mask) {
+   if (qproc->current_dump_size == qproc->total_dump_size) {
if (qproc->dump_mba_loaded) {
/* Try to reset ownership back to Q6 */
q6v5_xfer_mem_ownership(qproc, >mpss_perm,
@@ -1274,7 +1273,7 @@ static int q6v5_start(struct rproc *rproc)
"Failed to reclaim mba buffer system may become 
unstable\n");
 
/* Reset Dump Segment Mask */
-   qproc->dump_segment_mask = 0;
+   qproc->current_dump_size = 0;
qproc->running = true;
 
return 0;
@@ -1323,7 +1322,7 @@ static int qcom_q6v5_register_dump_segments(struct rproc 
*rproc,
 
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
-   qproc->dump_complete_mask = 0;
+   qproc->total_dump_size = 0;
 
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = [i];
@@ -1334,11 +1333,11 @@ static int qcom_q6v5_register_dump_segments(struct 
rproc *rproc,
ret = rproc_coredump_add_custom_segment(rproc, phdr->p_paddr,
phdr->p_memsz,
qcom_q6v5_dump_segment,
-   (void *)i);
+   NULL);
if (ret)
break;
 
-   qproc->dump_complete_mask |= BIT(i);
+   qproc->total_dump_size += phdr->p_memsz;
}
 
release_firmware(fw);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 5/5] remoteproc: Add coredump debugfs entry

2020-07-16 Thread Rishabh Bhatnagar
Add coredump debugfs entry to configure the type of dump that will
be collected during recovery. User can select between default or
inline coredump functionality. Also coredump collection can be
disabled through this interface.
This functionality can be configured differently for different
remote processors.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
Tested-by: Sibi Sankar 
Reviewed-by: Sibi Sankar 
---
 drivers/remoteproc/remoteproc_debugfs.c | 90 +
 1 file changed, 90 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..2e3b3e2 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,6 +28,94 @@
 static struct dentry *rproc_dbg;
 
 /*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via debugfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DEFAULT]= "default",
+   [RPROC_COREDUMP_INLINE] = "inline",
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
+  size_t count, loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   char buf[20];
+   int len;
+
+   len = scnprintf(buf, sizeof(buf), "%s\n",
+   rproc_coredump_str[rproc->dump_conf]);
+
+   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+/*
+ * By writing to the 'coredump' debugfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' debugfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ *
+ * disabled:   This will disable coredump. Recovery will proceed without
+ * collecting any dump.
+ */
+static ssize_t rproc_coredump_write(struct file *filp,
+   const char __user *user_buf, size_t count,
+   loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   int ret, err = 0;
+   char buf[20];
+
+   if (count > sizeof(buf))
+   return -EINVAL;
+
+   ret = copy_from_user(buf, user_buf, count);
+   if (ret)
+   return -EFAULT;
+
+   /* remove end of line */
+   if (buf[count - 1] == '\n')
+   buf[count - 1] = '\0';
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   err = -EBUSY;
+   goto out;
+   }
+
+   if (!strncmp(buf, "disable", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (!strncmp(buf, "inline", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_INLINE;
+   } else if (!strncmp(buf, "default", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
+   } else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   err = -EINVAL;
+   }
+out:
+   return err ? err : count;
+}
+
+static const struct file_operations rproc_coredump_fops = {
+   .read = rproc_coredump_read,
+   .write = rproc_coredump_write,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
+/*
  * Some remote processors may support dumping trace logs into a shared
  * memory buffer. We expose this trace buffer using debugfs, so users
  * can easily tell what's going on remotely.
@@ -337,6 +425,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+   debugfs_create_file("coredump", 0600, rproc->dbg_dir,
+   rproc, _coredump_fops);
 }
 
 void __init rproc_init_debugfs(void)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 3/5] remoteproc: Pass size and offset as arguments to segment dump function

2020-07-16 Thread Rishabh Bhatnagar
Change the segment dump API signature to include size and offset
arguments. Refactor the qcom_q6v5_mss driver to use these
arguments while copying the segment. Doing this lays the ground
work for "inline" coredump functionality being added in the next
patch.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_q6v5_mss.c   | 10 +-
 drivers/remoteproc/remoteproc_coredump.c |  5 +++--
 include/linux/remoteproc.h   |  5 +++--
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index 037cd45..6baa3ae 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1199,7 +1199,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
 
 static void qcom_q6v5_dump_segment(struct rproc *rproc,
   struct rproc_dump_segment *segment,
-  void *dest)
+  void *dest, size_t cp_offset, size_t size)
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
@@ -1219,16 +1219,16 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
}
 
if (!ret)
-   ptr = ioremap_wc(qproc->mpss_phys + offset, segment->size);
+   ptr = ioremap_wc(qproc->mpss_phys + offset + cp_offset, size);
 
if (ptr) {
-   memcpy(dest, ptr, segment->size);
+   memcpy(dest, ptr, size);
iounmap(ptr);
} else {
-   memset(dest, 0xff, segment->size);
+   memset(dest, 0xff, size);
}
 
-   qproc->current_dump_size += segment->size;
+   qproc->current_dump_size += size;
 
/* Reclaim mba after copying segments */
if (qproc->current_dump_size == qproc->total_dump_size) {
diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index ded0244..390f563 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -72,7 +72,8 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
  dma_addr_t da, size_t size,
  void (*dumpfn)(struct rproc *rproc,
 struct rproc_dump_segment 
*segment,
-void *dest),
+void *dest, size_t offset,
+size_t size),
  void *priv)
 {
struct rproc_dump_segment *segment;
@@ -183,7 +184,7 @@ void rproc_coredump(struct rproc *rproc)
elf_phdr_set_p_align(class, phdr, 0);
 
if (segment->dump) {
-   segment->dump(rproc, segment, data + offset);
+   segment->dump(rproc, segment, data + offset, 0, 
segment->size);
} else {
ptr = rproc_da_to_va(rproc, segment->da, segment->size);
if (!ptr) {
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index e7b7bab..eb08139 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -451,7 +451,7 @@ struct rproc_dump_segment {
 
void *priv;
void (*dump)(struct rproc *rproc, struct rproc_dump_segment *segment,
-void *dest);
+void *dest, size_t offset, size_t size);
loff_t offset;
 };
 
@@ -630,7 +630,8 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
  dma_addr_t da, size_t size,
  void (*dumpfn)(struct rproc *rproc,
 struct rproc_dump_segment 
*segment,
-void *dest),
+void *dest, size_t offset,
+size_t size),
  void *priv);
 int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 4/5] remoteproc: Add inline coredump functionality

2020-07-16 Thread Rishabh Bhatnagar
The current coredump implementation uses vmalloc area to copy
all the segments. But this might put strain on low memory targets
as the firmware size sometimes is in tens of MBs. The situation
becomes worse if there are multiple remote processors undergoing
recovery at the same time. This patch adds inline coredump
functionality that avoids extra memory usage. This requires
recovery to be halted until data is read by userspace and free
function is called.

Signed-off-by: Rishabh Bhatnagar 
Tested-by: Sibi Sankar 
---
 drivers/remoteproc/remoteproc_coredump.c | 156 +++
 include/linux/remoteproc.h   |  16 
 2 files changed, 154 insertions(+), 18 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index 390f563..bb15a29 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,12 @@
 #include "remoteproc_internal.h"
 #include "remoteproc_elf_helpers.h"
 
+struct rproc_coredump_state {
+   struct rproc *rproc;
+   void *header;
+   struct completion dump_done;
+};
+
 /**
  * rproc_coredump_cleanup() - clean up dump_segments list
  * @rproc: the remote processor handle
@@ -115,12 +122,110 @@ int rproc_coredump_set_elf_info(struct rproc *rproc, u8 
class, u16 machine)
 }
 EXPORT_SYMBOL(rproc_coredump_set_elf_info);
 
+static void rproc_coredump_free(void *data)
+{
+   struct rproc_coredump_state *dump_state = data;
+
+   vfree(dump_state->header);
+   complete(_state->dump_done);
+}
+
+static void *rproc_coredump_find_segment(loff_t user_offset,
+struct list_head *segments,
+size_t *data_left)
+{
+   struct rproc_dump_segment *segment;
+
+   list_for_each_entry(segment, segments, node) {
+   if (user_offset < segment->size) {
+   *data_left = segment->size - user_offset;
+   return segment;
+   }
+   user_offset -= segment->size;
+   }
+
+   *data_left = 0;
+   return NULL;
+}
+
+static void rproc_copy_segment(struct rproc *rproc, void *dest,
+  struct rproc_dump_segment *segment,
+  size_t offset, size_t size)
+{
+   void *ptr;
+
+   if (segment->dump) {
+   segment->dump(rproc, segment, dest, offset, size);
+   } else {
+   ptr = rproc_da_to_va(rproc, segment->da + offset, size);
+   if (!ptr) {
+   dev_err(>dev,
+   "invalid copy request for segment %pad with 
offset %zu and size %zu)\n",
+   >da, offset, size);
+   memset(dest, 0xff, size);
+   } else {
+   memcpy(dest, ptr, size);
+   }
+   }
+}
+
+static ssize_t rproc_coredump_read(char *buffer, loff_t offset, size_t count,
+  void *data, size_t header_sz)
+{
+   size_t seg_data, bytes_left = count;
+   ssize_t copy_sz;
+   struct rproc_dump_segment *seg;
+   struct rproc_coredump_state *dump_state = data;
+   struct rproc *rproc = dump_state->rproc;
+   void *elfcore = dump_state->header;
+
+   /* Copy the vmalloc'ed header first. */
+   if (offset < header_sz) {
+   copy_sz = memory_read_from_buffer(buffer, count, ,
+ elfcore, header_sz);
+
+   return copy_sz;
+   }
+
+   /*
+* Find out the segment memory chunk to be copied based on offset.
+* Keep copying data until count bytes are read.
+*/
+   while (bytes_left) {
+   seg = rproc_coredump_find_segment(offset - header_sz,
+ >dump_segments,
+ _data);
+   /* EOF check */
+   if (!seg) {
+   dev_info(>dev, "Ramdump done, %lld bytes read",
+offset);
+   break;
+   }
+
+   copy_sz = min_t(size_t, bytes_left, seg_data);
+
+   rproc_copy_segment(rproc, buffer, seg, seg->size - seg_data,
+  copy_sz);
+
+   offset += copy_sz;
+   buffer += copy_sz;
+   bytes_left -= copy_sz;
+   }
+
+   return count - bytes_left;
+}
+
 /**
  * rproc_coredump() - perform coredump
  * @rproc: rproc handle
  *
  * This function will generate an ELF header for the registered segments
- * and create a devcoredump dev

[PATCH v7 4/4] remoteproc: Add coredump debugfs entry

2020-07-09 Thread Rishabh Bhatnagar
Add coredump debugfs entry to configure the type of dump that will
be collected during recovery. User can select between default or
inline coredump functionality. Also coredump collection can be
disabled through this interface.
This functionality can be configured differently for different
remote processors.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
Tested-by: Sibi Sankar 
Reviewed-by: Sibi Sankar 
---
 drivers/remoteproc/remoteproc_debugfs.c | 90 +
 1 file changed, 90 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..16a4196 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,6 +28,94 @@
 static struct dentry *rproc_dbg;
 
 /*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via debugfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DEFAULT]= "default",
+   [RPROC_COREDUMP_INLINE] = "inline",
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
+  size_t count, loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   char buf[20];
+   int len;
+
+   len = scnprintf(buf, sizeof(buf), "%s\n",
+   rproc_coredump_str[rproc->dump_conf]);
+
+   return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+/*
+ * By writing to the 'coredump' debugfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' debugfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ *
+ * disabled:   This will disable coredump. Recovery will proceed without
+ * collecting any dump.
+ */
+static ssize_t rproc_coredump_write(struct file *filp,
+   const char __user *user_buf, size_t count,
+   loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   int ret, err = 0;
+   char buf[20];
+
+   if (count > sizeof(buf))
+   return -EINVAL;
+
+   ret = copy_from_user(buf, user_buf, count);
+   if (ret)
+   return -EFAULT;
+
+   /* remove end of line */
+   if (buf[count - 1] == '\n')
+   buf[count - 1] = '\0';
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   err = -EBUSY;
+   goto out;
+   }
+
+   if (!strncmp(buf, "disable", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (!strncmp(buf, "inline", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_INLINE;
+   } else if (!strncmp(buf, "default", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
+   } else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   err = -EINVAL;
+   }
+out:
+   return err ? err : count;
+}
+
+static const struct file_operations rproc_coredump_fops = {
+   .read = rproc_coredump_read,
+   .write = rproc_coredump_write,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
+/*
  * Some remote processors may support dumping trace logs into a shared
  * memory buffer. We expose this trace buffer using debugfs, so users
  * can easily tell what's going on remotely.
@@ -337,6 +425,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+   debugfs_create_file("coredump", 0600, rproc->dbg_dir,
+   rproc, _coredump_fops);
 }
 
 void __init rproc_init_debugfs(void)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 3/4] remoteproc: Add inline coredump functionality

2020-07-09 Thread Rishabh Bhatnagar
The current coredump implementation uses vmalloc area to copy
all the segments. But this might put strain on low memory targets
as the firmware size sometimes is in tens of MBs. The situation
becomes worse if there are multiple remote processors undergoing
recovery at the same time. This patch adds inline coredump
functionality that avoids extra memory usage. This requires
recovery to be halted until data is read by userspace and free
function is called. Also modify the qcom_q6v5_mss driver to include
size and offset in the segment dump function.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Sibi Sankar 
---
 drivers/remoteproc/qcom_q6v5_mss.c   |  11 ++-
 drivers/remoteproc/remoteproc_coredump.c | 160 +++
 include/linux/remoteproc.h   |  21 +++-
 3 files changed, 166 insertions(+), 26 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index c6ce032..79df354 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1199,11 +1199,12 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
 
 static void qcom_q6v5_dump_segment(struct rproc *rproc,
   struct rproc_dump_segment *segment,
-  void *dest)
+  void *dest, size_t cp_offset, size_t size)
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
int offset = segment->da - qproc->mpss_reloc;
+   size_t cp_size = size ? size : segment->size;
void *ptr = NULL;
 
/* Unlock mba before copying segments */
@@ -1219,16 +1220,16 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
}
 
if (!ret)
-   ptr = ioremap_wc(qproc->mpss_phys + offset, segment->size);
+   ptr = ioremap_wc(qproc->mpss_phys + offset + cp_offset, 
cp_size);
 
if (ptr) {
-   memcpy(dest, ptr, segment->size);
+   memcpy(dest, ptr, cp_size);
iounmap(ptr);
} else {
-   memset(dest, 0xff, segment->size);
+   memset(dest, 0xff, cp_size);
}
 
-   qproc->current_dump_size += segment->size;
+   qproc->current_dump_size += cp_size;
 
/* Reclaim mba after copying segments */
if (qproc->current_dump_size == qproc->total_dump_size) {
diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index ded0244..646886f 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,12 @@
 #include "remoteproc_internal.h"
 #include "remoteproc_elf_helpers.h"
 
+struct rproc_coredump_state {
+   struct rproc *rproc;
+   void *header;
+   struct completion dump_done;
+};
+
 /**
  * rproc_coredump_cleanup() - clean up dump_segments list
  * @rproc: the remote processor handle
@@ -72,7 +79,8 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
  dma_addr_t da, size_t size,
  void (*dumpfn)(struct rproc *rproc,
 struct rproc_dump_segment 
*segment,
-void *dest),
+void *dest, size_t offset,
+size_t size),
  void *priv)
 {
struct rproc_dump_segment *segment;
@@ -114,12 +122,110 @@ int rproc_coredump_set_elf_info(struct rproc *rproc, u8 
class, u16 machine)
 }
 EXPORT_SYMBOL(rproc_coredump_set_elf_info);
 
+static void rproc_coredump_free(void *data)
+{
+   struct rproc_coredump_state *dump_state = data;
+
+   complete(_state->dump_done);
+   vfree(dump_state->header);
+}
+
+static void *rproc_coredump_find_segment(loff_t user_offset,
+struct list_head *segments,
+size_t *data_left)
+{
+   struct rproc_dump_segment *segment;
+
+   list_for_each_entry(segment, segments, node) {
+   if (user_offset < segment->size) {
+   *data_left = segment->size - user_offset;
+   return segment;
+   }
+   user_offset -= segment->size;
+   }
+
+   *data_left = 0;
+   return NULL;
+}
+
+static void rproc_copy_segment(struct rproc *rproc, void *dest,
+  struct rproc_dump_segment *segment,
+  size_t offset, size_t size)
+{
+   void *ptr;
+
+   if (segment->dump) {
+   segment->dump(rproc, segment, dest, offset, size);
+

[PATCH v7 1/4] remoteproc: Move coredump functionality to a new file

2020-07-09 Thread Rishabh Bhatnagar
Move all coredump functionality to an individual file. This is
being done so that the current functionality can be extended
in future patchsets.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
Reviewed-by: Sibi Sankar 
Tested-by: Sibi Sankar 
---
 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 -
 drivers/remoteproc/remoteproc_coredump.c | 204 +++
 drivers/remoteproc/remoteproc_internal.h |   4 +
 4 files changed, 209 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index e8b886e..8702a4e 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REMOTEPROC)   += remoteproc.o
 remoteproc-y   := remoteproc_core.o
+remoteproc-y   += remoteproc_coredump.o
 remoteproc-y   += remoteproc_debugfs.o
 remoteproc-y   += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 9f04c30..57db042 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -26,7 +26,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -41,7 +40,6 @@
 #include 
 
 #include "remoteproc_internal.h"
-#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xULL
 
@@ -1239,19 +1237,6 @@ static int rproc_alloc_registered_carveouts(struct rproc 
*rproc)
return 0;
 }
 
-/**
- * rproc_coredump_cleanup() - clean up dump_segments list
- * @rproc: the remote processor handle
- */
-static void rproc_coredump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, >dump_segments, node) {
-   list_del(>node);
-   kfree(entry);
-   }
-}
 
 /**
  * rproc_resource_cleanup() - clean up and free all acquired resources
@@ -1518,182 +1503,6 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
return 0;
 }
 
-/**
- * rproc_coredump_add_segment() - add segment of device memory to coredump
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- *
- * Add device memory to the list of segments to be included in a coredump for
- * the remoteproc.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_segment);
-
-/**
- * rproc_coredump_add_custom_segment() - add custom coredump segment
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- * @dumpfn:custom dump function called for each segment during coredump
- * @priv:  private data
- *
- * Add device memory to the list of segments to be included in the coredump
- * and associate the segment with the given custom dump function and private
- * data.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_custom_segment(struct rproc *rproc,
- dma_addr_t da, size_t size,
- void (*dumpfn)(struct rproc *rproc,
-struct rproc_dump_segment 
*segment,
-void *dest),
- void *priv)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-   segment->priv = priv;
-   segment->dump = dumpfn;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
-
-/**
- * rproc_coredump_set_elf_info() - set coredump elf information
- * @rproc: handle of a remote processor
- * @class: elf class for coredump elf file
- * @machine:   elf machine for coredump elf file
- *
- * Set elf information which will be used for coredump elf file.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine)
-{
-   if (class != ELFCLASS64 && class != ELFCLASS32)
- 

[PATCH v7 0/4] Extend coredump functionality

2020-07-09 Thread Rishabh Bhatnagar
This patch series moves the coredump functionality to a separate
file and adds "inline" coredump feature. Inline coredump directly
copies segments from device memory during coredump to userspace.
This avoids extra memory usage at the cost of speed. Recovery is
stalled until all data is read by userspace.
This patchset also includes Sibi Sankar's patch to deal with chunk sizes
lesser than segment size to make inline coredump work for modem.
https://patchwork.kernel.org/patch/11637157/

Changelog:

v7 -> v6:
- Include Sibi's patch as part of this patchset
- Add a linefeed when displaying coredump conf in debugfs
- Fix a typo in remoteproc.h

v6 -> v5:
- Fix unsigned comaprison with negative bug found on gcc-9.3.0

v5 -> v4:
- Rebase on top of linux-next
- Modify qcom_q6v5_mss driver as a result of rebasing on latest tip.

v4 -> v3:
- Write a helper function to copy segment memory for every dump format
- Change segment dump fn to add offset and size adn covert mss driver

v3 -> v2:
- Move entire coredump functionality to remoteproc_coredump.c
- Modify rproc_coredump to perform dump according to conf. set by userspace
- Move the userspace configuration to debugfs from sysfs.
- Keep the default coredump implementation as is

v2 -> v1:
- Introduce new file for coredump.
- Add userspace sysfs configuration for dump type.


Rishabh Bhatnagar (3):
  remoteproc: Move coredump functionality to a new file
  remoteproc: Add inline coredump functionality
  remoteproc: Add coredump debugfs entry

Sibi Sankar (1):
  remoteproc: qcom_q6v5_mss: Replace mask based tracking with size

 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/qcom_q6v5_mss.c   |  22 +--
 drivers/remoteproc/remoteproc_core.c | 191 --
 drivers/remoteproc/remoteproc_coredump.c | 326 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  90 +
 drivers/remoteproc/remoteproc_internal.h |   4 +
 include/linux/remoteproc.h   |  21 +-
 7 files changed, 451 insertions(+), 204 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v1 2/4] remoteproc: qcom_q6v5_mss: Replace mask based tracking with size

2020-07-09 Thread Rishabh Bhatnagar
From: Sibi Sankar 

In order to land inline coredump support for mss, the dump_segment
function would need to support granularities less than the segment
size. This is achieved by replacing mask based tracking with size.

Signed-off-by: Sibi Sankar 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_q6v5_mss.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index feb70283b..c6ce032 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -181,8 +181,8 @@ struct q6v5 {
bool running;
 
bool dump_mba_loaded;
-   unsigned long dump_segment_mask;
-   unsigned long dump_complete_mask;
+   size_t current_dump_size;
+   size_t total_dump_size;
 
phys_addr_t mba_phys;
void *mba_region;
@@ -1203,7 +1203,6 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
-   unsigned long mask = BIT((unsigned long)segment->priv);
int offset = segment->da - qproc->mpss_reloc;
void *ptr = NULL;
 
@@ -1229,10 +1228,10 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
memset(dest, 0xff, segment->size);
}
 
-   qproc->dump_segment_mask |= mask;
+   qproc->current_dump_size += segment->size;
 
/* Reclaim mba after copying segments */
-   if (qproc->dump_segment_mask == qproc->dump_complete_mask) {
+   if (qproc->current_dump_size == qproc->total_dump_size) {
if (qproc->dump_mba_loaded) {
/* Try to reset ownership back to Q6 */
q6v5_xfer_mem_ownership(qproc, >mpss_perm,
@@ -1274,7 +1273,7 @@ static int q6v5_start(struct rproc *rproc)
"Failed to reclaim mba buffer system may become 
unstable\n");
 
/* Reset Dump Segment Mask */
-   qproc->dump_segment_mask = 0;
+   qproc->current_dump_size = 0;
qproc->running = true;
 
return 0;
@@ -1323,7 +1322,7 @@ static int qcom_q6v5_register_dump_segments(struct rproc 
*rproc,
 
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
-   qproc->dump_complete_mask = 0;
+   qproc->total_dump_size = 0;
 
for (i = 0; i < ehdr->e_phnum; i++) {
phdr = [i];
@@ -1338,7 +1337,7 @@ static int qcom_q6v5_register_dump_segments(struct rproc 
*rproc,
if (ret)
break;
 
-   qproc->dump_complete_mask |= BIT(i);
+   qproc->total_dump_size += phdr->p_memsz;
}
 
release_firmware(fw);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 2/3] remoteproc: Add inline coredump functionality

2020-06-29 Thread Rishabh Bhatnagar
The current coredump implementation uses vmalloc area to copy
all the segments. But this might put strain on low memory targets
as the firmware size sometimes is in tens of MBs. The situation
becomes worse if there are multiple remote processors undergoing
recovery at the same time. This patch adds inline coredump
functionality that avoids extra memory usage. This requires
recovery to be halted until data is read by userspace and free
function is called.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_q6v5_mss.c   |   9 +-
 drivers/remoteproc/remoteproc_coredump.c | 160 +++
 include/linux/remoteproc.h   |  21 +++-
 3 files changed, 165 insertions(+), 25 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index 903b2bb..d4ff9b8 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1200,12 +1200,13 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
 
 static void qcom_q6v5_dump_segment(struct rproc *rproc,
   struct rproc_dump_segment *segment,
-  void *dest)
+  void *dest, size_t cp_offset, size_t size)
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
unsigned long mask = BIT((unsigned long)segment->priv);
int offset = segment->da - qproc->mpss_reloc;
+   size_t cp_size = size ? size : segment->size;
void *ptr = NULL;
 
/* Unlock mba before copying segments */
@@ -1221,13 +1222,13 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
}
 
if (!ret)
-   ptr = ioremap_wc(qproc->mpss_phys + offset, segment->size);
+   ptr = ioremap_wc(qproc->mpss_phys + offset + cp_offset, 
cp_size);
 
if (ptr) {
-   memcpy(dest, ptr, segment->size);
+   memcpy(dest, ptr, cp_size);
iounmap(ptr);
} else {
-   memset(dest, 0xff, segment->size);
+   memset(dest, 0xff, cp_size);
}
 
qproc->dump_segment_mask |= mask;
diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index ded0244..646886f 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,12 @@
 #include "remoteproc_internal.h"
 #include "remoteproc_elf_helpers.h"
 
+struct rproc_coredump_state {
+   struct rproc *rproc;
+   void *header;
+   struct completion dump_done;
+};
+
 /**
  * rproc_coredump_cleanup() - clean up dump_segments list
  * @rproc: the remote processor handle
@@ -72,7 +79,8 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
  dma_addr_t da, size_t size,
  void (*dumpfn)(struct rproc *rproc,
 struct rproc_dump_segment 
*segment,
-void *dest),
+void *dest, size_t offset,
+size_t size),
  void *priv)
 {
struct rproc_dump_segment *segment;
@@ -114,12 +122,110 @@ int rproc_coredump_set_elf_info(struct rproc *rproc, u8 
class, u16 machine)
 }
 EXPORT_SYMBOL(rproc_coredump_set_elf_info);
 
+static void rproc_coredump_free(void *data)
+{
+   struct rproc_coredump_state *dump_state = data;
+
+   complete(_state->dump_done);
+   vfree(dump_state->header);
+}
+
+static void *rproc_coredump_find_segment(loff_t user_offset,
+struct list_head *segments,
+size_t *data_left)
+{
+   struct rproc_dump_segment *segment;
+
+   list_for_each_entry(segment, segments, node) {
+   if (user_offset < segment->size) {
+   *data_left = segment->size - user_offset;
+   return segment;
+   }
+   user_offset -= segment->size;
+   }
+
+   *data_left = 0;
+   return NULL;
+}
+
+static void rproc_copy_segment(struct rproc *rproc, void *dest,
+  struct rproc_dump_segment *segment,
+  size_t offset, size_t size)
+{
+   void *ptr;
+
+   if (segment->dump) {
+   segment->dump(rproc, segment, dest, offset, size);
+   } else {
+   ptr = rproc_da_to_va(rproc, segment->da + offset, size);
+   if (!ptr) {
+   dev_err(>dev,
+   "invalid copy request for segment %

[PATCH v6 0/3] Extend coredump functionality

2020-06-29 Thread Rishabh Bhatnagar
This patch series moves the coredump functionality to a separate
file and adds "inline" coredump feature. Inline coredump directly
copies segments from device memory during coredump to userspace.
This avoids extra memory usage at the cost of speed. Recovery is
stalled until all data is read by userspace.

Changelog:

v6 -> v5:
- Fix unsigned comaprison with negative bug found on gcc-9.3.0

v5 -> v4:
- Rebase on top of linux-next

v4 -> v3:
- Write a helper function to copy segment memory for every dump format
- Change segment dump fn to add offset and size adn covert mss driver

v3 -> v2:
- Move entire coredump functionality to remoteproc_coredump.c
- Modify rproc_coredump to perform dump according to conf. set by userspace
- Move the userspace configuration to debugfs from sysfs.
- Keep the default coredump implementation as is

v2 -> v1:
- Introduce new file for coredump.
- Add userspace sysfs configuration for dump type.

Rishabh Bhatnagar (3):
  remoteproc: Move coredump functionality to a new file
  remoteproc: Add inline coredump functionality
  remoteproc: Add coredump debugfs entry

 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/qcom_q6v5_mss.c   |   9 +-
 drivers/remoteproc/remoteproc_core.c | 191 --
 drivers/remoteproc/remoteproc_coredump.c | 328 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  86 
 drivers/remoteproc/remoteproc_internal.h |   4 +
 include/linux/remoteproc.h   |  21 +-
 7 files changed, 443 insertions(+), 197 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 1/3] remoteproc: Move coredump functionality to a new file

2020-06-29 Thread Rishabh Bhatnagar
Move all coredump functionality to an individual file. This is
being done so that the current functionality can be extended
in future patchsets.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 -
 drivers/remoteproc/remoteproc_coredump.c | 204 +++
 drivers/remoteproc/remoteproc_internal.h |   4 +
 4 files changed, 209 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index e8b886e..8702a4e 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REMOTEPROC)   += remoteproc.o
 remoteproc-y   := remoteproc_core.o
+remoteproc-y   += remoteproc_coredump.o
 remoteproc-y   += remoteproc_debugfs.o
 remoteproc-y   += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 9f04c30..57db042 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -26,7 +26,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -41,7 +40,6 @@
 #include 
 
 #include "remoteproc_internal.h"
-#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xULL
 
@@ -1239,19 +1237,6 @@ static int rproc_alloc_registered_carveouts(struct rproc 
*rproc)
return 0;
 }
 
-/**
- * rproc_coredump_cleanup() - clean up dump_segments list
- * @rproc: the remote processor handle
- */
-static void rproc_coredump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, >dump_segments, node) {
-   list_del(>node);
-   kfree(entry);
-   }
-}
 
 /**
  * rproc_resource_cleanup() - clean up and free all acquired resources
@@ -1518,182 +1503,6 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
return 0;
 }
 
-/**
- * rproc_coredump_add_segment() - add segment of device memory to coredump
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- *
- * Add device memory to the list of segments to be included in a coredump for
- * the remoteproc.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_segment);
-
-/**
- * rproc_coredump_add_custom_segment() - add custom coredump segment
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- * @dumpfn:custom dump function called for each segment during coredump
- * @priv:  private data
- *
- * Add device memory to the list of segments to be included in the coredump
- * and associate the segment with the given custom dump function and private
- * data.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_custom_segment(struct rproc *rproc,
- dma_addr_t da, size_t size,
- void (*dumpfn)(struct rproc *rproc,
-struct rproc_dump_segment 
*segment,
-void *dest),
- void *priv)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-   segment->priv = priv;
-   segment->dump = dumpfn;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
-
-/**
- * rproc_coredump_set_elf_info() - set coredump elf information
- * @rproc: handle of a remote processor
- * @class: elf class for coredump elf file
- * @machine:   elf machine for coredump elf file
- *
- * Set elf information which will be used for coredump elf file.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine)
-{
-   if (class != ELFCLASS64 && class != ELFCLASS32)
-   return -EINVAL;
-
- 

[PATCH v6 3/3] remoteproc: Add coredump debugfs entry

2020-06-29 Thread Rishabh Bhatnagar
Add coredump debugfs entry to configure the type of dump that will
be collected during recovery. User can select between default or
inline coredump functionality. Also coredump collection can be
disabled through this interface.
This functionality can be configured differently for different
remote processors.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/remoteproc_debugfs.c | 86 +
 1 file changed, 86 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..cca0a91 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,6 +28,90 @@
 static struct dentry *rproc_dbg;
 
 /*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via debugfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DEFAULT]= "default",
+   [RPROC_COREDUMP_INLINE] = "inline",
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
+  size_t count, loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   const char *buf = rproc_coredump_str[rproc->dump_conf];
+
+   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+/*
+ * By writing to the 'coredump' debugfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' debugfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ *
+ * disabled:   This will disable coredump. Recovery will proceed without
+ * collecting any dump.
+ */
+static ssize_t rproc_coredump_write(struct file *filp,
+   const char __user *user_buf, size_t count,
+   loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   int ret, err = 0;
+   char buf[20];
+
+   if (count > sizeof(buf))
+   return -EINVAL;
+
+   ret = copy_from_user(buf, user_buf, count);
+   if (ret)
+   return -EFAULT;
+
+   /* remove end of line */
+   if (buf[count - 1] == '\n')
+   buf[count - 1] = '\0';
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   err = -EBUSY;
+   goto out;
+   }
+
+   if (!strncmp(buf, "disable", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (!strncmp(buf, "inline", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_INLINE;
+   } else if (!strncmp(buf, "default", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
+   } else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   err = -EINVAL;
+   }
+out:
+   return err ? err : count;
+}
+
+static const struct file_operations rproc_coredump_fops = {
+   .read = rproc_coredump_read,
+   .write = rproc_coredump_write,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
+/*
  * Some remote processors may support dumping trace logs into a shared
  * memory buffer. We expose this trace buffer using debugfs, so users
  * can easily tell what's going on remotely.
@@ -337,6 +421,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+   debugfs_create_file("coredump", 0600, rproc->dbg_dir,
+   rproc, _coredump_fops);
 }
 
 void __init rproc_init_debugfs(void)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 1/2] remoteproc: qcom: Add per subsystem SSR notification

2020-06-23 Thread Rishabh Bhatnagar
Currently there is a single notification chain which is called whenever any
remoteproc shuts down. This leads to all the listeners being notified, and
is not an optimal design as kernel drivers might only be interested in
listening to notifications from a particular remoteproc. Create a global
list of remoteproc notification info data structures. This will hold the
name and notifier_list information for a particular remoteproc. The API
to register for notifications will use name argument to retrieve the
notification info data structure and the notifier block will be added to
that data structure's notification chain. Also move from blocking notifier
to srcu notifer based implementation to support dynamic notifier head
creation.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 90 ++-
 drivers/remoteproc/qcom_common.h  |  5 +-
 include/linux/remoteproc/qcom_rproc.h | 20 ++--
 3 files changed, 95 insertions(+), 20 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 9028cea..7a7384c 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,7 +24,14 @@
 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
 
-static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
+struct qcom_ssr_subsystem {
+   const char *name;
+   struct srcu_notifier_head notifier_list;
+   struct list_head list;
+};
+
+static LIST_HEAD(qcom_ssr_subsystem_list);
+static DEFINE_MUTEX(qcom_ssr_subsys_lock);
 
 static int glink_subdev_start(struct rproc_subdev *subdev)
 {
@@ -189,37 +197,83 @@ void qcom_remove_smd_subdev(struct rproc *rproc, struct 
qcom_rproc_subdev *smd)
 }
 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
 
+static struct qcom_ssr_subsystem *qcom_ssr_get_subsys(const char *name)
+{
+   struct qcom_ssr_subsystem *info;
+
+   mutex_lock(_ssr_subsys_lock);
+   /* Match in the global qcom_ssr_subsystem_list with name */
+   list_for_each_entry(info, _ssr_subsystem_list, list)
+   if (!strcmp(info->name, name))
+   goto out;
+
+   info = kzalloc(sizeof(*info), GFP_KERNEL);
+   if (!info) {
+   info = ERR_PTR(-ENOMEM);
+   goto out;
+   }
+   info->name = kstrdup_const(name, GFP_KERNEL);
+   srcu_init_notifier_head(>notifier_list);
+
+   /* Add to global notification list */
+   list_add_tail(>list, _ssr_subsystem_list);
+
+out:
+   mutex_unlock(_ssr_subsys_lock);
+   return info;
+}
+
 /**
  * qcom_register_ssr_notifier() - register SSR notification handler
- * @nb:notifier_block to notify for restart notifications
+ * @name:  Subsystem's SSR name
+ * @nb:notifier_block to be invoked upon subsystem's state 
change
  *
- * Returns 0 on success, negative errno on failure.
+ * This registers the @nb notifier block as part the notifier chain for a
+ * remoteproc associated with @name. The notifier block's callback
+ * will be invoked when the remote processor's SSR events occur
+ * (pre/post startup and pre/post shutdown).
  *
- * This register the @notify function as handler for restart notifications. As
- * remote processors are stopped this function will be called, with the SSR
- * name passed as a parameter.
+ * Return: a subsystem cookie on success, ERR_PTR on failure.
  */
-int qcom_register_ssr_notifier(struct notifier_block *nb)
+void *qcom_register_ssr_notifier(const char *name, struct notifier_block *nb)
 {
-   return blocking_notifier_chain_register(_notifiers, nb);
+   struct qcom_ssr_subsystem *info;
+
+   info = qcom_ssr_get_subsys(name);
+   if (IS_ERR(info))
+   return info;
+
+   srcu_notifier_chain_register(>notifier_list, nb);
+
+   return >notifier_list;
 }
 EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier);
 
 /**
  * qcom_unregister_ssr_notifier() - unregister SSR notification handler
+ * @notify:subsystem coookie returned from qcom_register_ssr_notifier
  * @nb:notifier_block to unregister
+ *
+ * This function will unregister the notifier from the particular notifier
+ * chain.
+ *
+ * Return: 0 on success, %ENOENT otherwise.
  */
-void qcom_unregister_ssr_notifier(struct notifier_block *nb)
+int qcom_unregister_ssr_notifier(void *notify, struct notifier_block *nb)
 {
-   blocking_notifier_chain_unregister(_notifiers, nb);
+   return srcu_notifier_chain_unregister(notify, nb);
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notify_data data = {
+   .name

[PATCH v6 0/2] Extend SSR notifications framework

2020-06-23 Thread Rishabh Bhatnagar
This set of patches gives kernel client drivers the ability to register
for a particular remoteproc's SSR notifications. Also the notifications
are extended to before/after-powerup/shutdown stages.
It also fixes the bug where clients need to register for notifications
again if the platform driver is removed. This is done by creating a
global list of per-remoteproc notification info data structures which
remain static. An API is exported to register for a remoteproc's SSR
notifications and uses remoteproc's ssr_name and notifier block as
arguments.

Changelog:

v6 -> v5:
- Fix mutec locking and naming convention

v5 -> v4:
- Make qcom_ssr_get_subsys static function
- Fix mutex locking
- Fix function comments

v4 -> v3:
- Fix naming convention 

v3 -> v2:
- Create a global list of per remoteproc notification data structure
- Pass ssr_name and crashed information as part of notification data
- Move notification type enum to qcom_rproc.h from remoteproc.h

v2 -> v1:
- Fix commit text

Rishabh Bhatnagar (1):
  remoteproc: qcom: Add per subsystem SSR notification

Siddharth Gupta (1):
  remoteproc: qcom: Add notification types to SSR

 drivers/remoteproc/qcom_common.c  | 128 ++
 drivers/remoteproc/qcom_common.h  |   5 +-
 include/linux/remoteproc/qcom_rproc.h |  36 --
 3 files changed, 149 insertions(+), 20 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 2/2] remoteproc: qcom: Add notification types to SSR

2020-06-23 Thread Rishabh Bhatnagar
The SSR subdevice only adds callback for the unprepare event. Add callbacks
for prepare, start and prepare events. The client driver for a particular
remoteproc might be interested in knowing the status of the remoteproc
while undergoing SSR, not just when the remoteproc has finished shutting
down.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 44 ++-
 include/linux/remoteproc/qcom_rproc.h | 16 +
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 7a7384c..7ec4597 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -265,6 +265,44 @@ int qcom_unregister_ssr_notifier(void *notify, struct 
notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
+static int ssr_notify_prepare(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notify_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_BEFORE_POWERUP, );
+   return 0;
+}
+
+static int ssr_notify_start(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notify_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_AFTER_POWERUP, );
+   return 0;
+}
+
+static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notify_data data = {
+   .name = ssr->info->name,
+   .crashed = crashed,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_BEFORE_SHUTDOWN, );
+}
+
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
@@ -273,7 +311,8 @@ static void ssr_notify_unprepare(struct rproc_subdev 
*subdev)
.crashed = false,
};
 
-   srcu_notifier_call_chain(>info->notifier_list, 0, );
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_AFTER_SHUTDOWN, );
 }
 
 /**
@@ -298,6 +337,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct 
qcom_rproc_ssr *ssr,
}
 
ssr->info = info;
+   ssr->subdev.prepare = ssr_notify_prepare;
+   ssr->subdev.start = ssr_notify_start;
+   ssr->subdev.stop = ssr_notify_stop;
ssr->subdev.unprepare = ssr_notify_unprepare;
 
rproc_add_subdev(rproc, >subdev);
diff --git a/include/linux/remoteproc/qcom_rproc.h 
b/include/linux/remoteproc/qcom_rproc.h
index 2a1d6d0..6470516 100644
--- a/include/linux/remoteproc/qcom_rproc.h
+++ b/include/linux/remoteproc/qcom_rproc.h
@@ -5,6 +5,22 @@ struct notifier_block;
 
 #if IS_ENABLED(CONFIG_QCOM_RPROC_COMMON)
 
+/**
+ * enum qcom_ssr_notify_type - Startup/Shutdown events related to a remoteproc
+ * processor.
+ *
+ * @QCOM_SSR_BEFORE_POWERUP:   Remoteproc about to start (prepare stage)
+ * @QCOM_SSR_AFTER_POWERUP:Remoteproc is running (start stage)
+ * @QCOM_SSR_BEFORE_SHUTDOWN:  Remoteproc crashed or shutting down (stop stage)
+ * @QCOM_SSR_AFTER_SHUTDOWN:   Remoteproc is down (unprepare stage)
+ */
+enum qcom_ssr_notify_type {
+   QCOM_SSR_BEFORE_POWERUP,
+   QCOM_SSR_AFTER_POWERUP,
+   QCOM_SSR_BEFORE_SHUTDOWN,
+   QCOM_SSR_AFTER_SHUTDOWN,
+};
+
 struct qcom_ssr_notify_data {
const char *name;
bool crashed;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v5 2/3] remoteproc: Add inline coredump functionality

2020-06-23 Thread Rishabh Bhatnagar
The current coredump implementation uses vmalloc area to copy
all the segments. But this might put strain on low memory targets
as the firmware size sometimes is in tens of MBs. The situation
becomes worse if there are multiple remote processors undergoing
recovery at the same time. This patch adds inline coredump
functionality that avoids extra memory usage. This requires
recovery to be halted until data is read by userspace and free
function is called.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_q6v5_mss.c   |   9 +-
 drivers/remoteproc/remoteproc_coredump.c | 162 +++
 include/linux/remoteproc.h   |  21 +++-
 3 files changed, 167 insertions(+), 25 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index 903b2bb..d4ff9b8 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1200,12 +1200,13 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
 
 static void qcom_q6v5_dump_segment(struct rproc *rproc,
   struct rproc_dump_segment *segment,
-  void *dest)
+  void *dest, size_t cp_offset, size_t size)
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
unsigned long mask = BIT((unsigned long)segment->priv);
int offset = segment->da - qproc->mpss_reloc;
+   size_t cp_size = size ? size : segment->size;
void *ptr = NULL;
 
/* Unlock mba before copying segments */
@@ -1221,13 +1222,13 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
}
 
if (!ret)
-   ptr = ioremap_wc(qproc->mpss_phys + offset, segment->size);
+   ptr = ioremap_wc(qproc->mpss_phys + offset + cp_offset, 
cp_size);
 
if (ptr) {
-   memcpy(dest, ptr, segment->size);
+   memcpy(dest, ptr, cp_size);
iounmap(ptr);
} else {
-   memset(dest, 0xff, segment->size);
+   memset(dest, 0xff, cp_size);
}
 
qproc->dump_segment_mask |= mask;
diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index ded0244..e643a66 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,12 @@
 #include "remoteproc_internal.h"
 #include "remoteproc_elf_helpers.h"
 
+struct rproc_coredump_state {
+   struct rproc *rproc;
+   void *header;
+   struct completion dump_done;
+};
+
 /**
  * rproc_coredump_cleanup() - clean up dump_segments list
  * @rproc: the remote processor handle
@@ -72,7 +79,8 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
  dma_addr_t da, size_t size,
  void (*dumpfn)(struct rproc *rproc,
 struct rproc_dump_segment 
*segment,
-void *dest),
+void *dest, size_t offset,
+size_t size),
  void *priv)
 {
struct rproc_dump_segment *segment;
@@ -114,12 +122,112 @@ int rproc_coredump_set_elf_info(struct rproc *rproc, u8 
class, u16 machine)
 }
 EXPORT_SYMBOL(rproc_coredump_set_elf_info);
 
+static void rproc_coredump_free(void *data)
+{
+   struct rproc_coredump_state *dump_state = data;
+
+   complete(_state->dump_done);
+   vfree(dump_state->header);
+}
+
+static void *rproc_coredump_find_segment(loff_t user_offset,
+struct list_head *segments,
+size_t *data_left)
+{
+   struct rproc_dump_segment *segment;
+
+   list_for_each_entry(segment, segments, node) {
+   if (user_offset < segment->size) {
+   *data_left = segment->size - user_offset;
+   return segment;
+   }
+   user_offset -= segment->size;
+   }
+
+   *data_left = 0;
+   return NULL;
+}
+
+static void rproc_copy_segment(struct rproc *rproc, void *dest,
+  struct rproc_dump_segment *segment,
+  size_t offset, size_t size)
+{
+   void *ptr;
+
+   if (segment->dump) {
+   segment->dump(rproc, segment, dest, offset, size);
+   } else {
+   ptr = rproc_da_to_va(rproc, segment->da + offset, size);
+   if (!ptr) {
+   dev_err(>dev,
+   "invalid copy request (%zu, %zu)\n",
+

[PATCH v5 3/3] remoteproc: Add coredump debugfs entry

2020-06-23 Thread Rishabh Bhatnagar
Add coredump debugfs entry to configure the type of dump that will
be collected during recovery. User can select between default or
inline coredump functionality. Also coredump collection can be
disabled through this interface.
This functionality can be configured differently for different
remote processors.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/remoteproc_debugfs.c | 86 +
 1 file changed, 86 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..cca0a91 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,6 +28,90 @@
 static struct dentry *rproc_dbg;
 
 /*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via debugfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DEFAULT]= "default",
+   [RPROC_COREDUMP_INLINE] = "inline",
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
+  size_t count, loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   const char *buf = rproc_coredump_str[rproc->dump_conf];
+
+   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+/*
+ * By writing to the 'coredump' debugfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' debugfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ *
+ * disabled:   This will disable coredump. Recovery will proceed without
+ * collecting any dump.
+ */
+static ssize_t rproc_coredump_write(struct file *filp,
+   const char __user *user_buf, size_t count,
+   loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   int ret, err = 0;
+   char buf[20];
+
+   if (count > sizeof(buf))
+   return -EINVAL;
+
+   ret = copy_from_user(buf, user_buf, count);
+   if (ret)
+   return -EFAULT;
+
+   /* remove end of line */
+   if (buf[count - 1] == '\n')
+   buf[count - 1] = '\0';
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   err = -EBUSY;
+   goto out;
+   }
+
+   if (!strncmp(buf, "disable", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (!strncmp(buf, "inline", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_INLINE;
+   } else if (!strncmp(buf, "default", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
+   } else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   err = -EINVAL;
+   }
+out:
+   return err ? err : count;
+}
+
+static const struct file_operations rproc_coredump_fops = {
+   .read = rproc_coredump_read,
+   .write = rproc_coredump_write,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
+/*
  * Some remote processors may support dumping trace logs into a shared
  * memory buffer. We expose this trace buffer using debugfs, so users
  * can easily tell what's going on remotely.
@@ -337,6 +421,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+   debugfs_create_file("coredump", 0600, rproc->dbg_dir,
+   rproc, _coredump_fops);
 }
 
 void __init rproc_init_debugfs(void)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v5 1/3] remoteproc: Move coredump functionality to a new file

2020-06-23 Thread Rishabh Bhatnagar
Move all coredump functionality to an individual file. This is
being done so that the current functionality can be extended
in future patchsets.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 -
 drivers/remoteproc/remoteproc_coredump.c | 204 +++
 drivers/remoteproc/remoteproc_internal.h |   4 +
 4 files changed, 209 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index e8b886e..8702a4e 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REMOTEPROC)   += remoteproc.o
 remoteproc-y   := remoteproc_core.o
+remoteproc-y   += remoteproc_coredump.o
 remoteproc-y   += remoteproc_debugfs.o
 remoteproc-y   += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 9f04c30..57db042 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -26,7 +26,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -41,7 +40,6 @@
 #include 
 
 #include "remoteproc_internal.h"
-#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xULL
 
@@ -1239,19 +1237,6 @@ static int rproc_alloc_registered_carveouts(struct rproc 
*rproc)
return 0;
 }
 
-/**
- * rproc_coredump_cleanup() - clean up dump_segments list
- * @rproc: the remote processor handle
- */
-static void rproc_coredump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, >dump_segments, node) {
-   list_del(>node);
-   kfree(entry);
-   }
-}
 
 /**
  * rproc_resource_cleanup() - clean up and free all acquired resources
@@ -1518,182 +1503,6 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
return 0;
 }
 
-/**
- * rproc_coredump_add_segment() - add segment of device memory to coredump
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- *
- * Add device memory to the list of segments to be included in a coredump for
- * the remoteproc.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_segment);
-
-/**
- * rproc_coredump_add_custom_segment() - add custom coredump segment
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- * @dumpfn:custom dump function called for each segment during coredump
- * @priv:  private data
- *
- * Add device memory to the list of segments to be included in the coredump
- * and associate the segment with the given custom dump function and private
- * data.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_custom_segment(struct rproc *rproc,
- dma_addr_t da, size_t size,
- void (*dumpfn)(struct rproc *rproc,
-struct rproc_dump_segment 
*segment,
-void *dest),
- void *priv)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-   segment->priv = priv;
-   segment->dump = dumpfn;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
-
-/**
- * rproc_coredump_set_elf_info() - set coredump elf information
- * @rproc: handle of a remote processor
- * @class: elf class for coredump elf file
- * @machine:   elf machine for coredump elf file
- *
- * Set elf information which will be used for coredump elf file.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine)
-{
-   if (class != ELFCLASS64 && class != ELFCLASS32)
-   return -EINVAL;
-
- 

[PATCH v5 0/3] Extend coredump functionality

2020-06-23 Thread Rishabh Bhatnagar
This patch series moves the coredump functionality to a separate
file and adds "inline" coredump feature. Inline coredump directly
copies segments from device memory during coredump to userspace.
This avoids extra memory usage at the cost of speed. Recovery is
stalled until all data is read by userspace.

Changelog:

v5 -> v4:
- Rebase on top of linux-next

v4 -> v3:
- Write a helper function to copy segment memory for every dump format
- Change segment dump fn to add offset and size adn covert mss driver

v3 -> v2:
- Move entire coredump functionality to remoteproc_coredump.c
- Modify rproc_coredump to perform dump according to conf. set by userspace
- Move the userspace configuration to debugfs from sysfs.
- Keep the default coredump implementation as is

v2 -> v1:
- Introduce new file for coredump.
- Add userspace sysfs configuration for dump type.

Rishabh Bhatnagar (3):
  remoteproc: Move coredump functionality to a new file
  remoteproc: Add inline coredump functionality
  remoteproc: Add coredump debugfs entry

 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/qcom_q6v5_mss.c   |   9 +-
 drivers/remoteproc/remoteproc_core.c | 191 --
 drivers/remoteproc/remoteproc_coredump.c | 328 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  86 
 drivers/remoteproc/remoteproc_internal.h |   4 +
 include/linux/remoteproc.h   |  21 +-
 7 files changed, 443 insertions(+), 197 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v5 1/2] remoteproc: qcom: Add per subsystem SSR notification

2020-06-22 Thread Rishabh Bhatnagar
Currently there is a single notification chain which is called whenever any
remoteproc shuts down. This leads to all the listeners being notified, and
is not an optimal design as kernel drivers might only be interested in
listening to notifications from a particular remoteproc. Create a global
list of remoteproc notification info data structures. This will hold the
name and notifier_list information for a particular remoteproc. The API
to register for notifications will use name argument to retrieve the
notification info data structure and the notifier block will be added to
that data structure's notification chain. Also move from blocking notifier
to srcu notifer based implementation to support dynamic notifier head
creation.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 86 +--
 drivers/remoteproc/qcom_common.h  |  5 +-
 include/linux/remoteproc/qcom_rproc.h | 20 ++--
 3 files changed, 91 insertions(+), 20 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 9028cea..658f2ca 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,7 +24,14 @@
 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
 
-static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
+struct qcom_ssr_subsystem {
+   const char *name;
+   struct srcu_notifier_head notifier_list;
+   struct list_head list;
+};
+
+static LIST_HEAD(qcom_ssr_subsystem_list);
+static DEFINE_MUTEX(qcom_ssr_subsys_lock);
 
 static int glink_subdev_start(struct rproc_subdev *subdev)
 {
@@ -189,37 +197,80 @@ void qcom_remove_smd_subdev(struct rproc *rproc, struct 
qcom_rproc_subdev *smd)
 }
 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
 
+static struct qcom_ssr_subsystem *qcom_ssr_get_subsys(const char *name)
+{
+   struct qcom_ssr_subsystem *info;
+
+   mutex_lock(_ssr_subsys_lock);
+   /* Match in the global qcom_ssr_subsystem_list with name */
+   list_for_each_entry(info, _ssr_subsystem_list, list)
+   if (!strcmp(info->name, name))
+   return info;
+
+   info = kzalloc(sizeof(*info), GFP_KERNEL);
+   if (!info)
+   return ERR_PTR(-ENOMEM);
+   info->name = kstrdup_const(name, GFP_KERNEL);
+   srcu_init_notifier_head(>notifier_list);
+
+   /* Add to global notification list */
+   list_add_tail(>list, _ssr_subsystem_list);
+   mutex_unlock(_ssr_subsys_lock);
+
+   return info;
+}
+
 /**
  * qcom_register_ssr_notifier() - register SSR notification handler
- * @nb:notifier_block to notify for restart notifications
+ * @name:  Subsystem's SSR name
+ * @nb:notifier_block to be invoked upon subsystem's state 
change
  *
- * Returns 0 on success, negative errno on failure.
+ * This registers the @nb notifier block as part the notifier chain for a
+ * remoteproc associated with @name. The notifier block's callback
+ * will be invoked when the remote processor's SSR events occur
+ * (pre/post startup and pre/post shutdown).
  *
- * This register the @notify function as handler for restart notifications. As
- * remote processors are stopped this function will be called, with the SSR
- * name passed as a parameter.
+ * Return: a subsystem cookie on success, ERR_PTR on failure.
  */
-int qcom_register_ssr_notifier(struct notifier_block *nb)
+void *qcom_register_ssr_notifier(const char *name, struct notifier_block *nb)
 {
-   return blocking_notifier_chain_register(_notifiers, nb);
+   struct qcom_ssr_subsystem *info;
+
+   info = qcom_ssr_get_subsys(name);
+   if (IS_ERR(info))
+   return info;
+
+   srcu_notifier_chain_register(>notifier_list, nb);
+
+   return >notifier_list;
 }
 EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier);
 
 /**
  * qcom_unregister_ssr_notifier() - unregister SSR notification handler
+ * @notify:subsystem coookie returned from qcom_register_ssr_notifier
  * @nb:notifier_block to unregister
+ *
+ * This function will unregister the notifier from the particular notifier
+ * chain.
+ *
+ * Return: 0 on success, %ENOENT otherwise.
  */
-void qcom_unregister_ssr_notifier(struct notifier_block *nb)
+int qcom_unregister_ssr_notifier(void *notify, struct notifier_block *nb)
 {
-   blocking_notifier_chain_unregister(_notifiers, nb);
+   return srcu_notifier_chain_unregister(notify, nb);
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   

[PATCH v5 0/2] Extend SSR notifications framework

2020-06-22 Thread Rishabh Bhatnagar
This set of patches gives kernel client drivers the ability to register
for a particular remoteproc's SSR notifications. Also the notifications
are extended to before/after-powerup/shutdown stages.
It also fixes the bug where clients need to register for notifications
again if the platform driver is removed. This is done by creating a
global list of per-remoteproc notification info data structures which
remain static. An API is exported to register for a remoteproc's SSR
notifications and uses remoteproc's ssr_name and notifier block as
arguments.

Changelog:
v5 -> v4:
- Make qcom_ssr_get_subsys static function
- Fix mutex locking
- Fix function comments

v4 -> v3:
- Fix naming convention 

v3 -> v2:
- Create a global list of per remoteproc notification data structure
- Pass ssr_name and crashed information as part of notification data
- Move notification type enum to qcom_rproc.h from remoteproc.h

v2 -> v1:
- Fix commit text

Rishabh Bhatnagar (1):
  remoteproc: qcom: Add per subsystem SSR notification

Siddharth Gupta (1):
  remoteproc: qcom: Add notification types to SSR

 drivers/remoteproc/qcom_common.c  | 128 ++
 drivers/remoteproc/qcom_common.h  |   5 +-
 include/linux/remoteproc/qcom_rproc.h |  36 --
 3 files changed, 149 insertions(+), 20 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v5 2/2] remoteproc: qcom: Add notification types to SSR

2020-06-22 Thread Rishabh Bhatnagar
The SSR subdevice only adds callback for the unprepare event. Add callbacks
for prepare, start and prepare events. The client driver for a particular
remoteproc might be interested in knowing the status of the remoteproc
while undergoing SSR, not just when the remoteproc has finished shutting
down.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 44 ++-
 include/linux/remoteproc/qcom_rproc.h | 16 +
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 658f2ca..0848bf1 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -262,6 +262,44 @@ int qcom_unregister_ssr_notifier(void *notify, struct 
notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
+static int ssr_notify_prepare(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_BEFORE_POWERUP, );
+   return 0;
+}
+
+static int ssr_notify_start(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_AFTER_POWERUP, );
+   return 0;
+}
+
+static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = crashed,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_BEFORE_SHUTDOWN, );
+}
+
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
@@ -270,7 +308,8 @@ static void ssr_notify_unprepare(struct rproc_subdev 
*subdev)
.crashed = false,
};
 
-   srcu_notifier_call_chain(>info->notifier_list, 0, );
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_AFTER_SHUTDOWN, );
 }
 
 /**
@@ -294,6 +333,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct 
qcom_rproc_ssr *ssr,
}
 
ssr->info = info;
+   ssr->subdev.prepare = ssr_notify_prepare;
+   ssr->subdev.start = ssr_notify_start;
+   ssr->subdev.stop = ssr_notify_stop;
ssr->subdev.unprepare = ssr_notify_unprepare;
 
rproc_add_subdev(rproc, >subdev);
diff --git a/include/linux/remoteproc/qcom_rproc.h 
b/include/linux/remoteproc/qcom_rproc.h
index 58422b1..83ac8e8 100644
--- a/include/linux/remoteproc/qcom_rproc.h
+++ b/include/linux/remoteproc/qcom_rproc.h
@@ -5,6 +5,22 @@ struct notifier_block;
 
 #if IS_ENABLED(CONFIG_QCOM_RPROC_COMMON)
 
+/**
+ * enum qcom_ssr_notif_type - Startup/Shutdown events related to a remoteproc
+ * processor.
+ *
+ * @QCOM_SSR_BEFORE_POWERUP:   Remoteproc about to start (prepare stage)
+ * @QCOM_SSR_AFTER_POWERUP:Remoteproc is running (start stage)
+ * @QCOM_SSR_BEFORE_SHUTDOWN:  Remoteproc crashed or shutting down (stop stage)
+ * @QCOM_SSR_AFTER_SHUTDOWN:   Remoteproc is down (unprepare stage)
+ */
+enum qcom_ssr_notif_type {
+   QCOM_SSR_BEFORE_POWERUP,
+   QCOM_SSR_AFTER_POWERUP,
+   QCOM_SSR_BEFORE_SHUTDOWN,
+   QCOM_SSR_AFTER_SHUTDOWN,
+};
+
 struct qcom_ssr_notif_data {
const char *name;
bool crashed;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v4 1/2] remoteproc: qcom: Add per subsystem SSR notification

2020-05-27 Thread Rishabh Bhatnagar
Currently there is a single notification chain which is called whenever any
remoteproc shuts down. This leads to all the listeners being notified, and
is not an optimal design as kernel drivers might only be interested in
listening to notifications from a particular remoteproc. Create a global
list of remoteproc notification info data structures. This will hold the
name and notifier_list information for a particular remoteproc. The API
to register for notifications will use name argument to retrieve the
notification info data structure and the notifier block will be added to
that data structure's notification chain. Also move from blocking notifier
to srcu notifer based implementation to support dynamic notifier head
creation.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 84 ++-
 drivers/remoteproc/qcom_common.h  |  5 ++-
 include/linux/remoteproc/qcom_rproc.h | 20 ++---
 3 files changed, 90 insertions(+), 19 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 9028cea..61ff2dd 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,7 +24,14 @@
 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
 
-static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
+struct qcom_ssr_subsystem {
+   const char *name;
+   struct srcu_notifier_head notifier_list;
+   struct list_head list;
+};
+
+static LIST_HEAD(qcom_ssr_subsystem_list);
+DEFINE_MUTEX(qcom_ssr_subsys_lock);
 
 static int glink_subdev_start(struct rproc_subdev *subdev)
 {
@@ -189,39 +197,79 @@ void qcom_remove_smd_subdev(struct rproc *rproc, struct 
qcom_rproc_subdev *smd)
 }
 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
 
+struct qcom_ssr_subsystem *qcom_ssr_get_subsys(const char *name)
+{
+   struct qcom_ssr_subsystem *info;
+
+   /* Match in the global qcom_ssr_subsystem_list with name */
+   list_for_each_entry(info, _ssr_subsystem_list, list) {
+   if (!strcmp(info->name, name))
+   return info;
+   }
+   info = kzalloc(sizeof(*info), GFP_KERNEL);
+   if (!info)
+   return ERR_PTR(-ENOMEM);
+   info->name = kstrdup_const(name, GFP_KERNEL);
+   srcu_init_notifier_head(>notifier_list);
+
+   /* Add to global notif list */
+   INIT_LIST_HEAD(>list);
+   list_add_tail(>list, _ssr_subsystem_list);
+
+   return info;
+}
+
 /**
  * qcom_register_ssr_notifier() - register SSR notification handler
+ * @name:  name that will be searched in global ssr subsystem list
  * @nb:notifier_block to notify for restart notifications
  *
- * Returns 0 on success, negative errno on failure.
+ * Returns a subsystem cookie on success, ERR_PTR on failure.
  *
- * This register the @notify function as handler for restart notifications. As
- * remote processors are stopped this function will be called, with the SSR
- * name passed as a parameter.
+ * This registers the @nb notifier block as part the notifier chain for a
+ * remoteproc associated with @name. The notifier block's callback
+ * will be invoked when the particular remote processor is stopped.
  */
-int qcom_register_ssr_notifier(struct notifier_block *nb)
+void *qcom_register_ssr_notifier(const char *name, struct notifier_block *nb)
 {
-   return blocking_notifier_chain_register(_notifiers, nb);
+   struct qcom_ssr_subsystem *info;
+
+   mutex_lock(_ssr_subsys_lock);
+   info = qcom_ssr_get_subsys(name);
+   if (IS_ERR(info)) {
+   mutex_unlock(_ssr_subsys_lock);
+   return info;
+   }
+
+   srcu_notifier_chain_register(>notifier_list, nb);
+   mutex_unlock(_ssr_subsys_lock);
+   return >notifier_list;
 }
 EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier);
 
 /**
  * qcom_unregister_ssr_notifier() - unregister SSR notification handler
+ * @notify:subsystem coookie returned from qcom_register_ssr_notifier
  * @nb:notifier_block to unregister
  */
-void qcom_unregister_ssr_notifier(struct notifier_block *nb)
+int qcom_unregister_ssr_notifier(void *notify, struct notifier_block *nb)
 {
-   blocking_notifier_chain_unregister(_notifiers, nb);
+   return srcu_notifier_chain_unregister(notify, nb);
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
 
-   blocking_notifier_call_chain(_notifiers, 0, (void *)ssr->name);
+   srcu_notifier_call

[PATCH v4 2/2] remoteproc: qcom: Add notification types to SSR

2020-05-27 Thread Rishabh Bhatnagar
From: Siddharth Gupta 

The SSR subdevice only adds callback for the unprepare event. Add callbacks
for unprepare, start and prepare events. The client driver for a particular
remoteproc might be interested in knowing the status of the remoteproc
while undergoing SSR, not just when the remoteproc has finished shutting
down.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 46 +--
 include/linux/remoteproc/qcom_rproc.h | 14 +++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 61ff2dd..5c5a1eb 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -228,7 +228,7 @@ struct qcom_ssr_subsystem *qcom_ssr_get_subsys(const char 
*name)
  *
  * This registers the @nb notifier block as part the notifier chain for a
  * remoteproc associated with @name. The notifier block's callback
- * will be invoked when the particular remote processor is stopped.
+ * will be invoked when the particular remote processor is started/stopped.
  */
 void *qcom_register_ssr_notifier(const char *name, struct notifier_block *nb)
 {
@@ -258,6 +258,44 @@ int qcom_unregister_ssr_notifier(void *notify, struct 
notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
+static int ssr_notify_prepare(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_BEFORE_POWERUP, );
+   return 0;
+}
+
+static int ssr_notify_start(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_AFTER_POWERUP, );
+   return 0;
+}
+
+static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct qcom_ssr_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = crashed,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_BEFORE_SHUTDOWN, );
+}
+
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
@@ -266,7 +304,8 @@ static void ssr_notify_unprepare(struct rproc_subdev 
*subdev)
.crashed = false,
};
 
-   srcu_notifier_call_chain(>info->notifier_list, 0, );
+   srcu_notifier_call_chain(>info->notifier_list,
+QCOM_SSR_AFTER_SHUTDOWN, );
 }
 
 
@@ -294,6 +333,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct 
qcom_rproc_ssr *ssr,
 
mutex_unlock(_ssr_subsys_lock);
ssr->info = info;
+   ssr->subdev.prepare = ssr_notify_prepare;
+   ssr->subdev.start = ssr_notify_start;
+   ssr->subdev.stop = ssr_notify_stop;
ssr->subdev.unprepare = ssr_notify_unprepare;
 
rproc_add_subdev(rproc, >subdev);
diff --git a/include/linux/remoteproc/qcom_rproc.h 
b/include/linux/remoteproc/qcom_rproc.h
index 58422b1..a558183 100644
--- a/include/linux/remoteproc/qcom_rproc.h
+++ b/include/linux/remoteproc/qcom_rproc.h
@@ -5,6 +5,20 @@
 
 #if IS_ENABLED(CONFIG_QCOM_RPROC_COMMON)
 
+/**
+ * enum qcom_ssr_notif_type - Different stages of remoteproc notifications
+ * @QCOM_SSR_BEFORE_SHUTDOWN:  unprepare stage of  remoteproc
+ * @QCOM_SSR_AFTER_SHUTDOWN:   stop stage of  remoteproc
+ * @QCOM_SSR_BEFORE_POWERUP:   prepare stage of  remoteproc
+ * @QCOM_SSR_AFTER_POWERUP:start stage of  remoteproc
+ */
+enum qcom_ssr_notif_type {
+   QCOM_SSR_BEFORE_SHUTDOWN,
+   QCOM_SSR_AFTER_SHUTDOWN,
+   QCOM_SSR_BEFORE_POWERUP,
+   QCOM_SSR_AFTER_POWERUP,
+};
+
 struct qcom_ssr_notif_data {
const char *name;
bool crashed;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v4 0/2] Extend SSR notifications framework

2020-05-27 Thread Rishabh Bhatnagar
This set of patches gives kernel client drivers the ability to register
for a particular remoteproc's SSR notifications. Also the notifications
are extended to before/after-powerup/shutdown stages.
It also fixes the bug where clients need to register for notifications
again if the platform driver is removed. This is done by creating a
global list of per-remoteproc notification info data structures which
remain static. An API is exported to register for a remoteproc's SSR
notifications and uses remoteproc's ssr_name and notifier block as
arguments. 

Changelog:
v4 -> v3:
- Fix naming convention 

v3 -> v2:
- Create a global list of per remoteproc notification data structure
- Pass ssr_name and crashed information as part of notification data
- Move notification type enum to qcom_rproc.h from remoteproc.h

 v2 -> v1:
- Fix commit text

Rishabh Bhatnagar (1):
  remoteproc: qcom: Add per subsystem SSR notification

Siddharth Gupta (1):
  remoteproc: qcom: Add notification types to SSR

 drivers/remoteproc/qcom_common.c  | 126 ++
 drivers/remoteproc/qcom_common.h  |   5 +-
 include/linux/remoteproc/qcom_rproc.h |  34 +++--
 3 files changed, 146 insertions(+), 19 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[v4 PATCH 0/3] Extend coredump functionality

2020-05-27 Thread Rishabh Bhatnagar
This patch series moves the coredump functionality to a separate
file and adds "inline" coredump feature. Inline coredump directly
copies segments from device memory during coredump to userspace.
This avoids extra memory usage at the cost of speed. Recovery is
stalled until all data is read by userspace.

Changelog:

v4 -> v3:
- Write a helper function to copy segment memory for every dump format
- Change segment dump fn to add offset and size adn covert mss driver

v3 -> v2:
- Move entire coredump functionality to remoteproc_coredump.c
- Modify rproc_coredump to perform dump according to conf. set by userspace
- Move the userspace configuration to debugfs from sysfs.
- Keep the default coredump implementation as is

v2 -> v1:
- Introduce new file for coredump.
- Add userspace sysfs configuration for dump type.

Rishabh Bhatnagar (3):
  remoteproc: Move coredump functionality to a new file
  remoteproc: Add inline coredump functionality
  remoteproc: Add coredump debugfs entry

 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/qcom_q6v5_mss.c   |   9 +-
 drivers/remoteproc/remoteproc_core.c | 191 --
 drivers/remoteproc/remoteproc_coredump.c | 328 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  86 
 drivers/remoteproc/remoteproc_internal.h |   4 +
 include/linux/remoteproc.h   |  21 +-
 7 files changed, 443 insertions(+), 197 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v4 1/3] remoteproc: Move coredump functionality to a new file

2020-05-27 Thread Rishabh Bhatnagar
Move all coredump functionality to an individual file. This is
being done so that the current functionality can be extended
in future patchsets.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 -
 drivers/remoteproc/remoteproc_coredump.c | 204 +++
 drivers/remoteproc/remoteproc_internal.h |   4 +
 4 files changed, 209 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 0effd38..f1a33c3 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REMOTEPROC)   += remoteproc.o
 remoteproc-y   := remoteproc_core.o
+remoteproc-y   += remoteproc_coredump.o
 remoteproc-y   += remoteproc_debugfs.o
 remoteproc-y   += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 4bd0f45..22575f4 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -26,7 +26,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -40,7 +39,6 @@
 #include 
 
 #include "remoteproc_internal.h"
-#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xULL
 
@@ -1238,19 +1236,6 @@ static int rproc_alloc_registered_carveouts(struct rproc 
*rproc)
return 0;
 }
 
-/**
- * rproc_coredump_cleanup() - clean up dump_segments list
- * @rproc: the remote processor handle
- */
-static void rproc_coredump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, >dump_segments, node) {
-   list_del(>node);
-   kfree(entry);
-   }
-}
 
 /**
  * rproc_resource_cleanup() - clean up and free all acquired resources
@@ -1509,182 +1494,6 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
return 0;
 }
 
-/**
- * rproc_coredump_add_segment() - add segment of device memory to coredump
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- *
- * Add device memory to the list of segments to be included in a coredump for
- * the remoteproc.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_segment);
-
-/**
- * rproc_coredump_add_custom_segment() - add custom coredump segment
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- * @dumpfn:custom dump function called for each segment during coredump
- * @priv:  private data
- *
- * Add device memory to the list of segments to be included in the coredump
- * and associate the segment with the given custom dump function and private
- * data.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_custom_segment(struct rproc *rproc,
- dma_addr_t da, size_t size,
- void (*dumpfn)(struct rproc *rproc,
-struct rproc_dump_segment 
*segment,
-void *dest),
- void *priv)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-   segment->priv = priv;
-   segment->dump = dumpfn;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
-
-/**
- * rproc_coredump_set_elf_info() - set coredump elf information
- * @rproc: handle of a remote processor
- * @class: elf class for coredump elf file
- * @machine:   elf machine for coredump elf file
- *
- * Set elf information which will be used for coredump elf file.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine)
-{
-   if (class != ELFCLASS64 && class != ELFCLASS32)
-   return -EINVAL;
-
- 

[PATCH v4 2/3] remoteproc: Add inline coredump functionality

2020-05-27 Thread Rishabh Bhatnagar
The current coredump implementation uses vmalloc area to copy
all the segments. But this might put strain on low memory targets
as the firmware size sometimes is in tens of MBs. The situation
becomes worse if there are multiple remote processors undergoing
recovery at the same time. This patch adds inline coredump
functionality that avoids extra memory usage. This requires
recovery to be halted until data is read by userspace and free
function is called.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/qcom_q6v5_mss.c   |   9 +-
 drivers/remoteproc/remoteproc_coredump.c | 162 +++
 include/linux/remoteproc.h   |  21 +++-
 3 files changed, 167 insertions(+), 25 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c 
b/drivers/remoteproc/qcom_q6v5_mss.c
index 38d2b21..a1aea19 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1231,12 +1231,13 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
 
 static void qcom_q6v5_dump_segment(struct rproc *rproc,
   struct rproc_dump_segment *segment,
-  void *dest)
+  void *dest, size_t offset, size_t size)
 {
int ret = 0;
struct q6v5 *qproc = rproc->priv;
unsigned long mask = BIT((unsigned long)segment->priv);
-   void *ptr = rproc_da_to_va(rproc, segment->da, segment->size);
+   size_t copy_size = size ? size : segment->size;
+   void *ptr = rproc_da_to_va(rproc, segment->da + offset, copy_size);
 
/* Unlock mba before copying segments */
if (!qproc->dump_mba_loaded) {
@@ -1251,9 +1252,9 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
}
 
if (!ptr || ret)
-   memset(dest, 0xff, segment->size);
+   memset(dest, 0xff, copy_size);
else
-   memcpy(dest, ptr, segment->size);
+   memcpy(dest, ptr, copy_size);
 
qproc->dump_segment_mask |= mask;
 
diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index ded0244..e643a66 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,12 @@
 #include "remoteproc_internal.h"
 #include "remoteproc_elf_helpers.h"
 
+struct rproc_coredump_state {
+   struct rproc *rproc;
+   void *header;
+   struct completion dump_done;
+};
+
 /**
  * rproc_coredump_cleanup() - clean up dump_segments list
  * @rproc: the remote processor handle
@@ -72,7 +79,8 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
  dma_addr_t da, size_t size,
  void (*dumpfn)(struct rproc *rproc,
 struct rproc_dump_segment 
*segment,
-void *dest),
+void *dest, size_t offset,
+size_t size),
  void *priv)
 {
struct rproc_dump_segment *segment;
@@ -114,12 +122,112 @@ int rproc_coredump_set_elf_info(struct rproc *rproc, u8 
class, u16 machine)
 }
 EXPORT_SYMBOL(rproc_coredump_set_elf_info);
 
+static void rproc_coredump_free(void *data)
+{
+   struct rproc_coredump_state *dump_state = data;
+
+   complete(_state->dump_done);
+   vfree(dump_state->header);
+}
+
+static void *rproc_coredump_find_segment(loff_t user_offset,
+struct list_head *segments,
+size_t *data_left)
+{
+   struct rproc_dump_segment *segment;
+
+   list_for_each_entry(segment, segments, node) {
+   if (user_offset < segment->size) {
+   *data_left = segment->size - user_offset;
+   return segment;
+   }
+   user_offset -= segment->size;
+   }
+
+   *data_left = 0;
+   return NULL;
+}
+
+static void rproc_copy_segment(struct rproc *rproc, void *dest,
+  struct rproc_dump_segment *segment,
+  size_t offset, size_t size)
+{
+   void *ptr;
+
+   if (segment->dump) {
+   segment->dump(rproc, segment, dest, offset, size);
+   } else {
+   ptr = rproc_da_to_va(rproc, segment->da + offset, size);
+   if (!ptr) {
+   dev_err(>dev,
+   "invalid copy request (%zu, %zu)\n",
+   segment->

[PATCH v4 3/3] remoteproc: Add coredump debugfs entry

2020-05-27 Thread Rishabh Bhatnagar
Add coredump debugfs entry to configure the type of dump that will
be collected during recovery. User can select between default or
inline coredump functionality. Also coredump collection can be
disabled through this interface.
This functionality can be configured differently for different
remote processors.

Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Bjorn Andersson 
Reviewed-by: Mathieu Poirier 
---
 drivers/remoteproc/remoteproc_debugfs.c | 86 +
 1 file changed, 86 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..cca0a91 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,6 +28,90 @@
 static struct dentry *rproc_dbg;
 
 /*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via debugfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [RPROC_COREDUMP_DEFAULT]= "default",
+   [RPROC_COREDUMP_INLINE] = "inline",
+   [RPROC_COREDUMP_DISABLED]   = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
+  size_t count, loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   const char *buf = rproc_coredump_str[rproc->dump_conf];
+
+   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+/*
+ * By writing to the 'coredump' debugfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' debugfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ *
+ * disabled:   This will disable coredump. Recovery will proceed without
+ * collecting any dump.
+ */
+static ssize_t rproc_coredump_write(struct file *filp,
+   const char __user *user_buf, size_t count,
+   loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   int ret, err = 0;
+   char buf[20];
+
+   if (count > sizeof(buf))
+   return -EINVAL;
+
+   ret = copy_from_user(buf, user_buf, count);
+   if (ret)
+   return -EFAULT;
+
+   /* remove end of line */
+   if (buf[count - 1] == '\n')
+   buf[count - 1] = '\0';
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   err = -EBUSY;
+   goto out;
+   }
+
+   if (!strncmp(buf, "disable", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DISABLED;
+   } else if (!strncmp(buf, "inline", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_INLINE;
+   } else if (!strncmp(buf, "default", count)) {
+   rproc->dump_conf = RPROC_COREDUMP_DEFAULT;
+   } else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   err = -EINVAL;
+   }
+out:
+   return err ? err : count;
+}
+
+static const struct file_operations rproc_coredump_fops = {
+   .read = rproc_coredump_read,
+   .write = rproc_coredump_write,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
+/*
  * Some remote processors may support dumping trace logs into a shared
  * memory buffer. We expose this trace buffer using debugfs, so users
  * can easily tell what's going on remotely.
@@ -337,6 +421,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+   debugfs_create_file("coredump", 0600, rproc->dbg_dir,
+   rproc, _coredump_fops);
 }
 
 void __init rproc_init_debugfs(void)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v3 1/3] remoteproc: Move coredump functionality to a new file

2020-05-14 Thread Rishabh Bhatnagar
Move all coredump functionality to an individual file. This is
being done so that the current functionality can be extended
in future patchsets.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 -
 drivers/remoteproc/remoteproc_coredump.c | 204 +++
 drivers/remoteproc/remoteproc_internal.h |   4 +
 4 files changed, 209 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 0effd38..f1a33c3 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REMOTEPROC)   += remoteproc.o
 remoteproc-y   := remoteproc_core.o
+remoteproc-y   += remoteproc_coredump.o
 remoteproc-y   += remoteproc_debugfs.o
 remoteproc-y   += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 4bd0f45..22575f4 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -26,7 +26,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -40,7 +39,6 @@
 #include 
 
 #include "remoteproc_internal.h"
-#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xULL
 
@@ -1238,19 +1236,6 @@ static int rproc_alloc_registered_carveouts(struct rproc 
*rproc)
return 0;
 }
 
-/**
- * rproc_coredump_cleanup() - clean up dump_segments list
- * @rproc: the remote processor handle
- */
-static void rproc_coredump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, >dump_segments, node) {
-   list_del(>node);
-   kfree(entry);
-   }
-}
 
 /**
  * rproc_resource_cleanup() - clean up and free all acquired resources
@@ -1509,182 +1494,6 @@ static int rproc_stop(struct rproc *rproc, bool crashed)
return 0;
 }
 
-/**
- * rproc_coredump_add_segment() - add segment of device memory to coredump
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- *
- * Add device memory to the list of segments to be included in a coredump for
- * the remoteproc.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_segment);
-
-/**
- * rproc_coredump_add_custom_segment() - add custom coredump segment
- * @rproc: handle of a remote processor
- * @da:device address
- * @size:  size of segment
- * @dumpfn:custom dump function called for each segment during coredump
- * @priv:  private data
- *
- * Add device memory to the list of segments to be included in the coredump
- * and associate the segment with the given custom dump function and private
- * data.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_add_custom_segment(struct rproc *rproc,
- dma_addr_t da, size_t size,
- void (*dumpfn)(struct rproc *rproc,
-struct rproc_dump_segment 
*segment,
-void *dest),
- void *priv)
-{
-   struct rproc_dump_segment *segment;
-
-   segment = kzalloc(sizeof(*segment), GFP_KERNEL);
-   if (!segment)
-   return -ENOMEM;
-
-   segment->da = da;
-   segment->size = size;
-   segment->priv = priv;
-   segment->dump = dumpfn;
-
-   list_add_tail(>node, >dump_segments);
-
-   return 0;
-}
-EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
-
-/**
- * rproc_coredump_set_elf_info() - set coredump elf information
- * @rproc: handle of a remote processor
- * @class: elf class for coredump elf file
- * @machine:   elf machine for coredump elf file
- *
- * Set elf information which will be used for coredump elf file.
- *
- * Return: 0 on success, negative errno on error.
- */
-int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine)
-{
-   if (class != ELFCLASS64 && class != ELFCLASS32)
-   return -EINVAL;
-
-   rproc->elf_class = class;
-   rproc->elf_machine = mach

[PATCH v3 3/3] remoteproc: Add coredump debugfs entry

2020-05-14 Thread Rishabh Bhatnagar
Add coredump debugfs entry to configure the type of dump that will
be collected during recovery. User can select between default or
inline coredump functionality. Also coredump collection can be
disabled through this interface.
This functionality can be configured differently for different
remote processors.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/remoteproc_debugfs.c | 86 +
 1 file changed, 86 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c 
b/drivers/remoteproc/remoteproc_debugfs.c
index 732770e..2f611de 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -28,6 +28,90 @@
 static struct dentry *rproc_dbg;
 
 /*
+ * A coredump-configuration-to-string lookup table, for exposing a
+ * human readable configuration via debugfs. Always keep in sync with
+ * enum rproc_coredump_mechanism
+ */
+static const char * const rproc_coredump_str[] = {
+   [COREDUMP_DEFAULT]  = "default",
+   [COREDUMP_INLINE]   = "inline",
+   [COREDUMP_DISABLED] = "disabled",
+};
+
+/* Expose the current coredump configuration via debugfs */
+static ssize_t rproc_coredump_read(struct file *filp, char __user *userbuf,
+   size_t count, loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   const char *buf = rproc_coredump_str[rproc->dump_conf];
+
+   return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+/*
+ * By writing to the 'coredump' debugfs entry, we control the behavior of the
+ * coredump mechanism dynamically. The default value of this entry is 
"default".
+ *
+ * The 'coredump' debugfs entry supports these commands:
+ *
+ * default:This is the default coredump mechanism. When the remoteproc
+ * crashes the entire coredump will be copied to a separate buffer
+ * and exposed to userspace.
+ *
+ * inline: The coredump will not be copied to a separate buffer and the
+ * recovery process will have to wait until data is read by
+ * userspace. But this avoid usage of extra memory.
+ *
+ * disabled:   This will disable coredump. Recovery will proceed without
+ * collecting any dump.
+ */
+static ssize_t rproc_coredump_write(struct file *filp,
+const char __user *user_buf, size_t count,
+loff_t *ppos)
+{
+   struct rproc *rproc = filp->private_data;
+   int ret, err = 0;
+   char buf[20];
+
+   if (count > sizeof(buf))
+   return -EINVAL;
+
+   ret = copy_from_user(buf, user_buf, count);
+   if (ret)
+   return -EFAULT;
+
+   /* remove end of line */
+   if (buf[count - 1] == '\n')
+   buf[count - 1] = '\0';
+
+   if (rproc->state == RPROC_CRASHED) {
+   dev_err(>dev, "can't change coredump configuration\n");
+   err = -EBUSY;
+   goto out;
+   }
+
+   if (!strncmp(buf, "disable", count))
+   rproc->dump_conf = COREDUMP_DISABLED;
+   else if (!strncmp(buf, "inline", count))
+   rproc->dump_conf = COREDUMP_INLINE;
+   else if (!strncmp(buf, "default", count))
+   rproc->dump_conf = COREDUMP_DEFAULT;
+   else {
+   dev_err(>dev, "Invalid coredump configuration\n");
+   err = -EINVAL;
+   }
+out:
+   return err ? err : count;
+}
+
+static const struct file_operations rproc_coredump_fops = {
+   .read = rproc_coredump_read,
+   .write = rproc_coredump_write,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
+/*
  * Some remote processors may support dumping trace logs into a shared
  * memory buffer. We expose this trace buffer using debugfs, so users
  * can easily tell what's going on remotely.
@@ -337,6 +421,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
rproc, _rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, _carveouts_fops);
+   debugfs_create_file("coredump", 0600, rproc->dbg_dir,
+   rproc, _coredump_fops);
 }
 
 void __init rproc_init_debugfs(void)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v3 0/3] Extend coredump functionality

2020-05-14 Thread Rishabh Bhatnagar
This patch series moves the coredump functionality to a separate
file and adds "inline" coredump feature. Inline coredump directly
copies segments from device memory during coredump to userspace.
This avoids extra memory usage at the cost of speed. Recovery is
stalled untill all data is read by userspace.

Changelog:

v3 -> v2:
- Move entire coredump functionality to remoteproc_coredump.c
- Modify rproc_coredump to perform dump according to conf. set by userspace
- Move the userspace configuration to debugfs from sysfs.
- Keep the default coredump implementation as is

v2 -> v1:
- Introduce new file for coredump.
- Add userspace sysfs configuration for dump type.

Rishabh Bhatnagar (3):
  remoteproc: Move coredump functionality to a new file
  remoteproc: Add inline coredump functionality
  remoteproc: Add coredump debugfs entry

 drivers/remoteproc/Makefile  |   1 +
 drivers/remoteproc/remoteproc_core.c | 191 --
 drivers/remoteproc/remoteproc_coredump.c | 322 +++
 drivers/remoteproc/remoteproc_debugfs.c  |  86 +
 drivers/remoteproc/remoteproc_internal.h |   4 +
 include/linux/remoteproc.h   |  15 ++
 6 files changed, 428 insertions(+), 191 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_coredump.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v3 2/3] remoteproc: Add inline coredump functionality

2020-05-14 Thread Rishabh Bhatnagar
The current coredump implementation uses vmalloc area to copy
all the segments. But this might put strain on low memory targets
as the firmware size sometimes is in tens of MBs. The situation
becomes worse if there are multiple remote processors undergoing
recovery at the same time. This patch adds inline coredump
functionality that avoids extra memory usage. This requires
recovery to be halted until data is read by userspace and free
function is called.

Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/remoteproc_coredump.c | 129 +--
 include/linux/remoteproc.h   |  15 
 2 files changed, 139 insertions(+), 5 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_coredump.c 
b/drivers/remoteproc/remoteproc_coredump.c
index ded0244..de75e89 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -12,6 +12,12 @@
 #include "remoteproc_internal.h"
 #include "remoteproc_elf_helpers.h"
 
+struct rproc_coredump_state {
+   struct rproc *rproc;
+   void *header;
+   struct completion dump_done;
+};
+
 /**
  * rproc_coredump_cleanup() - clean up dump_segments list
  * @rproc: the remote processor handle
@@ -114,12 +120,96 @@ int rproc_coredump_set_elf_info(struct rproc *rproc, u8 
class, u16 machine)
 }
 EXPORT_SYMBOL(rproc_coredump_set_elf_info);
 
+static void rproc_coredump_free(void *data)
+{
+   struct rproc_coredump_state *dump_state = data;
+
+   complete(_state->dump_done);
+   vfree(dump_state->header);
+}
+
+static unsigned long rproc_coredump_find_segment(loff_t user_offset,
+ struct list_head *segments,
+ size_t *data_left)
+{
+   struct rproc_dump_segment *segment;
+
+   list_for_each_entry(segment, segments, node) {
+   if (user_offset < segment->size) {
+   *data_left = segment->size - user_offset;
+   return segment->da + user_offset;
+   }
+   user_offset -= segment->size;
+   }
+
+   *data_left = 0;
+   return 0;
+}
+
+static ssize_t rproc_coredump_read(char *buffer, loff_t offset, size_t count,
+   void *data, size_t header_sz)
+{
+   void *device_mem;
+   size_t seg_data;
+   size_t copy_sz, bytes_left = count;
+   unsigned long addr;
+   struct rproc_coredump_state *dump_state = data;
+   struct rproc *rproc = dump_state->rproc;
+   void *elfcore = dump_state->header;
+
+   /* Copy the vmalloc'ed header first. */
+   if (offset < header_sz) {
+   copy_sz = memory_read_from_buffer(buffer, count, ,
+ elfcore, header_sz);
+   if (copy_sz < 0)
+   return -EINVAL;
+
+   return copy_sz;
+   }
+
+   /* Find out the segment memory chunk to be copied based on offset.
+* Keep copying data until count bytes are read.
+*/
+   while (bytes_left) {
+   addr = rproc_coredump_find_segment(offset - header_sz,
+  >dump_segments,
+  _data);
+   /* EOF check */
+   if (seg_data == 0) {
+   dev_info(>dev, "Ramdump done, %lld bytes read",
+offset);
+   break;
+   }
+
+   copy_sz = min_t(size_t, bytes_left, seg_data);
+
+   device_mem = rproc_da_to_va(rproc, addr, copy_sz);
+   if (!device_mem) {
+   dev_err(>dev, "Coredump: %lx with size %zd out 
of remoteproc carveout\n",
+   addr, copy_sz);
+   return -ENOMEM;
+   }
+   memcpy(buffer, device_mem, copy_sz);
+
+   offset += copy_sz;
+   buffer += copy_sz;
+   bytes_left -= copy_sz;
+   }
+
+   return count - bytes_left;
+}
+
 /**
  * rproc_coredump() - perform coredump
  * @rproc: rproc handle
  *
  * This function will generate an ELF header for the registered segments
- * and create a devcoredump device associated with rproc.
+ * and create a devcoredump device associated with rproc. Based on the
+ * coredump configuration this function will directly copy the segments
+ * from device memory to userspace or copy segments from device memory to
+ * a separate buffer, which can then be read by userspace.
+ * The first approach avoids using extra vmalloc memory. But it will stall
+ * recovery flow until dump is read by userspace.
  */
 void rproc_coredump(struct rproc *rproc)
 {
@@ -132,8 +222,10 @@ void rproc_coredump(struct rproc *rproc)
void *ptr;
u8 class = rproc

[PATCH] remoteproc: core: Prevent system suspend during remoteproc recovery

2020-04-29 Thread Rishabh Bhatnagar
The system might go into suspend during recovery of any remoteproc.
This will interrupt the recovery process in between increasing the
recovery time. Make the platform device as wakeup capable and
use pm_stay_wake/pm_relax APIs to avoid system from going into
suspend during recovery.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
Acked-by: Mathieu Poirier 
---
 drivers/remoteproc/qcom_q6v5_pas.c   | 2 ++
 drivers/remoteproc/remoteproc_core.c | 5 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/remoteproc/qcom_q6v5_pas.c 
b/drivers/remoteproc/qcom_q6v5_pas.c
index edf9d0e..e608578 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -398,6 +398,8 @@ static int adsp_probe(struct platform_device *pdev)
adsp->has_aggre2_clk = desc->has_aggre2_clk;
platform_set_drvdata(pdev, adsp);
 
+   device_wakeup_enable(adsp->dev);
+
ret = adsp_alloc_memory_region(adsp);
if (ret)
goto free_rproc;
diff --git a/drivers/remoteproc/remoteproc_core.c 
b/drivers/remoteproc/remoteproc_core.c
index 097f33e..6a1cb98 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1712,6 +1712,8 @@ static void rproc_crash_handler_work(struct work_struct 
*work)
 
if (!rproc->recovery_disabled)
rproc_trigger_recovery(rproc);
+
+   pm_relax(rproc->dev.parent);
 }
 
 /**
@@ -2208,6 +2210,9 @@ void rproc_report_crash(struct rproc *rproc, enum 
rproc_crash_type type)
return;
}
 
+   /* Prevent suspend while the remoteproc is being recovered */
+   pm_stay_awake(rproc->dev.parent);
+
dev_err(>dev, "crash detected in %s: type %s\n",
rproc->name, rproc_crash_to_string(type));
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v3 1/2] remoteproc: qcom: Add per subsystem SSR notification

2020-04-28 Thread Rishabh Bhatnagar
Currently there is a single notification chain which is called whenever any
remoteproc shuts down. This leads to all the listeners being notified, and
is not an optimal design as kernel drivers might only be interested in
listening to notifications from a particular remoteproc. Create a global
list of remoteproc notification info data structures. This will hold the
name and notifier_list information for a particular remoteproc. The API
to register for notifications will use name argument to retrieve the
notification info data structure and the notifier block will be added to
that data structure's notification chain.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 89 ++-
 drivers/remoteproc/qcom_common.h  | 10 +++-
 include/linux/remoteproc/qcom_rproc.h | 20 ++--
 3 files changed, 99 insertions(+), 20 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 60650bc..7cd17be 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -15,16 +15,18 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "remoteproc_internal.h"
 #include "qcom_common.h"
 
+#define MAX_NAME_LEN   20
+DEFINE_MUTEX(rproc_notif_lock);
+
 #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
 
-static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
-
 static int glink_subdev_start(struct rproc_subdev *subdev)
 {
struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
@@ -174,39 +176,81 @@ void qcom_remove_smd_subdev(struct rproc *rproc, struct 
qcom_rproc_subdev *smd)
 }
 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
 
+struct rproc_notif_info *find_notif_info(const char *name)
+{
+   struct rproc_notif_info *info;
+
+   /* Match in the global rproc_notif_list with name */
+   list_for_each_entry(info, _notif_list, list) {
+   if (!strncmp(info->name, name, strlen(name)))
+   return info;
+   }
+   return NULL;
+}
+
 /**
  * qcom_register_ssr_notifier() - register SSR notification handler
+ * @name:  pointer to name which will be searched in the global notif_list
  * @nb:notifier_block to notify for restart notifications
  *
- * Returns 0 on success, negative errno on failure.
+ * Returns pointer to srcu notifier head on success, ERR_PTR on failure.
  *
- * This register the @notify function as handler for restart notifications. As
- * remote processors are stopped this function will be called, with the SSR
- * name passed as a parameter.
+ * This registers the @nb notifier block as part the notifier chain for a
+ * remoteproc associated with @name. The notifier block's callback
+ * will be invoked when the particular remote processor is stopped.
  */
-int qcom_register_ssr_notifier(struct notifier_block *nb)
+void *qcom_register_ssr_notifier(const char *name, struct notifier_block *nb)
 {
-   return blocking_notifier_chain_register(_notifiers, nb);
+   struct rproc_notif_info *info;
+
+   mutex_lock(_notif_lock);
+   info = find_notif_info(name);
+   if (!info) {
+   info = kzalloc(sizeof(*info), GFP_KERNEL);
+   if (!info) {
+   mutex_unlock(_notif_lock);
+   return ERR_PTR(-ENOMEM);
+   }
+   info->name = kstrndup(name, MAX_NAME_LEN, GFP_KERNEL);
+   srcu_init_notifier_head(>notifier_list);
+
+   /* Add to global notif list */
+   INIT_LIST_HEAD(>list);
+   list_add_tail(>list, _notif_list);
+   }
+
+   srcu_notifier_chain_register(>notifier_list, nb);
+   mutex_unlock(_notif_lock);
+   return >notifier_list;
 }
 EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier);
 
 /**
  * qcom_unregister_ssr_notifier() - unregister SSR notification handler
+ * @notify:pointer to srcu notifier head
  * @nb:notifier_block to unregister
  */
-void qcom_unregister_ssr_notifier(struct notifier_block *nb)
+int qcom_unregister_ssr_notifier(void *notify, struct notifier_block *nb)
 {
-   blocking_notifier_chain_unregister(_notifiers, nb);
+   if (!notify)
+   return -EINVAL;
+
+   return srcu_notifier_chain_unregister(notify, nb);
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct rproc_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
 
-   blocking_notifier_call_chain(_notifiers, 0, (void *)ssr->name);
+   srcu_notifier_call_chain(>info->notifier_list, 0, );
 }

[PATCH v3 0/2] Extend SSR notifications framework

2020-04-28 Thread Rishabh Bhatnagar
This set of patches gives kernel client drivers the ability to register
for a particular remoteproc's SSR notifications. Also the notifications
are extended to before/after-powerup/shutdown stages.
It also fixes the bug where clients need to register for notifications
again if the platform driver is removed. This is done by creating a
global list of per-remoteproc notification info data structures which
remain static. An API is exported to register for a remoteproc's SSR
notifications and uses remoteproc's ssr_name and notifier block as
arguments. 

Rishabh Bhatnagar (1):
  remoteproc: qcom: Add per subsystem SSR notification

Siddharth Gupta (1):
  remoteproc: qcom: Add notification types to SSR

v3 -> v2:
- Create a global list of per remoteproc notification data structure
- Pass ssr_name and crashed information as part of notification data
- Move notification type enum to qcom_rproc.h from remoteproc.h

v2 -> v1:
- Fix commit text

 drivers/remoteproc/qcom_common.c  | 133 ++
 drivers/remoteproc/qcom_common.h  |  11 ++-
 include/linux/remoteproc/qcom_rproc.h |  34 +++--
 3 files changed, 157 insertions(+), 21 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v3 2/2] remoteproc: qcom: Add notification types to SSR

2020-04-28 Thread Rishabh Bhatnagar
From: Siddharth Gupta 

The SSR subdevice only adds callback for the unprepare event. Add callbacks
for unprepare, start and prepare events. The client driver for a particular
remoteproc might be interested in knowing the status of the remoteproc
while undergoing SSR, not just when the remoteproc has finished shutting
down.

Signed-off-by: Siddharth Gupta 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/remoteproc/qcom_common.c  | 46 +--
 include/linux/remoteproc/qcom_rproc.h | 14 +++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 7cd17be..0d91cf3 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -197,7 +197,7 @@ struct rproc_notif_info *find_notif_info(const char *name)
  *
  * This registers the @nb notifier block as part the notifier chain for a
  * remoteproc associated with @name. The notifier block's callback
- * will be invoked when the particular remote processor is stopped.
+ * will be invoked when the particular remote processor is started/stopped.
  */
 void *qcom_register_ssr_notifier(const char *name, struct notifier_block *nb)
 {
@@ -239,6 +239,44 @@ int qcom_unregister_ssr_notifier(void *notify, struct 
notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 
+static int ssr_notify_prepare(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct rproc_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+RPROC_BEFORE_POWERUP, );
+   return 0;
+}
+
+static int ssr_notify_start(struct rproc_subdev *subdev)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct rproc_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = false,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+RPROC_AFTER_POWERUP, );
+   return 0;
+}
+
+static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed)
+{
+   struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
+   struct rproc_notif_data data = {
+   .name = ssr->info->name,
+   .crashed = crashed,
+   };
+
+   srcu_notifier_call_chain(>info->notifier_list,
+RPROC_BEFORE_SHUTDOWN, );
+}
+
 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 {
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
@@ -247,7 +285,8 @@ static void ssr_notify_unprepare(struct rproc_subdev 
*subdev)
.crashed = false,
};
 
-   srcu_notifier_call_chain(>info->notifier_list, 0, );
+   srcu_notifier_call_chain(>info->notifier_list,
+RPROC_AFTER_SHUTDOWN, );
 }
 
 
@@ -282,6 +321,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct 
qcom_rproc_ssr *ssr,
}
mutex_unlock(_notif_lock);
ssr->info = info;
+   ssr->subdev.prepare = ssr_notify_prepare;
+   ssr->subdev.start = ssr_notify_start;
+   ssr->subdev.stop = ssr_notify_stop;
ssr->subdev.unprepare = ssr_notify_unprepare;
 
rproc_add_subdev(rproc, >subdev);
diff --git a/include/linux/remoteproc/qcom_rproc.h 
b/include/linux/remoteproc/qcom_rproc.h
index 3dc65c0..567c1f9 100644
--- a/include/linux/remoteproc/qcom_rproc.h
+++ b/include/linux/remoteproc/qcom_rproc.h
@@ -5,6 +5,20 @@
 
 #if IS_ENABLED(CONFIG_QCOM_RPROC_COMMON)
 
+/**
+ * enum rproc_notif_type - Different stages of remoteproc notifications
+ * @RPROC_BEFORE_SHUTDOWN: unprepare stage of  remoteproc
+ * @RPROC_AFTER_SHUTDOWN:  stop stage of  remoteproc
+ * @RPROC_BEFORE_POWERUP:  prepare stage of  remoteproc
+ * @RPROC_AFTER_POWERUP:   start stage of  remoteproc
+ */
+enum rproc_notif_type {
+   RPROC_BEFORE_SHUTDOWN,
+   RPROC_AFTER_SHUTDOWN,
+   RPROC_BEFORE_POWERUP,
+   RPROC_AFTER_POWERUP,
+};
+
 struct rproc_notif_data {
const char *name;
bool crashed;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v1] dd: Invoke one probe retry cycle after some initcall levels

2018-08-13 Thread Rishabh Bhatnagar
From: Rishabh Bhatnagar 

Drivers that are registered at an initcall level may have to
wait until late_init before the probe deferral mechanism can
retry their probe functions. It is possible that their
dependencies were resolved much earlier, in some cases even
before the next initcall level. Invoke one probe retry cycle
at every _sync initcall level after subsys initcall, allowing
these drivers to be probed earlier.
To give an example many Qualcomm drivers are dependent on the 
regulator and bus driver. Both the regulator and bus driver 
are probed in the subsys_initcall level. Now the probe of bus 
driver requires regulator to be working. If the probe of bus 
driver happens before regulator, then bus driver's probe will 
be deferred and all other device's probes which depend on bus 
driver will also be deferred.
The impact of this problem is reduced if we have this patch.

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---

Changes since v0:
 * Remove arch_initcall_sync(deferred_probe_initcall) from patch. This is not
   really needed as none of the devices are re-probed in arch_initcall_sync
   level.

 drivers/base/dd.c | 32 ++--
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d72..9aa41aa 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,23 +224,43 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
 }
 
+static void enable_trigger_defer_cycle(void)
+{
+   driver_deferred_probe_enable = true;
+   driver_deferred_probe_trigger();
+   /*
+* Sort as many dependencies as possible before the next initcall
+* level
+*/
+   flush_work(_probe_work);
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
  * We don't want to get in the way when the bulk of drivers are getting probed.
  * Instead, this initcall makes sure that deferred probing is delayed until
- * late_initcall time.
+ * all the registered initcall functions at a particular level are completed.
+ * This function is invoked at every *_initcall_sync level.
  */
 static int deferred_probe_initcall(void)
 {
-   driver_deferred_probe_enable = true;
-   driver_deferred_probe_trigger();
-   /* Sort as many dependencies as possible before exiting initcalls */
-   flush_work(_probe_work);
+   enable_trigger_defer_cycle();
+   driver_deferred_probe_enable = false;
+   return 0;
+}
+subsys_initcall_sync(deferred_probe_initcall);
+fs_initcall_sync(deferred_probe_initcall);
+device_initcall_sync(deferred_probe_initcall);
+
+static int deferred_probe_enable_fn(void)
+{
+   /* Enable deferred probing for all time */
+   enable_trigger_defer_cycle();
initcalls_done = true;
return 0;
 }
-late_initcall(deferred_probe_initcall);
+late_initcall(deferred_probe_enable_fn);
 
 /**
  * device_is_bound() - Check if device is bound to a driver
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v1] dd: Invoke one probe retry cycle after some initcall levels

2018-08-13 Thread Rishabh Bhatnagar
From: Rishabh Bhatnagar 

Drivers that are registered at an initcall level may have to
wait until late_init before the probe deferral mechanism can
retry their probe functions. It is possible that their
dependencies were resolved much earlier, in some cases even
before the next initcall level. Invoke one probe retry cycle
at every _sync initcall level after subsys initcall, allowing
these drivers to be probed earlier.
To give an example many Qualcomm drivers are dependent on the 
regulator and bus driver. Both the regulator and bus driver 
are probed in the subsys_initcall level. Now the probe of bus 
driver requires regulator to be working. If the probe of bus 
driver happens before regulator, then bus driver's probe will 
be deferred and all other device's probes which depend on bus 
driver will also be deferred.
The impact of this problem is reduced if we have this patch.

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---

Changes since v0:
 * Remove arch_initcall_sync(deferred_probe_initcall) from patch. This is not
   really needed as none of the devices are re-probed in arch_initcall_sync
   level.

 drivers/base/dd.c | 32 ++--
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d72..9aa41aa 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,23 +224,43 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
 }
 
+static void enable_trigger_defer_cycle(void)
+{
+   driver_deferred_probe_enable = true;
+   driver_deferred_probe_trigger();
+   /*
+* Sort as many dependencies as possible before the next initcall
+* level
+*/
+   flush_work(_probe_work);
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
  * We don't want to get in the way when the bulk of drivers are getting probed.
  * Instead, this initcall makes sure that deferred probing is delayed until
- * late_initcall time.
+ * all the registered initcall functions at a particular level are completed.
+ * This function is invoked at every *_initcall_sync level.
  */
 static int deferred_probe_initcall(void)
 {
-   driver_deferred_probe_enable = true;
-   driver_deferred_probe_trigger();
-   /* Sort as many dependencies as possible before exiting initcalls */
-   flush_work(_probe_work);
+   enable_trigger_defer_cycle();
+   driver_deferred_probe_enable = false;
+   return 0;
+}
+subsys_initcall_sync(deferred_probe_initcall);
+fs_initcall_sync(deferred_probe_initcall);
+device_initcall_sync(deferred_probe_initcall);
+
+static int deferred_probe_enable_fn(void)
+{
+   /* Enable deferred probing for all time */
+   enable_trigger_defer_cycle();
initcalls_done = true;
return 0;
 }
-late_initcall(deferred_probe_initcall);
+late_initcall(deferred_probe_enable_fn);
 
 /**
  * device_is_bound() - Check if device is bound to a driver
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v1] dd: Invoke one probe retry cycle after some initcall levels

2018-08-10 Thread Rishabh Bhatnagar
Drivers that are registered at an initcall level may have to
wait until late_init before the probe deferral mechanism can
retry their probe functions. It is possible that their
dependencies were resolved much earlier, in some cases even
before the next initcall level. Invoke one probe retry cycle
at every _sync initcall level after subsys initcall, allowing
these drivers to be probed earlier.

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---

To give an example many Qualcomm drivers are dependent on the regulator and 
bus driver. Both the regulator and bus driver are probed in the 
subsys_initcall level. Now the probe of bus driver requires regulator to be 
working. If the probe of bus driver happens before regulator, then bus 
driver's probe will be deferred and all other device's probes which depend 
on bus driver will also be deferred. 
The impact of this problem is reduced if we have this patch.

Changes since v0:
* Remove arch_initcall_sync(deferred_probe_initcall) from patch. This is not
  really needed as none of the devices are re-probed in arch_initcall_sync
  level.

 drivers/base/dd.c | 32 ++--
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d72..9aa41aa 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,23 +224,43 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
 }
 
+static void enable_trigger_defer_cycle(void)
+{
+   driver_deferred_probe_enable = true;
+   driver_deferred_probe_trigger();
+   /*
+* Sort as many dependencies as possible before the next initcall
+* level
+*/
+   flush_work(_probe_work);
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
  * We don't want to get in the way when the bulk of drivers are getting probed.
  * Instead, this initcall makes sure that deferred probing is delayed until
- * late_initcall time.
+ * all the registered initcall functions at a particular level are completed.
+ * This function is invoked at every *_initcall_sync level.
  */
 static int deferred_probe_initcall(void)
 {
-   driver_deferred_probe_enable = true;
-   driver_deferred_probe_trigger();
-   /* Sort as many dependencies as possible before exiting initcalls */
-   flush_work(_probe_work);
+   enable_trigger_defer_cycle();
+   driver_deferred_probe_enable = false;
+   return 0;
+}
+subsys_initcall_sync(deferred_probe_initcall);
+fs_initcall_sync(deferred_probe_initcall);
+device_initcall_sync(deferred_probe_initcall);
+
+static int deferred_probe_enable_fn(void)
+{
+   /* Enable deferred probing for all time */
+   enable_trigger_defer_cycle();
initcalls_done = true;
return 0;
 }
-late_initcall(deferred_probe_initcall);
+late_initcall(deferred_probe_enable_fn);
 
 /**
  * device_is_bound() - Check if device is bound to a driver
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v1] dd: Invoke one probe retry cycle after some initcall levels

2018-08-10 Thread Rishabh Bhatnagar
Drivers that are registered at an initcall level may have to
wait until late_init before the probe deferral mechanism can
retry their probe functions. It is possible that their
dependencies were resolved much earlier, in some cases even
before the next initcall level. Invoke one probe retry cycle
at every _sync initcall level after subsys initcall, allowing
these drivers to be probed earlier.

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---

To give an example many Qualcomm drivers are dependent on the regulator and 
bus driver. Both the regulator and bus driver are probed in the 
subsys_initcall level. Now the probe of bus driver requires regulator to be 
working. If the probe of bus driver happens before regulator, then bus 
driver's probe will be deferred and all other device's probes which depend 
on bus driver will also be deferred. 
The impact of this problem is reduced if we have this patch.

Changes since v0:
* Remove arch_initcall_sync(deferred_probe_initcall) from patch. This is not
  really needed as none of the devices are re-probed in arch_initcall_sync
  level.

 drivers/base/dd.c | 32 ++--
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d72..9aa41aa 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,23 +224,43 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
 }
 
+static void enable_trigger_defer_cycle(void)
+{
+   driver_deferred_probe_enable = true;
+   driver_deferred_probe_trigger();
+   /*
+* Sort as many dependencies as possible before the next initcall
+* level
+*/
+   flush_work(_probe_work);
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
  * We don't want to get in the way when the bulk of drivers are getting probed.
  * Instead, this initcall makes sure that deferred probing is delayed until
- * late_initcall time.
+ * all the registered initcall functions at a particular level are completed.
+ * This function is invoked at every *_initcall_sync level.
  */
 static int deferred_probe_initcall(void)
 {
-   driver_deferred_probe_enable = true;
-   driver_deferred_probe_trigger();
-   /* Sort as many dependencies as possible before exiting initcalls */
-   flush_work(_probe_work);
+   enable_trigger_defer_cycle();
+   driver_deferred_probe_enable = false;
+   return 0;
+}
+subsys_initcall_sync(deferred_probe_initcall);
+fs_initcall_sync(deferred_probe_initcall);
+device_initcall_sync(deferred_probe_initcall);
+
+static int deferred_probe_enable_fn(void)
+{
+   /* Enable deferred probing for all time */
+   enable_trigger_defer_cycle();
initcalls_done = true;
return 0;
 }
-late_initcall(deferred_probe_initcall);
+late_initcall(deferred_probe_enable_fn);
 
 /**
  * device_is_bound() - Check if device is bound to a driver
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] firmware: Fix security issue with request_firmware_into_buf()

2018-08-01 Thread Rishabh Bhatnagar
When calling request_firmware_into_buf() with the FW_OPT_NOCACHE flag
it is expected that firmware is loaded into buffer from memory.
But inside alloc_lookup_fw_priv every new firmware that is loaded is
added to the firmware cache (fwc) list head. So if any driver requests
a firmware that is already loaded the code iterates over the above
mentioned list and it can end up giving a pointer to other device driver's
firmware buffer.
Also the existing copy may either be modified by drivers, remote processors
or even freed. This causes a potential security issue with batched requests
when using request_firmware_into_buf.

Fix alloc_lookup_fw_priv to not add to the fwc head list if FW_OPT_NOCACHE
is set, and also don't do the lookup in the list.

Fixes: 0e742e9275 ("firmware: provide infrastructure to make fw caching 
optional")

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/base/firmware_loader/main.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/base/firmware_loader/main.c 
b/drivers/base/firmware_loader/main.c
index 0943e70..b3c0498 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -209,21 +209,24 @@ static struct fw_priv *__lookup_fw_priv(const char 
*fw_name)
 static int alloc_lookup_fw_priv(const char *fw_name,
struct firmware_cache *fwc,
struct fw_priv **fw_priv, void *dbuf,
-   size_t size)
+   size_t size, enum fw_opt opt_flags)
 {
struct fw_priv *tmp;
 
spin_lock(>lock);
-   tmp = __lookup_fw_priv(fw_name);
-   if (tmp) {
-   kref_get(>ref);
-   spin_unlock(>lock);
-   *fw_priv = tmp;
-   pr_debug("batched request - sharing the same struct fw_priv and 
lookup for multiple requests\n");
-   return 1;
+   if (!(opt_flags & FW_OPT_NOCACHE)) {
+   tmp = __lookup_fw_priv(fw_name);
+   if (tmp) {
+   kref_get(>ref);
+   spin_unlock(>lock);
+   *fw_priv = tmp;
+   pr_debug("batched request - sharing the same struct 
fw_priv and lookup for multiple requests\n");
+   return 1;
+   }
}
+
tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size);
-   if (tmp)
+   if (tmp && !(opt_flags & FW_OPT_NOCACHE))
list_add(>list, >head);
spin_unlock(>lock);
 
@@ -493,7 +496,8 @@ int assign_fw(struct firmware *fw, struct device *device,
  */
 static int
 _request_firmware_prepare(struct firmware **firmware_p, const char *name,
- struct device *device, void *dbuf, size_t size)
+ struct device *device, void *dbuf, size_t size,
+ enum fw_opt opt_flags)
 {
struct firmware *firmware;
struct fw_priv *fw_priv;
@@ -511,7 +515,8 @@ int assign_fw(struct firmware *fw, struct device *device,
return 0; /* assigned */
}
 
-   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size);
+   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size,
+ opt_flags);
 
/*
 * bind with 'priv' now to avoid warning in failure path
@@ -571,7 +576,8 @@ static void fw_abort_batch_reqs(struct firmware *fw)
goto out;
}
 
-   ret = _request_firmware_prepare(, name, device, buf, size);
+   ret = _request_firmware_prepare(, name, device, buf, size,
+   opt_flags);
if (ret <= 0) /* error or already assigned */
goto out;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] firmware: Fix security issue with request_firmware_into_buf()

2018-08-01 Thread Rishabh Bhatnagar
When calling request_firmware_into_buf() with the FW_OPT_NOCACHE flag
it is expected that firmware is loaded into buffer from memory.
But inside alloc_lookup_fw_priv every new firmware that is loaded is
added to the firmware cache (fwc) list head. So if any driver requests
a firmware that is already loaded the code iterates over the above
mentioned list and it can end up giving a pointer to other device driver's
firmware buffer.
Also the existing copy may either be modified by drivers, remote processors
or even freed. This causes a potential security issue with batched requests
when using request_firmware_into_buf.

Fix alloc_lookup_fw_priv to not add to the fwc head list if FW_OPT_NOCACHE
is set, and also don't do the lookup in the list.

Fixes: 0e742e9275 ("firmware: provide infrastructure to make fw caching 
optional")

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/base/firmware_loader/main.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/base/firmware_loader/main.c 
b/drivers/base/firmware_loader/main.c
index 0943e70..b3c0498 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -209,21 +209,24 @@ static struct fw_priv *__lookup_fw_priv(const char 
*fw_name)
 static int alloc_lookup_fw_priv(const char *fw_name,
struct firmware_cache *fwc,
struct fw_priv **fw_priv, void *dbuf,
-   size_t size)
+   size_t size, enum fw_opt opt_flags)
 {
struct fw_priv *tmp;
 
spin_lock(>lock);
-   tmp = __lookup_fw_priv(fw_name);
-   if (tmp) {
-   kref_get(>ref);
-   spin_unlock(>lock);
-   *fw_priv = tmp;
-   pr_debug("batched request - sharing the same struct fw_priv and 
lookup for multiple requests\n");
-   return 1;
+   if (!(opt_flags & FW_OPT_NOCACHE)) {
+   tmp = __lookup_fw_priv(fw_name);
+   if (tmp) {
+   kref_get(>ref);
+   spin_unlock(>lock);
+   *fw_priv = tmp;
+   pr_debug("batched request - sharing the same struct 
fw_priv and lookup for multiple requests\n");
+   return 1;
+   }
}
+
tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size);
-   if (tmp)
+   if (tmp && !(opt_flags & FW_OPT_NOCACHE))
list_add(>list, >head);
spin_unlock(>lock);
 
@@ -493,7 +496,8 @@ int assign_fw(struct firmware *fw, struct device *device,
  */
 static int
 _request_firmware_prepare(struct firmware **firmware_p, const char *name,
- struct device *device, void *dbuf, size_t size)
+ struct device *device, void *dbuf, size_t size,
+ enum fw_opt opt_flags)
 {
struct firmware *firmware;
struct fw_priv *fw_priv;
@@ -511,7 +515,8 @@ int assign_fw(struct firmware *fw, struct device *device,
return 0; /* assigned */
}
 
-   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size);
+   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size,
+ opt_flags);
 
/*
 * bind with 'priv' now to avoid warning in failure path
@@ -571,7 +576,8 @@ static void fw_abort_batch_reqs(struct firmware *fw)
goto out;
}
 
-   ret = _request_firmware_prepare(, name, device, buf, size);
+   ret = _request_firmware_prepare(, name, device, buf, size,
+   opt_flags);
if (ret <= 0) /* error or already assigned */
goto out;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] firmware: Avoid caching firmware when FW_OPT_NOCACHE is set

2018-07-19 Thread Rishabh Bhatnagar
When calling request_firmware_into_buf(), we pass the FW_OPT_NOCACHE
flag with the intent of skipping the caching mechanism of the
firmware loader. Unfortunately, that doesn't work, because
alloc_lookup_fw_priv() isn't told to _not_ add the struct
firmware_buf to the firmware cache (fwc) list. So when we call
request_firmware_into_buf() the second time, we find the buffer in
the cache and return it immediately without reloading.

This may break users of request_firmware_into_buf that are expecting
a fresh copy of the firmware to be reloaded into memory. The existing
copy may either be modified by drivers, remote processors or even
freed. Fix fw_lookup_and_allocate_buf to not add to the fwc list
if FW_OPT_NOCACHE is set, and also don't do the lookup in the list.

Fixes: 0e742e9271 ("firmware: provide infrastructure to make fw caching 
optional")

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/base/firmware_loader/main.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/base/firmware_loader/main.c 
b/drivers/base/firmware_loader/main.c
index 2e0c37a..db9038c0 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -210,21 +210,24 @@ static struct fw_priv *__lookup_fw_priv(const char 
*fw_name)
 static int alloc_lookup_fw_priv(const char *fw_name,
struct firmware_cache *fwc,
struct fw_priv **fw_priv, void *dbuf,
-   size_t size)
+   size_t size, enum fw_opt opt_flags)
 {
struct fw_priv *tmp;
 
spin_lock(>lock);
-   tmp = __lookup_fw_priv(fw_name);
-   if (tmp) {
-   kref_get(>ref);
-   spin_unlock(>lock);
-   *fw_priv = tmp;
-   pr_debug("batched request - sharing the same struct fw_priv and 
lookup for multiple requests\n");
-   return 1;
+   if (!(opt_flags & FW_OPT_NOCACHE)) {
+   tmp = __lookup_fw_priv(fw_name);
+   if (tmp) {
+   kref_get(>ref);
+   spin_unlock(>lock);
+   *fw_priv = tmp;
+   pr_debug("batched request - sharing the same struct 
fw_priv and lookup for multiple requests\n");
+   return 1;
+   }
}
+
tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size);
-   if (tmp)
+   if (tmp && !(opt_flags & FW_OPT_NOCACHE))
list_add(>list, >head);
spin_unlock(>lock);
 
@@ -500,7 +503,8 @@ int assign_fw(struct firmware *fw, struct device *device,
  */
 static int
 _request_firmware_prepare(struct firmware **firmware_p, const char *name,
- struct device *device, void *dbuf, size_t size)
+ struct device *device, void *dbuf, size_t size,
+ enum fw_opt opt_flags)
 {
struct firmware *firmware;
struct fw_priv *fw_priv;
@@ -518,7 +522,8 @@ int assign_fw(struct firmware *fw, struct device *device,
return 0; /* assigned */
}
 
-   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size);
+   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size,
+ opt_flags);
 
/*
 * bind with 'priv' now to avoid warning in failure path
@@ -578,7 +583,8 @@ static void fw_abort_batch_reqs(struct firmware *fw)
goto out;
}
 
-   ret = _request_firmware_prepare(, name, device, buf, size);
+   ret = _request_firmware_prepare(, name, device, buf, size,
+   opt_flags);
if (ret <= 0) /* error or already assigned */
goto out;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] firmware: Avoid caching firmware when FW_OPT_NOCACHE is set

2018-07-19 Thread Rishabh Bhatnagar
When calling request_firmware_into_buf(), we pass the FW_OPT_NOCACHE
flag with the intent of skipping the caching mechanism of the
firmware loader. Unfortunately, that doesn't work, because
alloc_lookup_fw_priv() isn't told to _not_ add the struct
firmware_buf to the firmware cache (fwc) list. So when we call
request_firmware_into_buf() the second time, we find the buffer in
the cache and return it immediately without reloading.

This may break users of request_firmware_into_buf that are expecting
a fresh copy of the firmware to be reloaded into memory. The existing
copy may either be modified by drivers, remote processors or even
freed. Fix fw_lookup_and_allocate_buf to not add to the fwc list
if FW_OPT_NOCACHE is set, and also don't do the lookup in the list.

Fixes: 0e742e9271 ("firmware: provide infrastructure to make fw caching 
optional")

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/base/firmware_loader/main.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/base/firmware_loader/main.c 
b/drivers/base/firmware_loader/main.c
index 2e0c37a..db9038c0 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -210,21 +210,24 @@ static struct fw_priv *__lookup_fw_priv(const char 
*fw_name)
 static int alloc_lookup_fw_priv(const char *fw_name,
struct firmware_cache *fwc,
struct fw_priv **fw_priv, void *dbuf,
-   size_t size)
+   size_t size, enum fw_opt opt_flags)
 {
struct fw_priv *tmp;
 
spin_lock(>lock);
-   tmp = __lookup_fw_priv(fw_name);
-   if (tmp) {
-   kref_get(>ref);
-   spin_unlock(>lock);
-   *fw_priv = tmp;
-   pr_debug("batched request - sharing the same struct fw_priv and 
lookup for multiple requests\n");
-   return 1;
+   if (!(opt_flags & FW_OPT_NOCACHE)) {
+   tmp = __lookup_fw_priv(fw_name);
+   if (tmp) {
+   kref_get(>ref);
+   spin_unlock(>lock);
+   *fw_priv = tmp;
+   pr_debug("batched request - sharing the same struct 
fw_priv and lookup for multiple requests\n");
+   return 1;
+   }
}
+
tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size);
-   if (tmp)
+   if (tmp && !(opt_flags & FW_OPT_NOCACHE))
list_add(>list, >head);
spin_unlock(>lock);
 
@@ -500,7 +503,8 @@ int assign_fw(struct firmware *fw, struct device *device,
  */
 static int
 _request_firmware_prepare(struct firmware **firmware_p, const char *name,
- struct device *device, void *dbuf, size_t size)
+ struct device *device, void *dbuf, size_t size,
+ enum fw_opt opt_flags)
 {
struct firmware *firmware;
struct fw_priv *fw_priv;
@@ -518,7 +522,8 @@ int assign_fw(struct firmware *fw, struct device *device,
return 0; /* assigned */
}
 
-   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size);
+   ret = alloc_lookup_fw_priv(name, _cache, _priv, dbuf, size,
+ opt_flags);
 
/*
 * bind with 'priv' now to avoid warning in failure path
@@ -578,7 +583,8 @@ static void fw_abort_batch_reqs(struct firmware *fw)
goto out;
}
 
-   ret = _request_firmware_prepare(, name, device, buf, size);
+   ret = _request_firmware_prepare(, name, device, buf, size,
+   opt_flags);
if (ret <= 0) /* error or already assigned */
goto out;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] dd: Invoke one probe retry cycle after every initcall level

2018-07-19 Thread Rishabh Bhatnagar
Drivers that are registered at an initcall level may have to
wait until late_init before the probe deferral mechanism can
retry their probe functions. It is possible that their
dependencies were resolved much earlier, in some cases even
before the next initcall level. Invoke one probe retry cycle
at every _sync initcall level, allowing these drivers to be
probed earlier.

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/base/dd.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d72..e6a6821 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,23 +224,44 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
 }
 
+static void enable_trigger_defer_cycle(void)
+{
+   driver_deferred_probe_enable = true;
+   driver_deferred_probe_trigger();
+   /*
+* Sort as many dependencies as possible before the next initcall
+* level
+*/
+   flush_work(_probe_work);
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
  * We don't want to get in the way when the bulk of drivers are getting probed.
  * Instead, this initcall makes sure that deferred probing is delayed until
- * late_initcall time.
+ * all the registered initcall functions at a particular level are completed.
+ * This function is invoked at every *_initcall_sync level.
  */
 static int deferred_probe_initcall(void)
 {
-   driver_deferred_probe_enable = true;
-   driver_deferred_probe_trigger();
-   /* Sort as many dependencies as possible before exiting initcalls */
-   flush_work(_probe_work);
+   enable_trigger_defer_cycle();
+   driver_deferred_probe_enable = false;
+   return 0;
+}
+arch_initcall_sync(deferred_probe_initcall);
+subsys_initcall_sync(deferred_probe_initcall);
+fs_initcall_sync(deferred_probe_initcall);
+device_initcall_sync(deferred_probe_initcall);
+
+static int deferred_probe_enable_fn(void)
+{
+   /* Enable deferred probing for all time */
+   enable_trigger_defer_cycle();
initcalls_done = true;
return 0;
 }
-late_initcall(deferred_probe_initcall);
+late_initcall(deferred_probe_enable_fn);
 
 /**
  * device_is_bound() - Check if device is bound to a driver
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] dd: Invoke one probe retry cycle after every initcall level

2018-07-19 Thread Rishabh Bhatnagar
Drivers that are registered at an initcall level may have to
wait until late_init before the probe deferral mechanism can
retry their probe functions. It is possible that their
dependencies were resolved much earlier, in some cases even
before the next initcall level. Invoke one probe retry cycle
at every _sync initcall level, allowing these drivers to be
probed earlier.

Signed-off-by: Vikram Mulukutla 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/base/dd.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d72..e6a6821 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,23 +224,44 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
 }
 
+static void enable_trigger_defer_cycle(void)
+{
+   driver_deferred_probe_enable = true;
+   driver_deferred_probe_trigger();
+   /*
+* Sort as many dependencies as possible before the next initcall
+* level
+*/
+   flush_work(_probe_work);
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
  * We don't want to get in the way when the bulk of drivers are getting probed.
  * Instead, this initcall makes sure that deferred probing is delayed until
- * late_initcall time.
+ * all the registered initcall functions at a particular level are completed.
+ * This function is invoked at every *_initcall_sync level.
  */
 static int deferred_probe_initcall(void)
 {
-   driver_deferred_probe_enable = true;
-   driver_deferred_probe_trigger();
-   /* Sort as many dependencies as possible before exiting initcalls */
-   flush_work(_probe_work);
+   enable_trigger_defer_cycle();
+   driver_deferred_probe_enable = false;
+   return 0;
+}
+arch_initcall_sync(deferred_probe_initcall);
+subsys_initcall_sync(deferred_probe_initcall);
+fs_initcall_sync(deferred_probe_initcall);
+device_initcall_sync(deferred_probe_initcall);
+
+static int deferred_probe_enable_fn(void)
+{
+   /* Enable deferred probing for all time */
+   enable_trigger_defer_cycle();
initcalls_done = true;
return 0;
 }
-late_initcall(deferred_probe_initcall);
+late_initcall(deferred_probe_enable_fn);
 
 /**
  * device_is_bound() - Check if device is bound to a driver
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] lib: rhashtable: Correct self-assignment in rhashtable.c

2018-07-01 Thread Rishabh Bhatnagar
In file lib/rhashtable.c line 777, skip variable is assigned to
itself. The following error was observed:

lib/rhashtable.c:777:41: warning: explicitly assigning value of
variable of type 'int' to itself [-Wself-assign] error, forbidden
warning: rhashtable.c:777
This error was found when compiling with Clang 6.0. Change it to iter->skip.

Change-Id: I5abd1ce5ba76737a73bd6eca94b07b1bd5267523
Signed-off-by: Rishabh Bhatnagar 
---
 lib/rhashtable.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 9427b57..3109b2e 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -774,7 +774,7 @@ int rhashtable_walk_start_check(struct rhashtable_iter 
*iter)
skip++;
if (list == iter->list) {
iter->p = p;
-   skip = skip;
+   iter->skip = skip;
goto found;
}
}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] lib: rhashtable: Correct self-assignment in rhashtable.c

2018-07-01 Thread Rishabh Bhatnagar
In file lib/rhashtable.c line 777, skip variable is assigned to
itself. The following error was observed:

lib/rhashtable.c:777:41: warning: explicitly assigning value of
variable of type 'int' to itself [-Wself-assign] error, forbidden
warning: rhashtable.c:777
This error was found when compiling with Clang 6.0. Change it to iter->skip.

Change-Id: I5abd1ce5ba76737a73bd6eca94b07b1bd5267523
Signed-off-by: Rishabh Bhatnagar 
---
 lib/rhashtable.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 9427b57..3109b2e 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -774,7 +774,7 @@ int rhashtable_walk_start_check(struct rhashtable_iter 
*iter)
skip++;
if (list == iter->list) {
iter->p = p;
-   skip = skip;
+   iter->skip = skip;
goto found;
}
}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 0/2] SDM845 System Cache Driver

2018-05-23 Thread Rishabh Bhatnagar
This series implements system cache or LLCC(Last Level Cache Controller)
driver for SDM845 SOC. The purpose of the driver is to partition the
system cache and program the settings such as priortiy, lines to probe
while doing a look up in the system cache, low power related settings etc.
The partitions are called cache slices. Each cache slice is associated
with size and SCID(System Cache ID). The driver also provides API for
clients to query the cache slice details,activate and deactivate them.

The driver can be broadly classified into:
* SOC specific driver: llcc-sdm845.c: Cache partitioning and cache slice
properties for usecases on sdm845 that need to use system cache.

* API : llcc-slice.c: Exports APIs to clients to query cache slice details,
activate and deactivate cache slices.

Changes since v7:
* Change the DT node name to cache-controller.
* Use the module_platform_driver_macro
* Use GENMASK and SZ_* macros
* Correct indentation, and remove unnecessary assignemnts.
* Addresed all comments by Andy Schevchenko except the comment to ignore some
  lines of code going over 80 characters.

Changes since v6:
* Remove the max-slices property from DT.
* Make client's slice_ids as macros.
* Unlock mutex while returning from function in case of error.

Changes since v5:
* Remove client information from DT.
* Make the llcc driver data as global.
* Check return value of llcc_update_act_ctrl function
* Change error returned from -EFAULT to -EINVAL

Changes since v4:
* Remove null pointer checks as per comments.
* Remove extra blank lines.

Changes since v3:
* Use the regmap_read_poll_timeout function
* Check for regmap read/write errors.
* Remove memory barrier after regmap write
* Derive memory bank offsets using stride macro variable
* Remove debug statements from code
* Remove the qcom_llcc_remove function
* Use if IS_ENABLED in place of ifdef for built-in module
* Change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
* Remove unnecessary free functions
* Change the variable names as per review comments

Changes since v2:
* Corrected the Makefile to fix compilation.

Changes since v1:
* Added Makefile and Kconfig.

Changes since v0:
* Removed the syscon and simple-mfd approach
* Updated the device tree nodes to mention LLCC as a single HW block
* Moved llcc bank offsets from device tree and handled the offset
  in the driver.

ckad...@codeaurora.org (2):
  dt-bindings: Documentation for qcom, llcc
  drivers: soc: Add LLCC driver

 .../devicetree/bindings/arm/msm/qcom,llcc.txt  |  26 ++
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c |  94 ++
 drivers/soc/qcom/llcc-slice.c  | 335 +
 include/linux/soc/qcom/llcc-qcom.h | 180 +++
 6 files changed, 654 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 0/2] SDM845 System Cache Driver

2018-05-23 Thread Rishabh Bhatnagar
This series implements system cache or LLCC(Last Level Cache Controller)
driver for SDM845 SOC. The purpose of the driver is to partition the
system cache and program the settings such as priortiy, lines to probe
while doing a look up in the system cache, low power related settings etc.
The partitions are called cache slices. Each cache slice is associated
with size and SCID(System Cache ID). The driver also provides API for
clients to query the cache slice details,activate and deactivate them.

The driver can be broadly classified into:
* SOC specific driver: llcc-sdm845.c: Cache partitioning and cache slice
properties for usecases on sdm845 that need to use system cache.

* API : llcc-slice.c: Exports APIs to clients to query cache slice details,
activate and deactivate cache slices.

Changes since v7:
* Change the DT node name to cache-controller.
* Use the module_platform_driver_macro
* Use GENMASK and SZ_* macros
* Correct indentation, and remove unnecessary assignemnts.
* Addresed all comments by Andy Schevchenko except the comment to ignore some
  lines of code going over 80 characters.

Changes since v6:
* Remove the max-slices property from DT.
* Make client's slice_ids as macros.
* Unlock mutex while returning from function in case of error.

Changes since v5:
* Remove client information from DT.
* Make the llcc driver data as global.
* Check return value of llcc_update_act_ctrl function
* Change error returned from -EFAULT to -EINVAL

Changes since v4:
* Remove null pointer checks as per comments.
* Remove extra blank lines.

Changes since v3:
* Use the regmap_read_poll_timeout function
* Check for regmap read/write errors.
* Remove memory barrier after regmap write
* Derive memory bank offsets using stride macro variable
* Remove debug statements from code
* Remove the qcom_llcc_remove function
* Use if IS_ENABLED in place of ifdef for built-in module
* Change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
* Remove unnecessary free functions
* Change the variable names as per review comments

Changes since v2:
* Corrected the Makefile to fix compilation.

Changes since v1:
* Added Makefile and Kconfig.

Changes since v0:
* Removed the syscon and simple-mfd approach
* Updated the device tree nodes to mention LLCC as a single HW block
* Moved llcc bank offsets from device tree and handled the offset
  in the driver.

ckad...@codeaurora.org (2):
  dt-bindings: Documentation for qcom, llcc
  drivers: soc: Add LLCC driver

 .../devicetree/bindings/arm/msm/qcom,llcc.txt  |  26 ++
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c |  94 ++
 drivers/soc/qcom/llcc-slice.c  | 335 +
 include/linux/soc/qcom/llcc-qcom.h | 180 +++
 6 files changed, 654 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 1/2] dt-bindings: Documentation for qcom, llcc

2018-05-23 Thread Rishabh Bhatnagar
Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi <ckad...@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
Reviewed-by: Evan Green <evgr...@chromium.org>
Reviewed-by: Rob Herring <r...@kernel.org>
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt  | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 000..5e85749
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,26 @@
+== Introduction==
+
+LLCC (Last Level Cache Controller) provides last level of cache memory in SOC,
+that can be shared by multiple clients. Clients here are different cores in the
+SOC, the idea is to minimize the local caches at the clients and migrate to
+common pool of memory. Cache memory is divided into partitions called slices
+which are assigned to clients. Clients can query the slice details, activate
+and deactivate them.
+
+Properties:
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,sdm845-llcc"
+
+- reg:
+   Usage: required
+   Value Type: 
+   Definition: Start address and the the size of the register region.
+
+Example:
+
+   cache-controller@110 {
+   compatible = "qcom,sdm845-llcc";
+   reg = <0x110 0x25>;
+   };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 1/2] dt-bindings: Documentation for qcom, llcc

2018-05-23 Thread Rishabh Bhatnagar
Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi 
Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Evan Green 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt  | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 000..5e85749
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,26 @@
+== Introduction==
+
+LLCC (Last Level Cache Controller) provides last level of cache memory in SOC,
+that can be shared by multiple clients. Clients here are different cores in the
+SOC, the idea is to minimize the local caches at the clients and migrate to
+common pool of memory. Cache memory is divided into partitions called slices
+which are assigned to clients. Clients can query the slice details, activate
+and deactivate them.
+
+Properties:
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,sdm845-llcc"
+
+- reg:
+   Usage: required
+   Value Type: 
+   Definition: Start address and the the size of the register region.
+
+Example:
+
+   cache-controller@110 {
+   compatible = "qcom,sdm845-llcc";
+   reg = <0x110 0x25>;
+   };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v8 2/2] drivers: soc: Add LLCC driver

2018-05-23 Thread Rishabh Bhatnagar
LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into multiple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice they get and activate or deactivate the slice as needed. LLCC driver
provides API for the clients to perform these operations.

Signed-off-by: Channagoud Kadabi <ckad...@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
Reviewed-by: Evan Green <evgr...@chromium.org>
Reviewed-by: Rob Herring <r...@kernel.org>
---
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c |  94 +++
 drivers/soc/qcom/llcc-slice.c  | 335 +
 include/linux/soc/qcom/llcc-qcom.h | 180 
 5 files changed, 628 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e050eb8..0b550f9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -21,6 +21,23 @@ config QCOM_GSBI
   functions for connecting the underlying serial UART, SPI, and I2C
   devices to the output pins.
 
+config QCOM_LLCC
+   tristate "Qualcomm Technologies, Inc. LLCC driver"
+   depends on ARCH_QCOM
+   help
+ Qualcomm Technologies, Inc. platform specific
+ Last Level Cache Controller(LLCC) driver. This provides interfaces
+ to clients that use the LLCC. Say yes here to enable LLCC slice
+ driver.
+
+config QCOM_SDM845_LLCC
+   tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+   depends on QCOM_LLCC
+   help
+ Say yes here to enable the LLCC driver for SDM845. This provides
+ data required to configure LLCC so that clients can start using the
+ LLCC slices.
+
 config QCOM_MDT_LOADER
tristate
select QCOM_SCM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index dcebf28..e16d6a2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)   += smp2p.o
 obj-$(CONFIG_QCOM_SMSM)+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 000..2e1e4f0
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * SCT(System Cache Table) entry contains of the following members:
+ * usecase_id: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Boolean indicating if the slice has a fixed capacity
+ * bonus_ways: Bonus ways are additional ways to be used for any slice,
+ * if client ends up using more than reserved cache ways. Bonus
+ * ways are allocated only if they are not reserved for some
+ * other client.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot
+ * be used by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ * slice: normal or TCM(Tightly Coupled Memory)
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *configured to 1 only bonus and reserved ways are probed.
+ *When configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maintained active vote
+ *   then the ways assigned to this client are not flushed on power
+ *   collapse.
+ * activate_on_init: Activate the slice immediately after the SCT is programmed
+ */
+#define SCT_ENTRY(uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+   {   \
+   .usecase_id = uid,  \
+   .slice_id = sid,\
+   .max_cap = mc,  \
+   .priority = p,  \
+   .fixed_size = fs,   \
+   .bonus_ways = bway

[PATCH v8 2/2] drivers: soc: Add LLCC driver

2018-05-23 Thread Rishabh Bhatnagar
LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into multiple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice they get and activate or deactivate the slice as needed. LLCC driver
provides API for the clients to perform these operations.

Signed-off-by: Channagoud Kadabi 
Signed-off-by: Rishabh Bhatnagar 
Reviewed-by: Evan Green 
Reviewed-by: Rob Herring 
---
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c |  94 +++
 drivers/soc/qcom/llcc-slice.c  | 335 +
 include/linux/soc/qcom/llcc-qcom.h | 180 
 5 files changed, 628 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e050eb8..0b550f9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -21,6 +21,23 @@ config QCOM_GSBI
   functions for connecting the underlying serial UART, SPI, and I2C
   devices to the output pins.
 
+config QCOM_LLCC
+   tristate "Qualcomm Technologies, Inc. LLCC driver"
+   depends on ARCH_QCOM
+   help
+ Qualcomm Technologies, Inc. platform specific
+ Last Level Cache Controller(LLCC) driver. This provides interfaces
+ to clients that use the LLCC. Say yes here to enable LLCC slice
+ driver.
+
+config QCOM_SDM845_LLCC
+   tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+   depends on QCOM_LLCC
+   help
+ Say yes here to enable the LLCC driver for SDM845. This provides
+ data required to configure LLCC so that clients can start using the
+ LLCC slices.
+
 config QCOM_MDT_LOADER
tristate
select QCOM_SCM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index dcebf28..e16d6a2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)   += smp2p.o
 obj-$(CONFIG_QCOM_SMSM)+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 000..2e1e4f0
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * SCT(System Cache Table) entry contains of the following members:
+ * usecase_id: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Boolean indicating if the slice has a fixed capacity
+ * bonus_ways: Bonus ways are additional ways to be used for any slice,
+ * if client ends up using more than reserved cache ways. Bonus
+ * ways are allocated only if they are not reserved for some
+ * other client.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot
+ * be used by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ * slice: normal or TCM(Tightly Coupled Memory)
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *configured to 1 only bonus and reserved ways are probed.
+ *When configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maintained active vote
+ *   then the ways assigned to this client are not flushed on power
+ *   collapse.
+ * activate_on_init: Activate the slice immediately after the SCT is programmed
+ */
+#define SCT_ENTRY(uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+   {   \
+   .usecase_id = uid,  \
+   .slice_id = sid,\
+   .max_cap = mc,  \
+   .priority = p,  \
+   .fixed_size = fs,   \
+   .bonus_ways = bway, \
+   .res_ways = rway,   \
+   .cache_mode = cmod, \
+   

[PATCH v7 0/2] SDM845 System Cache Driver

2018-05-16 Thread Rishabh Bhatnagar
This series implements system cache or LLCC(Last Level Cache Controller)
driver for SDM845 SOC. The purpose of the driver is to partition the
system cache and program the settings such as priortiy, lines to probe
while doing a look up in the system cache, low power related settings etc.
The partitions are called cache slices. Each cache slice is associated
with size and SCID(System Cache ID). The driver also provides API for
clients to query the cache slice details,activate and deactivate them.

The driver can be broadly classified into:
* SOC specific driver: llcc-sdm845.c: Cache partitioning and cache slice
properties for usecases on sdm845 that need to use system cache.

* API : llcc-slice.c: Exports APIs to clients to query cache slice details,
activate and deactivate cache slices.

Changes since v6:
* Remove the max-slices property from DT.
* Make client's slice_ids as macros.
* Unlock mutex while returning from function in case of error.

Changes since v5:
* Remove client information from DT.
* Make the llcc driver data as global.
* Check return value of llcc_update_act_ctrl function
* Change error returned from -EFAULT to -EINVAL

Changes since v4:
* Remove null pointer checks as per comments.
* Remove extra blank lines.

Changes since v3:
* Use the regmap_read_poll_timeout function
* Check for regmap read/write errors.
* Remove memory barrier after regmap write
* Derive memory bank offsets using stride macro variable
* Remove debug statements from code
* Remove the qcom_llcc_remove function
* Use if IS_ENABLED in place of ifdef for built-in module
* Change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
* Remove unnecessary free functions
* Change the variable names as per review comments

Changes since v2:
* Corrected the Makefile to fix compilation.

Changes since v1:
* Added Makefile and Kconfig.

Changes since v0:
* Removed the syscon and simple-mfd approach
* Updated the device tree nodes to mention LLCC as a single HW block
* Moved llcc bank offsets from device tree and handled the offset
  in the driver.

ckad...@codeaurora.org (2):
  dt-bindings: Documentation for qcom, llcc
  drivers: soc: Add LLCC driver

 .../devicetree/bindings/arm/msm/qcom,llcc.txt  |  26 ++
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c | 106 +++
 drivers/soc/qcom/llcc-slice.c  | 337 +
 include/linux/soc/qcom/llcc-qcom.h | 180 +++
 6 files changed, 668 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 0/2] SDM845 System Cache Driver

2018-05-16 Thread Rishabh Bhatnagar
This series implements system cache or LLCC(Last Level Cache Controller)
driver for SDM845 SOC. The purpose of the driver is to partition the
system cache and program the settings such as priortiy, lines to probe
while doing a look up in the system cache, low power related settings etc.
The partitions are called cache slices. Each cache slice is associated
with size and SCID(System Cache ID). The driver also provides API for
clients to query the cache slice details,activate and deactivate them.

The driver can be broadly classified into:
* SOC specific driver: llcc-sdm845.c: Cache partitioning and cache slice
properties for usecases on sdm845 that need to use system cache.

* API : llcc-slice.c: Exports APIs to clients to query cache slice details,
activate and deactivate cache slices.

Changes since v6:
* Remove the max-slices property from DT.
* Make client's slice_ids as macros.
* Unlock mutex while returning from function in case of error.

Changes since v5:
* Remove client information from DT.
* Make the llcc driver data as global.
* Check return value of llcc_update_act_ctrl function
* Change error returned from -EFAULT to -EINVAL

Changes since v4:
* Remove null pointer checks as per comments.
* Remove extra blank lines.

Changes since v3:
* Use the regmap_read_poll_timeout function
* Check for regmap read/write errors.
* Remove memory barrier after regmap write
* Derive memory bank offsets using stride macro variable
* Remove debug statements from code
* Remove the qcom_llcc_remove function
* Use if IS_ENABLED in place of ifdef for built-in module
* Change EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
* Remove unnecessary free functions
* Change the variable names as per review comments

Changes since v2:
* Corrected the Makefile to fix compilation.

Changes since v1:
* Added Makefile and Kconfig.

Changes since v0:
* Removed the syscon and simple-mfd approach
* Updated the device tree nodes to mention LLCC as a single HW block
* Moved llcc bank offsets from device tree and handled the offset
  in the driver.

ckad...@codeaurora.org (2):
  dt-bindings: Documentation for qcom, llcc
  drivers: soc: Add LLCC driver

 .../devicetree/bindings/arm/msm/qcom,llcc.txt  |  26 ++
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c | 106 +++
 drivers/soc/qcom/llcc-slice.c  | 337 +
 include/linux/soc/qcom/llcc-qcom.h | 180 +++
 6 files changed, 668 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 2/2] drivers: soc: Add LLCC driver

2018-05-16 Thread Rishabh Bhatnagar
LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into multiple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice they get and activate or deactivate the slice as needed. LLCC driver
provides API for the clients to perform these operations.

Signed-off-by: Channagoud Kadabi <ckad...@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
---
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c | 106 
 drivers/soc/qcom/llcc-slice.c  | 337 +
 include/linux/soc/qcom/llcc-qcom.h | 180 
 5 files changed, 642 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e050eb8..0b550f9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -21,6 +21,23 @@ config QCOM_GSBI
   functions for connecting the underlying serial UART, SPI, and I2C
   devices to the output pins.
 
+config QCOM_LLCC
+   tristate "Qualcomm Technologies, Inc. LLCC driver"
+   depends on ARCH_QCOM
+   help
+ Qualcomm Technologies, Inc. platform specific
+ Last Level Cache Controller(LLCC) driver. This provides interfaces
+ to clients that use the LLCC. Say yes here to enable LLCC slice
+ driver.
+
+config QCOM_SDM845_LLCC
+   tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+   depends on QCOM_LLCC
+   help
+ Say yes here to enable the LLCC driver for SDM845. This provides
+ data required to configure LLCC so that clients can start using the
+ LLCC slices.
+
 config QCOM_MDT_LOADER
tristate
select QCOM_SCM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index dcebf28..e16d6a2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)   += smp2p.o
 obj-$(CONFIG_QCOM_SMSM)+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 000..bda2234
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * SCT(System Cache Table) entry contains of the following members:
+ * usecase_id: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Boolean indicating if the slice has a fixed capacity
+ * bonus_ways: Bonus ways are additional ways to be used for any slice,
+ * if client ends up using more than reserved cache ways. Bonus
+ * ways are allocated only if they are not reserved for some
+ * other client.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot
+ * be used by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ * slice: normal or TCM(Tightly Coupled Memory)
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *configured to 1 only bonus and reserved ways are probed.
+ *When configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maintained active vote
+ *   then the ways assigned to this client are not flushed on power
+ *   collapse.
+ * activate_on_init: Activate the slice immediately after the SCT is programmed
+ */
+#define SCT_ENTRY(uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+   {   \
+   .usecase_id = uid,  \
+   .slice_id = sid,\
+   .max_cap = mc,  \
+   .priority = p,  \
+   .fixed_size = fs,   \
+   .bonus_ways = bway, \
+   .res_ways = rway,   \
+   .cache_mode = cmod, \
+   

[PATCH v7 2/2] drivers: soc: Add LLCC driver

2018-05-16 Thread Rishabh Bhatnagar
LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into multiple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice they get and activate or deactivate the slice as needed. LLCC driver
provides API for the clients to perform these operations.

Signed-off-by: Channagoud Kadabi 
Signed-off-by: Rishabh Bhatnagar 
---
 drivers/soc/qcom/Kconfig   |  17 ++
 drivers/soc/qcom/Makefile  |   2 +
 drivers/soc/qcom/llcc-sdm845.c | 106 
 drivers/soc/qcom/llcc-slice.c  | 337 +
 include/linux/soc/qcom/llcc-qcom.h | 180 
 5 files changed, 642 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e050eb8..0b550f9 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -21,6 +21,23 @@ config QCOM_GSBI
   functions for connecting the underlying serial UART, SPI, and I2C
   devices to the output pins.
 
+config QCOM_LLCC
+   tristate "Qualcomm Technologies, Inc. LLCC driver"
+   depends on ARCH_QCOM
+   help
+ Qualcomm Technologies, Inc. platform specific
+ Last Level Cache Controller(LLCC) driver. This provides interfaces
+ to clients that use the LLCC. Say yes here to enable LLCC slice
+ driver.
+
+config QCOM_SDM845_LLCC
+   tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+   depends on QCOM_LLCC
+   help
+ Say yes here to enable the LLCC driver for SDM845. This provides
+ data required to configure LLCC so that clients can start using the
+ LLCC slices.
+
 config QCOM_MDT_LOADER
tristate
select QCOM_SCM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index dcebf28..e16d6a2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)   += smp2p.o
 obj-$(CONFIG_QCOM_SMSM)+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 000..bda2234
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * SCT(System Cache Table) entry contains of the following members:
+ * usecase_id: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Boolean indicating if the slice has a fixed capacity
+ * bonus_ways: Bonus ways are additional ways to be used for any slice,
+ * if client ends up using more than reserved cache ways. Bonus
+ * ways are allocated only if they are not reserved for some
+ * other client.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot
+ * be used by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ * slice: normal or TCM(Tightly Coupled Memory)
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *configured to 1 only bonus and reserved ways are probed.
+ *When configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maintained active vote
+ *   then the ways assigned to this client are not flushed on power
+ *   collapse.
+ * activate_on_init: Activate the slice immediately after the SCT is programmed
+ */
+#define SCT_ENTRY(uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+   {   \
+   .usecase_id = uid,  \
+   .slice_id = sid,\
+   .max_cap = mc,  \
+   .priority = p,  \
+   .fixed_size = fs,   \
+   .bonus_ways = bway, \
+   .res_ways = rway,   \
+   .cache_mode = cmod, \
+   .probe_target_ways = ptw,   \
+   

[PATCH v7 1/2] dt-bindings: Documentation for qcom, llcc

2018-05-16 Thread Rishabh Bhatnagar
Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi <ckad...@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt  | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 000..0ebbf0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,26 @@
+== Introduction==
+
+LLCC (Last Level Cache Controller) provides last level of cache memory in SOC,
+that can be shared by multiple clients. Clients here are different cores in the
+SOC, the idea is to minimize the local caches at the clients and migrate to
+common pool of memory. Cache memory is divided into partitions called slices
+which are assigned to clients. Clients can query the slice details, activate
+and deactivate them.
+
+Properties:
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,sdm845-llcc"
+
+- reg:
+   Usage: required
+   Value Type: 
+   Definition: Start address and the the size of the register region.
+
+Example:
+
+   qcom,llcc@110 {
+   compatible = "qcom,sdm845-llcc";
+   reg = <0x110 0x25>;
+   };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 1/2] dt-bindings: Documentation for qcom, llcc

2018-05-16 Thread Rishabh Bhatnagar
Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi 
Signed-off-by: Rishabh Bhatnagar 
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt  | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 000..0ebbf0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,26 @@
+== Introduction==
+
+LLCC (Last Level Cache Controller) provides last level of cache memory in SOC,
+that can be shared by multiple clients. Clients here are different cores in the
+SOC, the idea is to minimize the local caches at the clients and migrate to
+common pool of memory. Cache memory is divided into partitions called slices
+which are assigned to clients. Clients can query the slice details, activate
+and deactivate them.
+
+Properties:
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,sdm845-llcc"
+
+- reg:
+   Usage: required
+   Value Type: 
+   Definition: Start address and the the size of the register region.
+
+Example:
+
+   qcom,llcc@110 {
+   compatible = "qcom,sdm845-llcc";
+   reg = <0x110 0x25>;
+   };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 1/2] dt-bindings: Documentation for qcom, llcc

2018-05-08 Thread Rishabh Bhatnagar
Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi <ckad...@codeaurora.org>
Signed-off-by: Rishabh Bhatnagar <risha...@codeaurora.org>
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt  | 32 ++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 000..a586a17
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,32 @@
+== Introduction==
+
+LLCC (Last Level Cache Controller) provides last level of cache memory in SOC,
+that can be shared by multiple clients. Clients here are different cores in the
+SOC, the idea is to minimize the local caches at the clients and migrate to
+common pool of memory. Cache memory is divided into partitions called slices
+which are assigned to clients. Clients can query the slice details, activate
+and deactivate them.
+
+Properties:
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be "qcom,sdm845-llcc"
+
+- reg:
+   Usage: required
+   Value Type: 
+   Definition: Start address and the range of the LLCC registers.
+
+- max-slices:
+   usage: required
+   Value Type: 
+   Definition: Number of cache slices supported by hardware
+
+Example:
+
+   llcc: qcom,llcc@110 {
+   compatible = "qcom,sdm845-llcc";
+   reg = <0x110 0x25>;
+   max-slices = <32>;
+   };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



  1   2   >