[PATCH v5 03/17] remoteproc: qcom_q6v5_pas: Use qcom_rproc_minidump()

2023-09-09 Thread Mukesh Ojha
Now, as all the minidump specific data structure is moved to
minidump specific files and implementation wise qcom_rproc_minidump()
and qcom_minidump() exactly same and the name qcom_rproc_minidump
make more sense as it happen to collect the minidump for the
remoteproc processors. So, let's use qcom_rproc_minidump() and
we will be removing qcom_minidump() and minidump related stuff
from driver/remoteproc/qcom_common.c .

Signed-off-by: Mukesh Ojha 
---
 drivers/remoteproc/Kconfig | 1 +
 drivers/remoteproc/qcom_q6v5_pas.c | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 48845dc8fa85..cea960749e2c 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -166,6 +166,7 @@ config QCOM_PIL_INFO
 
 config QCOM_RPROC_COMMON
tristate
+   select QCOM_RPROC_MINIDUMP
 
 config QCOM_Q6V5_COMMON
tristate
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c 
b/drivers/remoteproc/qcom_q6v5_pas.c
index 3153d82037e7..f235daae84ff 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "qcom_common.h"
 #include "qcom_pil_info.h"
@@ -130,7 +131,7 @@ static void adsp_minidump(struct rproc *rproc)
if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
return;
 
-   qcom_minidump(rproc, adsp->minidump_id, adsp_segment_dump);
+   qcom_rproc_minidump(rproc, adsp->minidump_id, adsp_segment_dump);
 }
 
 static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
-- 
2.7.4



[PATCH v5 00/17] Add Qualcomm Minidump kernel driver related support

2023-09-09 Thread Mukesh Ojha
Hi All,

This is to continuation from the conversation happened at v4

https://lore.kernel.org/lkml/632c5b97-4a91-c3e8-1e6c-33d6c4f64...@quicinc.com/

https://lore.kernel.org/lkml/695133e6-105f-de2a-5559-555cea0a0...@quicinc.com/

We have put abstract on LPC on this topic as well as initiated a mail thread
with other SoC vendors but did not get much traction on it.

https://lore.kernel.org/lkml/0199db00-1b1d-0c63-58ff-03efae02c...@quicinc.com/

We explored most of possiblity present in kernel to address this issue[1] but
solution like kdump/fadump does not seems safe/secure/performant from our
perspective.

Hence, with this series we tried to make the minidump kernel driver, simple
and tied with pstore frontends, so that it collects the present available
frontends data like dmesg, ftrace, pmsg, ftrace., Also, we will be working
towards enhancing generic pstore to capture more debug data which will be
helpful for first hand of debugging that can benefit both other pstore users
as well as us as minidump users.

One of the proposal made here,
https://lore.kernel.org/lkml/1683561060-2197-1-git-send-email-quic_mo...@quicinc.com/

Looking forward for your comments.

Thanks,
Mukesh

[1]
Minidump is a best effort mechanism to collect useful and predefined data
for first level of debugging on end user devices running on Qualcomm SoCs.
It is built on the premise that System on Chip (SoC) or subsystem part of
SoC crashes, due to a range of hardware and software bugs. Hence, the
ability to collect accurate data is only a best-effort. The data collected
could be invalid or corrupted, data collection itself could fail, and so on.

Qualcomm devices in engineering mode provides a mechanism for generating
full system ramdumps for post mortem debugging. But in some cases it's
however not feasible to capture the entire content of RAM. The minidump
mechanism provides the means for selecting which snippets should be
included in the ramdump.

The core of SMEM based minidump feature is part of Qualcomm's boot
firmware code. It initializes shared memory (SMEM), which is a part of
DDR and allocates a small section of SMEM to minidump table i.e also
called global table of content (G-ToC). Each subsystem (APSS, ADSP, ...)
has their own table of segments to be included in the minidump and all
get their reference from G-ToC. Each segment/region has some details
like name, physical address and it's size etc. and it could be anywhere
scattered in the DDR.

Existing upstream Qualcomm remoteproc driver[1] already supports SMEM
based minidump feature for remoteproc instances like ADSP, MODEM, ...
where predefined selective segments of subsystem region can be dumped
as part of coredump collection which generates smaller size artifacts
compared to complete coredump of subsystem on crash.

[1]
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/remoteproc/qcom_common.c#n142

In addition to managing and querying the APSS minidump description,
the Linux driver maintains a ELF header in a segment. This segment
gets updated with section/program header whenever a new entry gets
registered.

Changes in v5:
 - On suggestion from Pavan.k, to have single function call for minidump 
collection
   from remoteproc driver, separated the logic to have separate minidump file 
called
   qcom_rproc_minidump.c and also renamed the function from qcom_minidump() to 
   qcom_rproc_minidump(); however, dropped his suggestion about rework on lazy 
deletion
   during region unregister in this series, will pursue it in next series.

 - To simplify the minidump driver, removed the complication for frontend and 
different
   backend from Greg suggestion, will pursue this once main driver gets 
mainlined.

 - Move the dynamic ramoops region allocation from Device tree approach to 
command line
   approch with the introduction command line parsing and memblock reservation 
during
   early boot up; Not added documentation about it yet, will add if it gets 
positive
   response.

 - Exporting linux banner from kernel to make minidump build also as module, 
however,
   minidump is a debug module and should be kernel built to get most debug 
information
   from kernel.

 - Tried to address comments given on dload patch series. 

Changes in v4: 
https://lore.kernel.org/lkml/1687955688-20809-1-git-send-email-quic_mo...@quicinc.com/
 - Redesigned the driver and divided the driver into front end and backend 
(smem) so
   that any new backend can be attached easily to avoid code duplication.
 - Patch reordering as per the driver and subsystem to easier review of the 
code.
 - Removed minidump specific code from remoteproc to minidump smem based driver.
 - Enabled the all the driver as modules.
 - Address comments made on documentation and yaml and Device tree file 
[Krzysztof/Konrad]
 - Address comments made qcom_pstore_minidump driver and given its Device tree
   same set of properties as ramoops. [Luca/Kees]
 - Added patch for MAINTAINER file.
 - Inclu

[PATCH v5 01/17] docs: qcom: Add qualcomm minidump guide

2023-09-09 Thread Mukesh Ojha
Add the qualcomm minidump guide for the users which tries to cover
the dependency, API use and the way to test and collect minidump
on Qualcomm supported SoCs.

Signed-off-by: Mukesh Ojha 
---
 Documentation/admin-guide/index.rst |   1 +
 Documentation/admin-guide/qcom_minidump.rst | 272 
 2 files changed, 273 insertions(+)
 create mode 100644 Documentation/admin-guide/qcom_minidump.rst

diff --git a/Documentation/admin-guide/index.rst 
b/Documentation/admin-guide/index.rst
index 43ea35613dfc..251d070486c2 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -120,6 +120,7 @@ configure specific aspects of kernel behavior to your 
liking.
perf-security
pm/index
pnp
+   qcom_minidump
rapidio
ras
rtc
diff --git a/Documentation/admin-guide/qcom_minidump.rst 
b/Documentation/admin-guide/qcom_minidump.rst
new file mode 100644
index ..20202da8ca40
--- /dev/null
+++ b/Documentation/admin-guide/qcom_minidump.rst
@@ -0,0 +1,272 @@
+Qualcomm minidump feature
+=
+
+Introduction
+
+
+Minidump is a best effort mechanism to collect useful and predefined
+data for first level of debugging on end user devices running on
+Qualcomm SoCs. It is built on the premise that System on Chip (SoC)
+or subsystem part of SoC crashes, due to a range of hardware and
+software bugs. Hence, the ability to collect accurate data is only
+a best-effort. The data collected could be invalid or corrupted, data
+collection itself could fail, and so on.
+
+Qualcomm devices in engineering mode provides a mechanism for generating
+full system RAM dumps for post-mortem debugging. But in some cases it's
+however not feasible to capture the entire content of RAM. The minidump
+mechanism provides the means for selected region should be included in
+the ramdump.
+
+
+::
+
+   +---+
+   |   DDR   +-+   |
+   | |  SS0-ToC|   |
+   | ++ ++ |   |
+   | |Shared memory   | | SS1-ToC| |   |
+   | |(SMEM)  | || |   |
+   | || +-->|+   | |   |
+   | |G-ToC   | |   | SS-ToC  \  | |   |
+   | |+-+ | |   | +---+  | |   |
+   | ||-| | |   | |---|  | |   |
+   | || SS0-ToC | | | +-|<|SS1 region1|  | |   |
+   | ||-| | | | | |---|  | |   |
+   | || SS1-ToC |-|>+ | | |SS1 region2|  | |   |
+   | ||-| |   | | |---|  | |   |
+   | || SS2-ToC | |   | | |  ...  |  | |   |
+   | ||-| |   | | |---|  | |   |
+   | ||  ...| |   |-|<|SS1 regionN|  | |   |
+   | ||-| |   | | |---|  | |   |
+   | || SSn-ToC | |   | | +---+  | |   |
+   | |+-+ |   | || |   |
+   | ||   | || |   |
+   | ||   +>|  regionN   | |   |
+   | ||   | || |   |
+   | ++   | || |   |
+   |  | || |   |
+   |  +>|  region1   | |   |
+   ||| |   |
+   ||| |   |
+   |||-+   |
+   ||  region5   | |
+   ||| |
+   ||| |
+   |  Region information++ |
+   | +---+ |
+   | |region name| |
+   | |---| |
+   | |region address | |
+   | |---| |
+   | |region size| |
+   | +---+ |
+   +---+
+   G-ToC: Global table of contents
+   SS-ToC: Subsystem table of contents
+   SS0-SSn: Subsystem numbered from 0 to n
+
+It depends on SoC where the underlying firmware is keeping the
+minidump global table taking care of subsystem ToC part for
+minidump like for above diagram, it is for shared memory sitting
+in DDR and it is shared among various master however it is possible
+that this could be implemented via memory mapped regions but the
+general idea should remain same. Here, various subsystem could be
+DSP's like ADSP/CDSP/MODEM etc, along with Application processor
+(APSS) where Linux runs. DSP minidump gets collected when DSP's goes
+for recovery followed by a crash. The minidump part of code for
+that resides in ``qcom_rproc_minidump.c``.
+
+
+SMEM as backend
+
+
+In this document, SMEM will be used as the backend implementation
+o

[PATCH v5 02/17] soc: qcom: Add qcom_rproc_minidump module

2023-09-09 Thread Mukesh Ojha
Add qcom_rproc_minidump module in a preparation to remove
minidump specific code from driver/remoteproc/qcom_common.c
and provide needed exported API, this as well helps to
abstract minidump specific data layout from qualcomm's
remoteproc driver.

It is just a copying of qcom_minidump() functionality from
driver/remoteproc/qcom_common.c into a separate file under
qcom_rproc_minidump().

Signed-off-by: Mukesh Ojha 
---
 drivers/soc/qcom/Kconfig  |  10 +++
 drivers/soc/qcom/Makefile |   1 +
 drivers/soc/qcom/qcom_minidump_internal.h |  64 +
 drivers/soc/qcom/qcom_rproc_minidump.c| 111 ++
 include/soc/qcom/qcom_minidump.h  |  23 +++
 5 files changed, 209 insertions(+)
 create mode 100644 drivers/soc/qcom/qcom_minidump_internal.h
 create mode 100644 drivers/soc/qcom/qcom_rproc_minidump.c
 create mode 100644 include/soc/qcom/qcom_minidump.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e597799e8121..ff38deac6a7d 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -290,4 +290,14 @@ config QCOM_INLINE_CRYPTO_ENGINE
tristate
select QCOM_SCM
 
+config QCOM_RPROC_MINIDUMP
+   tristate "QCOM Remoteproc Minidump Support"
+   depends on ARCH_QCOM || COMPILE_TEST
+   depends on QCOM_SMEM
+   help
+ Enablement of core minidump feature is controlled from boot firmware
+ side, so if it is enabled from firmware, this config allow linux to
+ query predefined minidump segments associated with the remote 
processor
+ and check its validity and end up collecting the dump on remote 
processor
+ crash during its recovery.
 endmenu
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 99114c71092b..a5fd2fed0923 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -35,3 +35,4 @@ obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) +=   
kryo-l2-accessors.o
 obj-$(CONFIG_QCOM_ICC_BWMON)   += icc-bwmon.o
 qcom_ice-objs  += ice.o
 obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE)+= qcom_ice.o
+obj-$(CONFIG_QCOM_RPROC_MINIDUMP)  += qcom_rproc_minidump.o
diff --git a/drivers/soc/qcom/qcom_minidump_internal.h 
b/drivers/soc/qcom/qcom_minidump_internal.h
new file mode 100644
index ..71709235b196
--- /dev/null
+++ b/drivers/soc/qcom/qcom_minidump_internal.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _QCOM_MINIDUMP_INTERNAL_H_
+#define _QCOM_MINIDUMP_INTERNAL_H_
+
+#define MAX_NUM_OF_SS   10
+#define MAX_REGION_NAME_LENGTH  16
+#define SBL_MINIDUMP_SMEM_ID   602
+#define MINIDUMP_REGION_VALID ('V' << 24 | 'A' << 16 | 'L' << 8 | 'I' << 0)
+#define MINIDUMP_SS_ENCR_DONE ('D' << 24 | 'O' << 16 | 'N' << 8 | 'E' << 0)
+#define MINIDUMP_SS_ENABLED   ('E' << 24 | 'N' << 16 | 'B' << 8 | 'L' << 0)
+
+/**
+ * struct minidump_region - Minidump region
+ * @name   : Name of the region to be dumped
+ * @seq_num:   : Use to differentiate regions with same name.
+ * @valid  : This entry to be dumped (if set to 1)
+ * @address: Physical address of region to be dumped
+ * @size   : Size of the region
+ */
+struct minidump_region {
+   charname[MAX_REGION_NAME_LENGTH];
+   __le32  seq_num;
+   __le32  valid;
+   __le64  address;
+   __le64  size;
+};
+
+/**
+ * struct minidump_subsystem - Subsystem's SMEM Table of content
+ * @status : Subsystem toc init status
+ * @enabled : if set to 1, this region would be copied during coredump
+ * @encryption_status: Encryption status for this subsystem
+ * @encryption_required : Decides to encrypt the subsystem regions or not
+ * @region_count : Number of regions added in this subsystem toc
+ * @regions_baseptr : regions base pointer of the subsystem
+ */
+struct minidump_subsystem {
+   __le32  status;
+   __le32  enabled;
+   __le32  encryption_status;
+   __le32  encryption_required;
+   __le32  region_count;
+   __le64  regions_baseptr;
+};
+
+/**
+ * struct minidump_global_toc - Global Table of Content
+ * @status : Global Minidump init status
+ * @md_revision : Minidump revision
+ * @enabled : Minidump enable status
+ * @subsystems : Array of subsystems toc
+ */
+struct minidump_global_toc {
+   __le32  status;
+   __le32  md_revision;
+   __le32  enabled;
+   struct minidump_subsystem   subsystems[MAX_NUM_OF_SS];
+};
+
+#endif /* _QCOM_MINIDUMP_INTERNAL_H_ */
diff --git a/drivers/soc/qcom/qcom_rproc_minidump.c 
b/drivers/soc/qcom/qcom_rproc_minidump.c
new file mode 100644
index ..9bc84cc2536f
--- /dev/null
+++ b/drivers/soc/qcom/qcom_rproc_minidump.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*

[PATCH v5 05/17] init: export linux_banner data variable

2023-09-09 Thread Mukesh Ojha
Some debug loadable module like minidump is interested in knowing
the kernel version against which it is being build. Let's export
linux_banner.

Signed-off-by: Mukesh Ojha 
---
 include/linux/init.h | 3 +++
 init/version-timestamp.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/include/linux/init.h b/include/linux/init.h
index 266c3e1640d4..1e5d03c2de68 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -148,6 +148,9 @@ extern char *saved_command_line;
 extern unsigned int saved_command_line_len;
 extern unsigned int reset_devices;
 
+/* Defined in init/version-timestamp.c */
+extern const char linux_banner[];
+
 /* used by init/main.c */
 void setup_arch(char **);
 void prepare_namespace(void);
diff --git a/init/version-timestamp.c b/init/version-timestamp.c
index 043cbf80a766..a48f2c19e5d7 100644
--- a/init/version-timestamp.c
+++ b/init/version-timestamp.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct uts_namespace init_uts_ns = {
.ns.count = REFCOUNT_INIT(2),
@@ -28,3 +29,5 @@ struct uts_namespace init_uts_ns = {
 const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+EXPORT_SYMBOL_GPL(linux_banner);
-- 
2.7.4



[PATCH v5 04/17] remoteproc: qcom: Remove minidump related data from qcom_common.c

2023-09-09 Thread Mukesh Ojha
As minidump specific data structure and functions move under
config QCOM_RPROC_MINIDUMP, so remove minidump specific data
from driver/remoteproc/qcom_common.c .

Signed-off-by: Mukesh Ojha 
---
 drivers/remoteproc/qcom_common.c | 150 ---
 1 file changed, 150 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index a0d4238492e9..24dc3144b15a 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -26,61 +26,6 @@
 #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)
 
-#define MAX_NUM_OF_SS   10
-#define MAX_REGION_NAME_LENGTH  16
-#define SBL_MINIDUMP_SMEM_ID   602
-#define MD_REGION_VALID('V' << 24 | 'A' << 16 | 'L' << 8 | 'I' 
<< 0)
-#define MD_SS_ENCR_DONE('D' << 24 | 'O' << 16 | 'N' << 8 | 'E' 
<< 0)
-#define MD_SS_ENABLED  ('E' << 24 | 'N' << 16 | 'B' << 8 | 'L' << 0)
-
-/**
- * struct minidump_region - Minidump region
- * @name   : Name of the region to be dumped
- * @seq_num:   : Use to differentiate regions with same name.
- * @valid  : This entry to be dumped (if set to 1)
- * @address: Physical address of region to be dumped
- * @size   : Size of the region
- */
-struct minidump_region {
-   charname[MAX_REGION_NAME_LENGTH];
-   __le32  seq_num;
-   __le32  valid;
-   __le64  address;
-   __le64  size;
-};
-
-/**
- * struct minidump_subsystem - Subsystem's SMEM Table of content
- * @status : Subsystem toc init status
- * @enabled : if set to 1, this region would be copied during coredump
- * @encryption_status: Encryption status for this subsystem
- * @encryption_required : Decides to encrypt the subsystem regions or not
- * @region_count : Number of regions added in this subsystem toc
- * @regions_baseptr : regions base pointer of the subsystem
- */
-struct minidump_subsystem {
-   __le32  status;
-   __le32  enabled;
-   __le32  encryption_status;
-   __le32  encryption_required;
-   __le32  region_count;
-   __le64  regions_baseptr;
-};
-
-/**
- * struct minidump_global_toc - Global Table of Content
- * @status : Global Minidump init status
- * @md_revision : Minidump revision
- * @enabled : Minidump enable status
- * @subsystems : Array of subsystems toc
- */
-struct minidump_global_toc {
-   __le32  status;
-   __le32  md_revision;
-   __le32  enabled;
-   struct minidump_subsystem   subsystems[MAX_NUM_OF_SS];
-};
-
 struct qcom_ssr_subsystem {
const char *name;
struct srcu_notifier_head notifier_list;
@@ -90,101 +35,6 @@ struct qcom_ssr_subsystem {
 static LIST_HEAD(qcom_ssr_subsystem_list);
 static DEFINE_MUTEX(qcom_ssr_subsys_lock);
 
-static void qcom_minidump_cleanup(struct rproc *rproc)
-{
-   struct rproc_dump_segment *entry, *tmp;
-
-   list_for_each_entry_safe(entry, tmp, &rproc->dump_segments, node) {
-   list_del(&entry->node);
-   kfree(entry->priv);
-   kfree(entry);
-   }
-}
-
-static int qcom_add_minidump_segments(struct rproc *rproc, struct 
minidump_subsystem *subsystem,
-   void (*rproc_dumpfn_t)(struct rproc *rproc, struct 
rproc_dump_segment *segment,
-   void *dest, size_t offset, size_t size))
-{
-   struct minidump_region __iomem *ptr;
-   struct minidump_region region;
-   int seg_cnt, i;
-   dma_addr_t da;
-   size_t size;
-   char *name;
-
-   if (WARN_ON(!list_empty(&rproc->dump_segments))) {
-   dev_err(&rproc->dev, "dump segment list already populated\n");
-   return -EUCLEAN;
-   }
-
-   seg_cnt = le32_to_cpu(subsystem->region_count);
-   ptr = ioremap((unsigned long)le64_to_cpu(subsystem->regions_baseptr),
- seg_cnt * sizeof(struct minidump_region));
-   if (!ptr)
-   return -EFAULT;
-
-   for (i = 0; i < seg_cnt; i++) {
-   memcpy_fromio(®ion, ptr + i, sizeof(region));
-   if (le32_to_cpu(region.valid) == MD_REGION_VALID) {
-   name = kstrndup(region.name, MAX_REGION_NAME_LENGTH - 
1, GFP_KERNEL);
-   if (!name) {
-   iounmap(ptr);
-   return -ENOMEM;
-   }
-   da = le64_to_cpu(region.address);
-   size = le64_to_cpu(region.size);
-   rproc_coredump_add_custom_segment(rproc, da, size, 
rproc_dumpfn_t, name);
-   }
-   }
-
-   iounmap(ptr);
-   return 0;
-}
-
-void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
-   void (*rproc_dumpfn_t)(struct rproc *rproc,
-   

[PATCH v5 07/17] soc: qcom: minidump: Add pending region registration

2023-09-09 Thread Mukesh Ojha
Pending regions are those apss minidump regions which came for
registration before minidump was initialized or ready to do
register the region.

We can add regions to pending region list and register all of
them from apss minidump driver probe in one go.

Signed-off-by: Mukesh Ojha 
---
 drivers/soc/qcom/qcom_minidump.c | 140 ---
 1 file changed, 130 insertions(+), 10 deletions(-)

diff --git a/drivers/soc/qcom/qcom_minidump.c b/drivers/soc/qcom/qcom_minidump.c
index 86f4d09a7b4e..4ce36f154e89 100644
--- a/drivers/soc/qcom/qcom_minidump.c
+++ b/drivers/soc/qcom/qcom_minidump.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -63,6 +64,33 @@ struct minidump {
struct mutexmd_lock;
 };
 
+/**
+ * struct minidump_pregion - Minidump pending region
+ * @list   : Pending region list pointer
+ * @region : APSS minidump client region
+ */
+struct minidump_pregion {
+   struct list_head list;
+   struct qcom_minidump_region  region;
+};
+
+/**
+ * struct minidump_plist - Minidump pending region list
+ * @plist  : List of pending region to be registered
+ * @pregion_cnt: Count of the pending region to be registered
+ */
+struct minidump_plist {
+   struct list_head  plist;
+   int   pregion_cnt;
+   struct mutex  plock;
+};
+
+static struct minidump_plist md_plist = {
+   .plist = LIST_HEAD_INIT(md_plist.plist),
+   .pregion_cnt = 0,
+   .plock = __MUTEX_INITIALIZER(md_plist.plock),
+};
+
 /*
  * In some of the Old Qualcomm devices, boot firmware statically allocates 300
  * as total number of supported region (including all co-processors) in
@@ -336,6 +364,26 @@ static bool qcom_minidump_valid_region(const struct 
qcom_minidump_region *region
IS_ALIGNED(region->size, 4);
 }
 
+static struct minidump_pregion *
+check_region_in_plist(const struct qcom_minidump_region *region)
+{
+   struct minidump_pregion *md_pregion;
+   struct minidump_pregion *tmp;
+   bool found = false;
+
+   list_for_each_entry_safe(md_pregion, tmp, &md_plist.plist, list) {
+   struct qcom_minidump_region *md_region;
+
+   md_region = &md_pregion->region;
+   if (!strcmp(md_region->name, region->name)) {
+   found = true;
+   break;
+   }
+   }
+
+   return found ? md_pregion : NULL;
+}
+
 /**
  * qcom_minidump_region_register() - Register region in APSS Minidump table.
  * @region: minidump region.
@@ -344,16 +392,44 @@ static bool qcom_minidump_valid_region(const struct 
qcom_minidump_region *region
  */
 int qcom_minidump_region_register(const struct qcom_minidump_region *region)
 {
+   struct minidump_pregion *md_pregion;
struct minidump *md;
-   int ret;
-
-   md = qcom_smem_minidump_ready();
-   if (!md)
-   return -EPROBE_DEFER;
+   int ret = 0;
 
if (!qcom_minidump_valid_region(region))
return -EINVAL;
 
+   mutex_lock(&md_plist.plock);
+   md = qcom_smem_minidump_ready();
+   if (!md) {
+   if (md_plist.pregion_cnt >= MAX_NUM_ENTRIES - 1) {
+   pr_err("maximum region limit %u reached\n", 
md_plist.pregion_cnt);
+   ret = -ENOSPC;
+   goto unlock_plock;
+   }
+
+   md_pregion = check_region_in_plist(region);
+   if (md_pregion) {
+   pr_info("%s region is already exist\n", region->name);
+   ret = -EEXIST;
+   goto unlock_plock;
+   }
+   /*
+* Maintain a list of client regions which came before
+* minidump driver was ready and once it is ready,
+* register them in one go from minidump probe function.
+*/
+   md_pregion = kzalloc(sizeof(*md_pregion), GFP_KERNEL);
+   if (!md_pregion) {
+   ret = -ENOMEM;
+   goto unlock_plock;
+   }
+   md_pregion->region = *region;
+   list_add_tail(&md_pregion->list, &md_plist.plist);
+   md_plist.pregion_cnt++;
+   goto unlock_plock;
+   }
+
mutex_lock(&md->md_lock);
ret = qcom_md_region_register(md, region);
if (ret)
@@ -362,6 +438,10 @@ int qcom_minidump_region_register(const struct 
qcom_minidump_region *region)
qcom_md_update_elfheader(md, region);
 unlock:
mutex_unlock(&md->md_lock);
+   return 0;
+
+unlock_plock:
+   mutex_unlock(&md_plist.plock);
return ret;
 }
 EXPORT_SYMBOL_GPL(qcom_minidump_region_register);
@@ -374,16 +454,28 @@ EXPORT_SYMBOL_GPL(qcom_minidump_region_register);
  */
 int qcom_minidump_region_unregister(const struct qcom_minidump_region *region)
 {
+   

[PATCH v5 06/17] soc: qcom: Add Qualcomm APSS minidump kernel driver

2023-09-09 Thread Mukesh Ojha
Minidump is a best effort mechanism to collect useful and predefined
data for first level of debugging on end user devices running on
Qualcomm SoCs. It is built on the premise that System on Chip (SoC)
or subsystem part of SoC crashes, due to a range of hardware and
software bugs. Hence, the ability to collect accurate data is only
a best-effort. The data collected could be invalid or corrupted,
data collection itself could fail, and so on.

Qualcomm devices in engineering mode provides a mechanism for
generating full system ramdumps for post mortem debugging. But in some
cases it's however not feasible to capture the entire content of RAM.
The minidump mechanism provides the means for selecting region should
be included in the ramdump. The solution supports extracting the
ramdump/minidump produced either over USB or stored to an attached
storage device.

The core of minidump feature is part of Qualcomm's boot firmware code.
It initializes shared memory (SMEM), which is a part of DDR and
allocates a small section of it to minidump table i.e also called
global table of content (G-ToC). Each subsystem (APSS, ADSP, ...) has
their own table of segments to be included in the minidump, all
references from a descriptor in SMEM (G-ToC). Each segment/region has
some details like name, physical address and it's size etc. and it
could be anywhere scattered in the DDR.

qcom_minidump(core or frontend) driver adds the capability to add inux
region to be dumped as part of ram dump collection. It provides
appropriate symbol to register/unregister client regions.

To simplify post mortem debugging, it creates and maintain an ELF
header as first region that gets updated upon registration
of a new region.

Signed-off-by: Mukesh Ojha 
---
 drivers/soc/qcom/Kconfig  |  13 +
 drivers/soc/qcom/Makefile |   1 +
 drivers/soc/qcom/qcom_minidump.c  | 603 ++
 drivers/soc/qcom/qcom_minidump_internal.h |  10 +
 drivers/soc/qcom/smem.c   |  18 +
 include/linux/soc/qcom/smem.h |   2 +
 include/soc/qcom/qcom_minidump.h  |  33 ++
 7 files changed, 680 insertions(+)
 create mode 100644 drivers/soc/qcom/qcom_minidump.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index ff38deac6a7d..4b36d46807bc 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -300,4 +300,17 @@ config QCOM_RPROC_MINIDUMP
  query predefined minidump segments associated with the remote 
processor
  and check its validity and end up collecting the dump on remote 
processor
  crash during its recovery.
+
+config QCOM_MINIDUMP
+   tristate "QCOM APSS Minidump driver"
+   depends on ARCH_QCOM || COMPILE_TEST
+   depends on QCOM_SMEM
+   help
+ This config enables linux core infrastructure for Application
+ processor subsystem (APSS) minidump collection i.e, it enables
+ Linux clients drivers to register their internal data structures
+ and debug messages as part of the apss minidump table and when
+ the SoC is crashed, these selective regions will be dumped
+ instead of the entire DDR dump. This saves significant amount
+ of time and/or storage space.
 endmenu
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index a5fd2fed0923..9c1a409679ec 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_QCOM_ICC_BWMON)  += icc-bwmon.o
 qcom_ice-objs  += ice.o
 obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE)+= qcom_ice.o
 obj-$(CONFIG_QCOM_RPROC_MINIDUMP)  += qcom_rproc_minidump.o
+obj-$(CONFIG_QCOM_MINIDUMP)+= qcom_minidump.o
diff --git a/drivers/soc/qcom/qcom_minidump.c b/drivers/soc/qcom/qcom_minidump.c
new file mode 100644
index ..86f4d09a7b4e
--- /dev/null
+++ b/drivers/soc/qcom/qcom_minidump.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "qcom_minidump_internal.h"
+
+/**
+ * struct minidump_ss_data - Minidump subsystem private data
+ * @md_ss_toc  : Application Subsystem TOC pointer
+ * @md_regions : Application Subsystem region base pointer
+ */
+struct minidump_ss_data {
+   struct minidump_subsystem   *md_ss_toc;
+   struct minidump_region  *md_regions;
+};
+
+/**
+ * struct minidump_elfhdr - Minidump table elf header
+ * @ehdr: elf main header
+ * @shdr: Section header
+ * @phdr: Program header
+ * @elf_offset: Section offset in elf
+ * @strtable_idx: String table current index position
+ */
+struct minidump_elfhdr {
+   struct elfhdr   *ehdr;
+   struct elf_shdr *shdr;

[PATCH v5 09/17] pstore/ram: Use dynamic ramoops reserve resource

2023-09-09 Thread Mukesh Ojha
As dynamic ramoops command line parsing is now added, so
lets add the support in ramoops driver to get the resource
structure and add it during platform device registration.

Signed-off-by: Mukesh Ojha 
---
 fs/pstore/ram.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 2f625e1fa8d8..e73fbbc1b5b5 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -913,13 +913,17 @@ static void __init ramoops_register_dummy(void)
 
/*
 * Prepare a dummy platform data structure to carry the module
-* parameters. If mem_size isn't set, then there are no module
-* parameters, and we can skip this.
+* parameters. If mem_size isn't set, check for dynamic ramoops
+* size and extract the information if it is set.
 */
-   if (!mem_size)
+   if (!mem_size && !dyn_ramoops_res.end)
return;
 
pr_info("using module parameters\n");
+   if (dyn_ramoops_res.end) {
+   mem_size = resource_size(&dyn_ramoops_res);
+   mem_address = dyn_ramoops_res.start;
+   }
 
memset(&pdata, 0, sizeof(pdata));
pdata.mem_size = mem_size;
-- 
2.7.4



[PATCH v5 14/17] pinctrl: qcom: Use qcom_scm_io_update_field()

2023-09-09 Thread Mukesh Ojha
Use qcom_scm_io_update_field() exported function in
pinctrl-msm driver.

Signed-off-by: Mukesh Ojha 
---
 drivers/pinctrl/qcom/pinctrl-msm.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c 
b/drivers/pinctrl/qcom/pinctrl-msm.c
index 115b83e2d8e6..2b9182375702 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1078,22 +1078,20 @@ static int msm_gpio_irq_set_type(struct irq_data *d, 
unsigned int type)
if (g->intr_target_width)
intr_target_mask = GENMASK(g->intr_target_width - 1, 0);
 
+   intr_target_mask <<= g->intr_target_bit;
if (pctrl->intr_target_use_scm) {
u32 addr = pctrl->phys_base[0] + g->intr_target_reg;
int ret;
 
-   qcom_scm_io_readl(addr, &val);
-   val &= ~(intr_target_mask << g->intr_target_bit);
-   val |= g->intr_target_kpss_val << g->intr_target_bit;
-
-   ret = qcom_scm_io_writel(addr, val);
+   val = g->intr_target_kpss_val << g->intr_target_bit;
+   ret = qcom_scm_io_update_field(addr, intr_target_mask, val);
if (ret)
dev_err(pctrl->dev,
"Failed routing %lu interrupt to Apps proc",
d->hwirq);
} else {
val = msm_readl_intr_target(pctrl, g);
-   val &= ~(intr_target_mask << g->intr_target_bit);
+   val &= ~intr_target_mask;
val |= g->intr_target_kpss_val << g->intr_target_bit;
msm_writel_intr_target(val, pctrl, g);
}
-- 
2.7.4



[PATCH v5 12/17] MAINTAINERS: Add entry for minidump related files

2023-09-09 Thread Mukesh Ojha
Add the entries into maintainer file for all the minidump related
modules.

Signed-off-by: Mukesh Ojha 
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d590ce31aa72..0595176e76fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17640,6 +17640,16 @@ S: Maintained
 F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
 F: drivers/regulator/vqmmc-ipq4019-regulator.c
 
+QUALCOMM MINIDUMP DRIVER
+M: Mukesh Ojha 
+L: linux-arm-...@vger.kernel.org
+S: Maintained
+F: Documentation/admin-guide/qcom_minidump.rst
+F: drivers/soc/qcom/qcom_rproc_minidump.c
+F: drivers/soc/qcom/qcom_minidump.c
+F: drivers/soc/qcom/qcom_ramoops_minidump.c
+
+
 QUALCOMM NAND CONTROLLER DRIVER
 M: Manivannan Sadhasivam 
 L: linux-...@lists.infradead.org
-- 
2.7.4



[PATCH v5 13/17] firmware: qcom_scm: provide a read-modify-write function

2023-09-09 Thread Mukesh Ojha
It was realized by Srinivas K. that there is a need of
read-modify-write scm exported function so that it can
be used by multiple clients.

Let's introduce qcom_scm_io_update_field() which masks
out the bits and write the passed value to that
bit-offset. Subsequent patch will use this function.

Suggested-by: Srinivas Kandagatla 
Signed-off-by: Mukesh Ojha 
---
 drivers/firmware/qcom_scm.c| 20 
 include/linux/firmware/qcom/qcom_scm.h |  2 ++
 2 files changed, 22 insertions(+)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index fde33acd46b7..5ea8fc4fd4e8 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -78,6 +78,7 @@ static const char * const qcom_scm_convention_names[] = {
 };
 
 static struct qcom_scm *__scm;
+static DEFINE_SPINLOCK(lock);
 
 static int qcom_scm_clk_enable(void)
 {
@@ -407,6 +408,25 @@ int qcom_scm_set_remote_state(u32 state, u32 id)
 }
 EXPORT_SYMBOL(qcom_scm_set_remote_state);
 
+int qcom_scm_io_update_field(phys_addr_t addr, unsigned int mask, unsigned int 
val)
+{
+   unsigned int old, new;
+   int ret;
+
+   spin_lock(&lock);
+   ret = qcom_scm_io_readl(addr, &old);
+   if (ret)
+   goto unlock;
+
+   new = (old & ~mask) | (val & mask);
+
+   ret = qcom_scm_io_writel(addr, new);
+unlock:
+   spin_unlock(&lock);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_scm_io_update_field);
+
 static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
 {
struct qcom_scm_desc desc = {
diff --git a/include/linux/firmware/qcom/qcom_scm.h 
b/include/linux/firmware/qcom/qcom_scm.h
index 250ea4efb7cb..ca41e4eb33ad 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -84,6 +84,8 @@ extern bool qcom_scm_pas_supported(u32 peripheral);
 
 extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
 extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
+extern int qcom_scm_io_update_field(phys_addr_t addr, unsigned int mask,
+   unsigned int val);
 
 extern bool qcom_scm_restore_sec_cfg_available(void);
 extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
-- 
2.7.4



[PATCH v5 16/17] firmware: qcom_scm: Refactor code to support multiple download mode

2023-09-09 Thread Mukesh Ojha
Currently on Qualcomm SoC, download_mode is enabled if
CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is selected.

Refactor the code such that it supports multiple download
modes and drop CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT config
instead, give interface to set the download mode from
module parameter.

Signed-off-by: Mukesh Ojha 
---
 drivers/firmware/Kconfig| 11 -
 drivers/firmware/qcom_scm.c | 56 +++--
 2 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index b59e3041fd62..ff7e9f330559 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -215,17 +215,6 @@ config MTK_ADSP_IPC
 config QCOM_SCM
tristate
 
-config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
-   bool "Qualcomm download mode enabled by default"
-   depends on QCOM_SCM
-   help
- A device with "download mode" enabled will upon an unexpected
- warm-restart enter a special debug mode that allows the user to
- "download" memory content over USB for offline postmortem analysis.
- The feature can be enabled/disabled on the kernel command line.
-
- Say Y here to enable "download mode" by default.
-
 config SYSFB
bool
select BOOT_VESA_SUPPORT
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index eda92f713019..689bf882cb69 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -20,13 +20,13 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include "qcom_scm.h"
 
-static bool download_mode = IS_ENABLED(CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT);
-module_param(download_mode, bool, 0);
+static u32 download_mode;
 
 #define SCM_HAS_CORE_CLK   BIT(0)
 #define SCM_HAS_IFACE_CLK  BIT(1)
@@ -83,6 +83,11 @@ static const char * const qcom_scm_convention_names[] = {
[SMC_CONVENTION_LEGACY] = "smc legacy",
 };
 
+static const char * const download_mode_name[] = {
+   [QCOM_DLOAD_NODUMP] = "off",
+   [QCOM_DLOAD_FULLDUMP]   = "full",
+};
+
 static struct qcom_scm *__scm;
 static DEFINE_SPINLOCK(lock);
 
@@ -448,9 +453,10 @@ static int __qcom_scm_set_dload_mode(struct device *dev, 
bool enable)
return qcom_scm_call_atomic(__scm->dev, &desc, NULL);
 }
 
-static void qcom_scm_set_download_mode(bool enable)
+static void qcom_scm_set_download_mode(u32 download_mode)
 {
-   u32 val = enable ? QCOM_DLOAD_FULLDUMP : QCOM_DLOAD_NODUMP;
+   bool enable = !!download_mode;
+   u32 val = download_mode;
bool avail;
int ret = 0;
 
@@ -1430,6 +1436,42 @@ static irqreturn_t qcom_scm_irq_handler(int irq, void 
*data)
return IRQ_HANDLED;
 }
 
+static int get_download_mode(char *buffer, const struct kernel_param *kp)
+{
+   if (download_mode >= ARRAY_SIZE(download_mode_name))
+   return sysfs_emit(buffer, "unknown mode\n");
+
+   return sysfs_emit(buffer, "%s\n", download_mode_name[download_mode]);
+}
+
+static int set_download_mode(const char *val, const struct kernel_param *kp)
+{
+   u32 old = download_mode;
+   int ret;
+
+   ret = sysfs_match_string(download_mode_name, val);
+   if (ret < 0) {
+   download_mode = old;
+   pr_err("qcom_scm: unknown download mode: %s\n", val);
+   return -EINVAL;
+   }
+
+   download_mode = ret;
+   if (__scm)
+   qcom_scm_set_download_mode(download_mode);
+
+   return 0;
+}
+
+static const struct kernel_param_ops download_mode_param_ops = {
+   .get = get_download_mode,
+   .set = set_download_mode,
+};
+
+module_param_cb(download_mode, &download_mode_param_ops, NULL, 0644);
+MODULE_PARM_DESC(download_mode,
+   "download mode: off/full are acceptable values");
+
 static int qcom_scm_probe(struct platform_device *pdev)
 {
struct qcom_scm *scm;
@@ -1523,12 +1565,12 @@ static int qcom_scm_probe(struct platform_device *pdev)
__get_convention();
 
/*
-* If requested enable "download mode", from this point on warmboot
+* If "download mode" is requested, from this point on warmboot
 * will cause the boot stages to enter download mode, unless
 * disabled below by a clean shutdown/reboot.
 */
if (download_mode)
-   qcom_scm_set_download_mode(true);
+   qcom_scm_set_download_mode(download_mode);
 
return 0;
 }
@@ -1536,7 +1578,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
 static void qcom_scm_shutdown(struct platform_device *pdev)
 {
/* Clean shutdown, disable download mode to allow normal restart */
-   qcom_scm_set_download_mode(false);
+   qcom_scm_set_download_mode(QCOM_DLOAD_NODUMP);
 }
 
 static const struct of_device_id qcom_scm_dt_match[] = {
-- 
2.7.4



[PATCH v5 17/17] firmware: qcom_scm: Add multiple download mode support

2023-09-09 Thread Mukesh Ojha
Currently, scm driver only supports full dump when download
mode is selected. Add support to enable minidump as well as
enable it along with fulldump.

Signed-off-by: Mukesh Ojha 
---
 drivers/firmware/qcom_scm.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 689bf882cb69..9faf0431d47a 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -34,6 +34,8 @@ static u32 download_mode;
 
 #define QCOM_DLOAD_MASKGENMASK(5, 4)
 #define QCOM_DLOAD_FULLDUMP0x1
+#define QCOM_DLOAD_MINIDUMP0x2
+#define QCOM_DLOAD_BOTHDUMP(QCOM_DLOAD_FULLDUMP | QCOM_DLOAD_MINIDUMP)
 #define QCOM_DLOAD_NODUMP  0x0
 
 struct qcom_scm {
@@ -86,6 +88,8 @@ static const char * const qcom_scm_convention_names[] = {
 static const char * const download_mode_name[] = {
[QCOM_DLOAD_NODUMP] = "off",
[QCOM_DLOAD_FULLDUMP]   = "full",
+   [QCOM_DLOAD_MINIDUMP]   = "mini",
+   [QCOM_DLOAD_BOTHDUMP]   = "full,mini",
 };
 
 static struct qcom_scm *__scm;
@@ -1470,7 +1474,7 @@ static const struct kernel_param_ops 
download_mode_param_ops = {
 
 module_param_cb(download_mode, &download_mode_param_ops, NULL, 0644);
 MODULE_PARM_DESC(download_mode,
-   "download mode: off/full are acceptable values");
+   "download mode: off/full/mini/full,mini are acceptable values");
 
 static int qcom_scm_probe(struct platform_device *pdev)
 {
-- 
2.7.4



[PATCH v5 15/17] firmware: scm: Modify only the download bits in TCSR register

2023-09-09 Thread Mukesh Ojha
Crashdump collection is based on the DLOAD bit of TCSR register.
To retain other bits, we read the register and modify only the
DLOAD bit as the other bits have their own significance.

Co-developed-by: Poovendhan Selvaraj 
Signed-off-by: Mukesh Ojha 
---
 drivers/firmware/qcom_scm.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 5ea8fc4fd4e8..eda92f713019 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -5,6 +5,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +32,10 @@ module_param(download_mode, bool, 0);
 #define SCM_HAS_IFACE_CLK  BIT(1)
 #define SCM_HAS_BUS_CLKBIT(2)
 
+#define QCOM_DLOAD_MASKGENMASK(5, 4)
+#define QCOM_DLOAD_FULLDUMP0x1
+#define QCOM_DLOAD_NODUMP  0x0
+
 struct qcom_scm {
struct device *dev;
struct clk *core_clk;
@@ -444,6 +450,7 @@ static int __qcom_scm_set_dload_mode(struct device *dev, 
bool enable)
 
 static void qcom_scm_set_download_mode(bool enable)
 {
+   u32 val = enable ? QCOM_DLOAD_FULLDUMP : QCOM_DLOAD_NODUMP;
bool avail;
int ret = 0;
 
@@ -453,8 +460,9 @@ static void qcom_scm_set_download_mode(bool enable)
if (avail) {
ret = __qcom_scm_set_dload_mode(__scm->dev, enable);
} else if (__scm->dload_mode_addr) {
-   ret = qcom_scm_io_writel(__scm->dload_mode_addr,
-   enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0);
+   ret = qcom_scm_io_update_field(__scm->dload_mode_addr,
+  QCOM_DLOAD_MASK,
+  FIELD_PREP(QCOM_DLOAD_MASK, 
val));
} else {
dev_err(__scm->dev,
"No available mechanism for setting download mode\n");
-- 
2.7.4



[PATCH v5 11/17] qcom_minidump: Register ramoops region with minidump

2023-09-09 Thread Mukesh Ojha
Register all the pstore frontend with minidump, so that they can
be dumped as default Linux minidump region to be collected on
SoC where minidump is enabled.

Helper functions is written in separate file and built along with
the minidump driver, since it is client of minidump and also call
it at appropriate place from minidump probe so that they always
get registered.

While at it also rename the out minidump module object name during
build as qcom_apss_minidump which basically depicts as Qualcomm
Application processor subsystem minidump.

Signed-off-by: Mukesh Ojha 
---
 drivers/soc/qcom/Kconfig |  1 +
 drivers/soc/qcom/Makefile|  3 +-
 drivers/soc/qcom/qcom_minidump.c |  4 ++
 drivers/soc/qcom/qcom_ramoops_minidump.c | 88 
 drivers/soc/qcom/qcom_ramoops_minidump.h | 10 
 5 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soc/qcom/qcom_ramoops_minidump.c
 create mode 100644 drivers/soc/qcom/qcom_ramoops_minidump.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 4b36d46807bc..b3977f1687d8 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -305,6 +305,7 @@ config QCOM_MINIDUMP
tristate "QCOM APSS Minidump driver"
depends on ARCH_QCOM || COMPILE_TEST
depends on QCOM_SMEM
+   depends on PSTORE
help
  This config enables linux core infrastructure for Application
  processor subsystem (APSS) minidump collection i.e, it enables
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 9c1a409679ec..fca80df8b5b1 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -36,4 +36,5 @@ obj-$(CONFIG_QCOM_ICC_BWMON)  += icc-bwmon.o
 qcom_ice-objs  += ice.o
 obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE)+= qcom_ice.o
 obj-$(CONFIG_QCOM_RPROC_MINIDUMP)  += qcom_rproc_minidump.o
-obj-$(CONFIG_QCOM_MINIDUMP)+= qcom_minidump.o
+obj-$(CONFIG_QCOM_MINIDUMP)+= qcom_apss_minidump.o
+qcom_apss_minidump-objs+= qcom_minidump.o 
qcom_ramoops_minidump.o
diff --git a/drivers/soc/qcom/qcom_minidump.c b/drivers/soc/qcom/qcom_minidump.c
index 4ce36f154e89..7930a80b9100 100644
--- a/drivers/soc/qcom/qcom_minidump.c
+++ b/drivers/soc/qcom/qcom_minidump.c
@@ -23,6 +23,7 @@
 #include 
 
 #include "qcom_minidump_internal.h"
+#include "qcom_ramoops_minidump.h"
 
 /**
  * struct minidump_ss_data - Minidump subsystem private data
@@ -688,6 +689,8 @@ static int qcom_apss_minidump_probe(struct platform_device 
*pdev)
return ret;
}
 
+   qcom_ramoops_minidump_register(md->dev);
+
mutex_lock(&md_plist.plock);
platform_set_drvdata(pdev, md);
qcom_apss_register_pending_regions(md);
@@ -701,6 +704,7 @@ static int qcom_apss_minidump_remove(struct platform_device 
*pdev)
struct minidump *md = platform_get_drvdata(pdev);
struct minidump_ss_data *mdss_data;
 
+   qcom_ramoops_minidump_unregister();
mdss_data = md->apss_data;
memset(mdss_data->md_ss_toc, cpu_to_le32(0), sizeof(struct 
minidump_subsystem));
md = NULL;
diff --git a/drivers/soc/qcom/qcom_ramoops_minidump.c 
b/drivers/soc/qcom/qcom_ramoops_minidump.c
new file mode 100644
index ..eb97310e3858
--- /dev/null
+++ b/drivers/soc/qcom/qcom_ramoops_minidump.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "qcom_ramoops_minidump.h"
+
+static LIST_HEAD(ramoops_region_list);
+
+struct md_region_list {
+   struct qcom_minidump_region md_region;
+   struct list_head list;
+};
+
+static int qcom_ramoops_region_register(struct device *dev, int type)
+{
+   struct qcom_minidump_region *md_region;
+   struct md_region_list *mdr_list;
+   struct pstore_record record;
+   unsigned int max_dump_cnt;
+   phys_addr_t phys;
+   const char *name;
+   void *virt;
+   size_t size;
+   int ret;
+
+   record.type = type;
+   record.id = 0;
+   max_dump_cnt = 0;
+   name = pstore_type_to_name(record.type);
+   do {
+   ret = pstore_region_defined(&record, &virt, &phys, &size, 
&max_dump_cnt);
+   if (ret < 0)
+   break;
+
+   mdr_list = devm_kzalloc(dev, sizeof(struct md_region_list), 
GFP_KERNEL);
+   if (!mdr_list)
+   return -ENOMEM;
+
+   md_region = &mdr_list->md_region;
+   scnprintf(md_region->name, sizeof(md_region->name) - 1, 
"K%s%llu", name, record.id);
+   md_region->virt_addr = virt;
+   md_region->phys_addr = phys;
+   md_region->size = size;
+   ret = qcom_minidump

[PATCH v5 10/17] pstore: Add pstore_region_defined() helper and export it

2023-09-09 Thread Mukesh Ojha
There are users like Qualcomm minidump which is interested in
knowing the pstore frontend addresses and sizes from the backend
(ram) to be able to register it with firmware to finally collect
them during crash for debugging.

Signed-off-by: Mukesh Ojha 
---
 fs/pstore/platform.c   | 15 +++
 fs/pstore/ram.c| 42 ++
 include/linux/pstore.h |  6 ++
 3 files changed, 63 insertions(+)

diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index cbc0b468c1ab..cb80116a05cb 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -137,6 +137,21 @@ enum pstore_type_id pstore_name_to_type(const char *name)
 }
 EXPORT_SYMBOL_GPL(pstore_name_to_type);
 
+int pstore_region_defined(struct pstore_record *record,
+ void **virt, phys_addr_t *phys,
+ size_t *size, unsigned int *max_dump_cnt)
+{
+   if (!psinfo)
+   return -EINVAL;
+
+   record->psi = psinfo;
+
+   return psinfo->region_info ?
+  psinfo->region_info(record, virt, phys, size, max_dump_cnt) :
+  -EINVAL;
+}
+EXPORT_SYMBOL_GPL(pstore_region_defined);
+
 static void pstore_timer_kick(void)
 {
if (pstore_update_ms < 0)
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index e73fbbc1b5b5..2ebb1f5f6350 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -436,6 +436,47 @@ static int ramoops_pstore_erase(struct pstore_record 
*record)
return 0;
 }
 
+static int ramoops_region_info(struct pstore_record *record,
+  void **virt, phys_addr_t *phys,
+  size_t *size, unsigned int *max_dump_cnt)
+{
+   struct ramoops_context *cxt = record->psi->data;
+   struct persistent_ram_zone *prz;
+
+   switch (record->type) {
+   case PSTORE_TYPE_DMESG:
+   if (record->id >= cxt->max_dump_cnt)
+   return -EINVAL;
+   prz = cxt->dprzs[record->id];
+   *max_dump_cnt = cxt->max_dump_cnt;
+   break;
+   case PSTORE_TYPE_CONSOLE:
+   if (!cxt->console_size)
+   return -EINVAL;
+   prz = cxt->cprz;
+   break;
+   case PSTORE_TYPE_FTRACE:
+   if (record->id >= cxt->max_ftrace_cnt)
+   return -EINVAL;
+   prz = cxt->fprzs[record->id];
+   *max_dump_cnt = cxt->max_ftrace_cnt;
+   break;
+   case PSTORE_TYPE_PMSG:
+   if (!cxt->pmsg_size)
+   return -EINVAL;
+   prz = cxt->mprz;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   *virt = prz->vaddr;
+   *phys = prz->paddr;
+   *size = prz->size;
+
+   return 0;
+}
+
 static struct ramoops_context oops_cxt = {
.pstore = {
.owner  = THIS_MODULE,
@@ -445,6 +486,7 @@ static struct ramoops_context oops_cxt = {
.write  = ramoops_pstore_write,
.write_user = ramoops_pstore_write_user,
.erase  = ramoops_pstore_erase,
+   .region_info = ramoops_region_info,
},
 };
 
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 638507a3c8ff..a64d866e8711 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -199,6 +199,9 @@ struct pstore_info {
int (*write_user)(struct pstore_record *record,
  const char __user *buf);
int (*erase)(struct pstore_record *record);
+   int (*region_info)(struct pstore_record *record,
+  void **virt, phys_addr_t *phys,
+  size_t *size, unsigned int 
*max_dump_cnt);
 };
 
 /* Supported frontends */
@@ -230,6 +233,9 @@ struct pstore_ftrace_record {
 #define TS_CPU_SHIFT 8
 #define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1)
 
+int pstore_region_defined(struct pstore_record *record,
+ void **virt, phys_addr_t *phys,
+ size_t *size, unsigned int *max_dump_cnt);
 /*
  * If CPU number can be stored in IP, store it there, otherwise store it in
  * the time stamp. This means more timestamp resolution is available when
-- 
2.7.4



[PATCH v5 08/17] arm64: mm: Add dynamic ramoops region support through command line

2023-09-09 Thread Mukesh Ojha
The reserved memory region for ramoops is assumed to be at a fixed
and known location when read from the devicetree. This may not be
required for something like Qualcomm's minidump which is interested
in knowing addresses of ramoops region but it does not put hard
requirement of address being fixed as most of it's SoC does not
support warm reset and does not use pstorefs at all instead it has
firmware way of collecting ramoops region if it gets to know the
address and register it with apss minidump table which is sitting
in shared memory region in DDR and firmware will have access to
these table during reset and collects it on crash of SoC.

So, add the support of reserving ramoops region to be dynamically
allocated early during boot if it is request through command line
via 'dyn_ramoops_size=' and fill up reserved resource structure and
export the structure, so that it can be read by ramoops driver.

Signed-off-by: Mukesh Ojha 
---
 arch/arm64/mm/init.c   | 94 ++
 include/linux/pstore_ram.h |  2 +
 2 files changed, 96 insertions(+)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index d31c3a9290c5..14d7086758bf 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -73,6 +74,93 @@ phys_addr_t __ro_after_init arm64_dma_phys_limit;
 
 #define DEFAULT_CRASH_KERNEL_LOW_SIZE  (128UL << 20)
 
+#define RAMOOPS_ADDR_HIGH_MAX  (PHYS_MASK + 1)
+
+/* Location of the reserved area for the dynamic ramoops */
+struct resource dyn_ramoops_res = {
+   .name  = "ramoops",
+   .start = 0,
+   .end   = 0,
+   .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
+   .desc  = IORES_DESC_NONE,
+};
+EXPORT_SYMBOL(dyn_ramoops_res);
+
+static int __init parse_dynamic_ramoops(char *cmdline, unsigned long long 
*size)
+{
+   const char *name = "dyn_ramoops_size=";
+   char *p = NULL;
+   char *q = NULL;
+   char *tmp;
+
+   if (!cmdline)
+   return -ENOENT;
+
+   /* Check for "dyn_ramoops_size" and use the later if there are more */
+   p = strstr(cmdline, name);
+   while (p) {
+   q = p;
+   p = strchr(p, ' ');
+   if (!p)
+   break;
+
+   p = strstr(p + 1, name);
+   }
+
+   if (!q) {
+   pr_err("ramoops: No entry found for %s\n", name);
+   return -ENOENT;
+   }
+
+   p = q + strlen(name);
+   *size = memparse(p, &tmp);
+   if (p == tmp) {
+   pr_err("ramoops: memory value expected\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int __init parse_dyn_ramoops_size_dummy(char *arg)
+{
+   return 0;
+}
+early_param("dyn_ramoops_size", parse_dyn_ramoops_size_dummy);
+
+/*
+ * reserve_dynamic_ramoops() - reserves memory for dynamic ramoops
+ *
+ * This enable dynamic reserve memory support for ramoops through
+ * command line.
+ */
+static void __init reserve_dynamic_ramoops(void)
+{
+   char *cmdline = boot_command_line;
+   unsigned long long ramoops_base;
+   unsigned long long ramoops_size;
+
+   if (!IS_ENABLED(CONFIG_PSTORE_RAM))
+   return;
+
+   if (parse_dynamic_ramoops(cmdline, &ramoops_size))
+   return;
+
+   ramoops_base = memblock_phys_alloc_range(ramoops_size, SMP_CACHE_BYTES,
+0, RAMOOPS_ADDR_HIGH_MAX);
+   if (!ramoops_base) {
+   pr_err("cannot allocate ramoops dynamic memory 
(size:0x%llx).\n",
+   ramoops_size);
+   return;
+   }
+
+   kmemleak_ignore_phys(ramoops_base);
+
+   dyn_ramoops_res.start = ramoops_base;
+   dyn_ramoops_res.end = ramoops_base + ramoops_size - 1;
+   insert_resource(&iomem_resource, &dyn_ramoops_res);
+}
+
 static int __init reserve_crashkernel_low(unsigned long long low_size)
 {
unsigned long long low_base;
@@ -456,6 +544,12 @@ void __init bootmem_init(void)
 */
reserve_crashkernel();
 
+   /*
+* Reserving ramoops region resource dynamically in case it is
+* requested from command line.
+*/
+   reserve_dynamic_ramoops();
+
memblock_dump_all();
 }
 
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9d65ff94e216..07d700b7649d 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -10,6 +10,8 @@
 
 #include 
 
+extern struct resource dyn_ramoops_res;
+
 struct persistent_ram_ecc_info {
int block_size;
int ecc_size;
-- 
2.7.4



[RFC 0/8] mm/damon: implement DAMOS apply intervals

2023-09-09 Thread SeongJae Park
DAMON-based operation schemes are applied for every aggregation
interval.  That is mainly because schemes are using nr_accesses, which
be complete to be used for every aggregation interval.  However, DAMON
provides nr_accesses_bp, which is updated for each sampling interval in
a way that reasonable to be used.  Therefore, there is no reason to not
use nr_accesses_bp instead and apply schemes for their own time interval
instead of the aggregation interval.

Actually, the alignment with the aggregation interval is also making
some use case of DAMOS tricky.  Quota setting under long aggregation
interval is one such example.  Suppose the aggregation interval is ten
seconds, and there is a scheme having CPU quota 100ms per 1s.  The
scheme will actually uses 100ms per ten seconds, since it cannobe be
applied before next aggregation interval.  The feature is working as
intended, but the results might not that intuitive for some users.  This
could be fixed by updating the quota to 1s per 10s.  But, in the case,
the CPU usage of DAMOS could look like spikes, and actually make a bad
effect to other CPU-sensitive workloads.

This patchset makes DAMOS schemes to use nr_accesses_bp instead of
nr_accesses, and have their own timing intervals.  Note that the
interval is 0 by default, and it is interpreted to use the aggregation
interval instead.  This is for avoid making behavioral changes to the
old users.


Patches Seuqeunce
-

The first patch (patch 1/8) makes DAMOS uses nr_accesses_bp instead of
nr_accesses, and following two patches (patches 2/8 and 3/8) updates DAMON
sysfs interface for DAMOS tried regions and the DAMOS before_apply
tracespoint to expose nr_accesses_bp instead of nr_accesses,
respectively.

The following two patches (patches 4/8 and 5/8) implements the
scheme-specific apply interval for DAMON kernel API users and update the
design document for the new feature.  Finally, the following three
patches (patches 6/8, 7/8, and 8/8) add support of the feature in DAMON
sysfs interface and documents it on usage and ABI documents,
repsectively.

SeongJae Park (8):
  mm/damon/core: make DAMOS uses nr_accesses_bp instead of nr_accesses
  mm/damon/sysfs-schemes: expose nr_accesses_bp via
tried_regions//nr_accesses
  mm/damon/core: expose nr_accesses_bp from damos_before_apply
tracepoint
  mm/damon/core: implement scheme-specific apply interval
  Docs/mm/damon/design: document DAMOS apply intervals
  mm/damon/sysfs-schemes: support DAMOS apply interval
  Docs/admin-guide/mm/damon/usage: update for DAMOS apply intervals
  Docs/ABI/damon: update for DAMOS apply intervals

 .../ABI/testing/sysfs-kernel-mm-damon |  7 ++
 Documentation/admin-guide/mm/damon/usage.rst  |  9 ++-
 Documentation/mm/damon/design.rst |  3 +-
 include/linux/damon.h | 17 +++-
 include/trace/events/damon.h  |  2 +-
 mm/damon/core.c   | 80 +--
 mm/damon/dbgfs.c  |  3 +-
 mm/damon/lru_sort.c   |  2 +
 mm/damon/reclaim.c|  2 +
 mm/damon/sysfs-schemes.c  | 40 --
 10 files changed, 144 insertions(+), 21 deletions(-)


base-commit: 2a43f312aed581fa5044c4a0c0d20cfd4e632aa6
-- 
2.25.1