summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurora zuma automerger <aurora-zuma-automerger@google.com>2023-02-02 09:28:41 +0000
committerCopybara-Service <copybara-worker@google.com>2023-02-02 01:56:33 -0800
commit77edbbfcd394cd9844ba7e675ed4e5358d6cf8b4 (patch)
treed0b0721d694bbd62e9d446e1b7fbda9e129f4626
parentdf93ed835156837cd4c6e2dfd32d34e015250055 (diff)
downloadzuma-77edbbfcd394cd9844ba7e675ed4e5358d6cf8b4.tar.gz
gxp: [Copybara Auto Merge] Merge branch 'zuma' into 'android14-gs-pixel-5.15'
gxp: create debug dir root earlier on probe gxp: fix code style/formatting issues gxp: Implement debug dump handling for mcu mode Bug: 265092842 gcip: fix code style/formatting issues GCIP_HEADERS_REV_ID: 8f57799df52bf60cb1805ab5e9ee48034bb139c8 GitOrigin-RevId: a40874e012eca6f104c74e754d7c10ae0284772b Change-Id: Id15d4c14d7964ed7a52771ba7d6e9dfa992f4cd1
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-image-config.h16
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-kci.h10
-rw-r--r--gxp-common-platform.c7
-rw-r--r--gxp-debug-dump.c82
-rw-r--r--gxp-debug-dump.h47
-rw-r--r--gxp-debugfs.c17
-rw-r--r--gxp-debugfs.h7
-rw-r--r--gxp-firmware-data.c2
-rw-r--r--gxp-firmware.c6
-rw-r--r--gxp-kci.c26
-rw-r--r--gxp-mcu-firmware.c4
-rw-r--r--gxp-vd.c34
-rw-r--r--gxp-vd.h15
13 files changed, 211 insertions, 62 deletions
diff --git a/gcip-kernel-driver/include/gcip/gcip-image-config.h b/gcip-kernel-driver/include/gcip/gcip-image-config.h
index 1d00ef9..bcc506f 100644
--- a/gcip-kernel-driver/include/gcip/gcip-image-config.h
+++ b/gcip-kernel-driver/include/gcip/gcip-image-config.h
@@ -92,27 +92,19 @@ struct gcip_image_config_parser {
/* For decoding the size of ns_iommu_mappings. */
static inline u32 gcip_ns_config_to_size(u32 cfg)
{
- u32 size;
-
if (cfg & GCIP_IMG_CFG_SIZE_MODE_BIT)
- size = (cfg & GCIP_IMG_CFG_NS_SIZE_MASK) << PAGE_SHIFT;
- else
- size = (cfg & GCIP_IMG_CFG_NS_SIZE_MASK) << GCIP_IMG_CFG_MB_SHIFT;
+ return (cfg & GCIP_IMG_CFG_NS_SIZE_MASK) << PAGE_SHIFT;
- return size;
+ return (cfg & GCIP_IMG_CFG_NS_SIZE_MASK) << GCIP_IMG_CFG_MB_SHIFT;
}
/* For decoding the size of iommu_mappings. */
static inline u32 gcip_config_to_size(u32 cfg)
{
- u32 page_size;
-
if (cfg & GCIP_IMG_CFG_SIZE_MODE_BIT)
- page_size = cfg & GCIP_IMG_CFG_SECURE_SIZE_MASK;
- else
- page_size = BIT(cfg & GCIP_IMG_CFG_SECURE_SIZE_MASK);
+ return (cfg & GCIP_IMG_CFG_SECURE_SIZE_MASK) << PAGE_SHIFT;
- return page_size << PAGE_SHIFT;
+ return BIT(cfg & GCIP_IMG_CFG_SECURE_SIZE_MASK) << PAGE_SHIFT;
}
/*
diff --git a/gcip-kernel-driver/include/gcip/gcip-kci.h b/gcip-kernel-driver/include/gcip/gcip-kci.h
index 3649779..c95d6a7 100644
--- a/gcip-kernel-driver/include/gcip/gcip-kci.h
+++ b/gcip-kernel-driver/include/gcip/gcip-kci.h
@@ -109,11 +109,11 @@ enum gcip_kci_code {
*/
enum gcip_reverse_kci_code {
GCIP_RKCI_CHIP_CODE_FIRST = 0,
- GCIP_RKCI_PM_QOS_REQUEST = GCIP_RKCI_CHIP_CODE_FIRST + 1,
- GCIP_RKCI_CHANGE_BTS_SCENARIO = GCIP_RKCI_CHIP_CODE_FIRST + 2,
- GCIP_RKCI_PM_QOS_BTS_REQUEST = GCIP_RKCI_CHIP_CODE_FIRST + 3,
- GCIP_RKCI_DSP_CORE_TELEMETRY_TRY_READ = GCIP_RKCI_CHIP_CODE_FIRST + 4,
- GCIP_RKCI_CLIENT_FATAL_ERROR_NOTIFY = GCIP_RKCI_CHIP_CODE_FIRST + 5,
+ GCIP_RKCI_PM_QOS_REQUEST,
+ GCIP_RKCI_CHANGE_BTS_SCENARIO,
+ GCIP_RKCI_PM_QOS_BTS_REQUEST,
+ GCIP_RKCI_DSP_CORE_TELEMETRY_TRY_READ,
+ GCIP_RKCI_CLIENT_FATAL_ERROR_NOTIFY,
GCIP_RKCI_CHIP_CODE_LAST = 0x7FFF,
GCIP_RKCI_GENERIC_CODE_FIRST = 0x8000,
GCIP_RKCI_FIRMWARE_CRASH = GCIP_RKCI_GENERIC_CODE_FIRST + 0,
diff --git a/gxp-common-platform.c b/gxp-common-platform.c
index 369d4b2..e8c5572 100644
--- a/gxp-common-platform.c
+++ b/gxp-common-platform.c
@@ -1908,10 +1908,11 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de
if (ret)
return ret;
+ gxp_create_debugdir(gxp);
ret = gxp_wakelock_init(gxp);
if (ret) {
dev_err(dev, "failed to init wakelock: %d", ret);
- return ret;
+ goto err_remove_debugdir;
}
ret = gxp_pm_init(gxp);
@@ -2063,6 +2064,8 @@ err_put_tpu_dev:
gxp_pm_destroy(gxp);
err_wakelock_destroy:
/* wakelock init doesn't need revert */
+err_remove_debugdir:
+ gxp_remove_debugdir(gxp);
return ret;
}
@@ -2070,7 +2073,7 @@ static int gxp_common_platform_remove(struct platform_device *pdev)
{
struct gxp_dev *gxp = platform_get_drvdata(pdev);
- gxp_remove_debugfs(gxp);
+ gxp_remove_debugdir(gxp);
misc_deregister(&gxp->misc_dev);
if (gxp->before_remove)
gxp->before_remove(gxp);
diff --git a/gxp-debug-dump.c b/gxp-debug-dump.c
index 36b8a23..5589ea3 100644
--- a/gxp-debug-dump.c
+++ b/gxp-debug-dump.c
@@ -18,6 +18,7 @@
#include <linux/platform_data/sscoredump.h>
#endif
+#include "gxp-client.h"
#include "gxp-debug-dump.h"
#include "gxp-dma.h"
#include "gxp-doorbell.h"
@@ -366,7 +367,12 @@ static void gxp_user_buffers_vunmap(struct gxp_dev *gxp,
* gxp->core_to_vd[], and up_read(&gxp->vd_semaphore) must be re-added
* after.
*/
- vd = gxp->core_to_vd[core_header->core_id];
+ if (gxp_is_direct_mode(gxp)) {
+ vd = gxp->core_to_vd[core_header->core_id];
+ } else {
+ vd = gxp->debug_dump_mgr
+ ->crashed_core_to_vd[core_header->core_id];
+ }
if (!vd) {
dev_err(gxp->dev,
"Virtual device is not available for vunmap\n");
@@ -414,7 +420,12 @@ static int gxp_user_buffers_vmap(struct gxp_dev *gxp,
* gxp->core_to_vd[], and up_read(&gxp->vd_semaphore) must be re-added
* after.
*/
- vd = gxp->core_to_vd[core_header->core_id];
+ if (gxp_is_direct_mode(gxp)) {
+ vd = gxp->core_to_vd[core_header->core_id];
+ } else {
+ vd = gxp->debug_dump_mgr
+ ->crashed_core_to_vd[core_header->core_id];
+ }
if (!vd) {
dev_err(gxp->dev, "Virtual device is not available for vmap\n");
goto out;
@@ -468,7 +479,7 @@ out:
}
#endif
-static void gxp_invalidate_segments(struct gxp_dev *gxp, uint32_t core_id)
+void gxp_debug_dump_invalidate_segments(struct gxp_dev *gxp, uint32_t core_id)
{
int i;
struct gxp_debug_dump_manager *mgr = gxp->debug_dump_mgr;
@@ -581,6 +592,10 @@ static int gxp_handle_debug_dump(struct gxp_dev *gxp, uint32_t core_id)
ret = -EFAULT;
goto out_efault;
}
+ /*
+ * TODO(b/265105909): Implement the logic for collecting fw rw section
+ * separately for mcu mode.
+ */
mgr->segs[core_id][seg_idx].addr = gxp->fwbufs[core_id].vaddr;
mgr->segs[core_id][seg_idx].size = gxp->fwbufs[core_id].size;
seg_idx++;
@@ -613,7 +628,7 @@ out_efault:
#endif
out:
- gxp_invalidate_segments(gxp, core_id);
+ gxp_debug_dump_invalidate_segments(gxp, core_id);
return ret;
}
@@ -663,18 +678,15 @@ out:
return ret;
}
-static void gxp_debug_dump_process_dump(struct work_struct *work)
+static void gxp_generate_debug_dump(struct gxp_dev *gxp, uint core_id,
+ struct gxp_virtual_device *crashed_vd)
{
- struct gxp_debug_dump_work *debug_dump_work =
- container_of(work, struct gxp_debug_dump_work, work);
-
- uint core_id = debug_dump_work->core_id;
- struct gxp_dev *gxp = debug_dump_work->gxp;
u32 boot_mode;
bool gxp_generate_coredump_called = false;
mutex_lock(&gxp->debug_dump_mgr->debug_dump_lock);
-
+ /* crashed_core_to_vd[] is only relevant in case of mcu mode.*/
+ gxp->debug_dump_mgr->crashed_core_to_vd[core_id] = crashed_vd;
/*
* Lock the VD semaphore to ensure no suspend/resume/start/stop requests
* can be made on core `core_id` while generating debug dump.
@@ -685,8 +697,11 @@ static void gxp_debug_dump_process_dump(struct work_struct *work)
*/
down_read(&gxp->vd_semaphore);
- /* TODO(b/234172464): pass proper VD */
- boot_mode = gxp_firmware_get_boot_mode(gxp, NULL, core_id);
+ /*
+ * TODO(b/265105909): Checks below to be verified after implementation for
+ * firmware loading for mcu mode are completed.
+ */
+ boot_mode = gxp_firmware_get_boot_mode(gxp, crashed_vd, core_id);
if (gxp_is_fw_running(gxp, core_id) &&
(boot_mode == GXP_BOOT_MODE_STATUS_COLD_BOOT_COMPLETED ||
@@ -697,7 +712,7 @@ static void gxp_debug_dump_process_dump(struct work_struct *work)
}
/* Invalidate segments to prepare for the next debug dump trigger */
- gxp_invalidate_segments(gxp, core_id);
+ gxp_debug_dump_invalidate_segments(gxp, core_id);
up_read(&gxp->vd_semaphore);
@@ -710,9 +725,46 @@ static void gxp_debug_dump_process_dump(struct work_struct *work)
if (gxp_generate_coredump_called)
msleep(1000);
+ /* crashed_core_to_vd[] is only relevant in case of mcu mode.*/
+ gxp->debug_dump_mgr->crashed_core_to_vd[core_id] = NULL;
mutex_unlock(&gxp->debug_dump_mgr->debug_dump_lock);
}
+static void gxp_debug_dump_process_dump(struct work_struct *work)
+{
+ struct gxp_debug_dump_work *debug_dump_work =
+ container_of(work, struct gxp_debug_dump_work, work);
+ uint core_id = debug_dump_work->core_id;
+ struct gxp_dev *gxp = debug_dump_work->gxp;
+
+ gxp_generate_debug_dump(gxp, core_id, NULL /*Not used*/);
+}
+
+int gxp_debug_dump_process_dump_mcu_mode(struct gxp_dev *gxp, uint core_list,
+ struct gxp_virtual_device *crashed_vd)
+{
+ uint core;
+ struct gxp_core_dump_header *core_dump_header;
+ struct gxp_debug_dump_manager *mgr = gxp->debug_dump_mgr;
+
+ if (crashed_vd->state != GXP_VD_UNAVAILABLE) {
+ dev_dbg(gxp->dev, "Invalid vd state=%u for processing dumps.\n",
+ crashed_vd->state);
+ return -EINVAL;
+ }
+
+ for (core = 0; core < GXP_NUM_CORES; core++) {
+ if (!(BIT(core) & core_list))
+ continue;
+ core_dump_header = &mgr->core_dump->core_dump_header[core];
+ /* Check if dump has been generated by core firmware */
+ if (core_dump_header &&
+ core_dump_header->core_header.dump_available == 1)
+ gxp_generate_debug_dump(gxp, core, crashed_vd);
+ }
+ return 0;
+}
+
struct work_struct *gxp_debug_dump_get_notification_handler(struct gxp_dev *gxp,
uint core)
{
@@ -759,7 +811,7 @@ int gxp_debug_dump_init(struct gxp_dev *gxp, void *sscd_dev, void *sscd_pdata)
gxp_init_segments(gxp);
for (core = 0; core < GXP_NUM_CORES; core++) {
- gxp_invalidate_segments(gxp, core);
+ gxp_debug_dump_invalidate_segments(gxp, core);
mgr->debug_dump_works[core].gxp = gxp;
mgr->debug_dump_works[core].core_id = core;
INIT_WORK(&mgr->debug_dump_works[core].work,
diff --git a/gxp-debug-dump.h b/gxp-debug-dump.h
index 2a5d1ce..66ab782 100644
--- a/gxp-debug-dump.h
+++ b/gxp-debug-dump.h
@@ -23,22 +23,22 @@
#define GXP_NUM_CORE_SEGMENTS 8
#define GXP_NUM_BUFFER_MAPPINGS 32
#define GXP_SEG_HEADER_NAME_LENGTH 32
-#define GXP_NUM_SEGMENTS_PER_CORE \
- (GXP_NUM_COMMON_SEGMENTS + GXP_NUM_CORE_SEGMENTS + \
+#define GXP_NUM_SEGMENTS_PER_CORE \
+ (GXP_NUM_COMMON_SEGMENTS + GXP_NUM_CORE_SEGMENTS + \
GXP_NUM_BUFFER_MAPPINGS + 1)
#define GXP_Q7_ICACHE_SIZE 131072 /* I-cache size in bytes */
#define GXP_Q7_ICACHE_LINESIZE 64 /* I-cache line size in bytes */
#define GXP_Q7_ICACHE_WAYS 4
-#define GXP_Q7_ICACHE_SETS ((GXP_Q7_ICACHE_SIZE / GXP_Q7_ICACHE_WAYS) / \
- GXP_Q7_ICACHE_LINESIZE)
+#define GXP_Q7_ICACHE_SETS \
+ ((GXP_Q7_ICACHE_SIZE / GXP_Q7_ICACHE_WAYS) / GXP_Q7_ICACHE_LINESIZE)
#define GXP_Q7_ICACHE_WORDS_PER_LINE (GXP_Q7_ICACHE_LINESIZE / sizeof(u32))
#define GXP_Q7_DCACHE_SIZE 65536 /* D-cache size in bytes */
-#define GXP_Q7_DCACHE_LINESIZE 64 /* D-cache line size in bytes */
+#define GXP_Q7_DCACHE_LINESIZE 64 /* D-cache line size in bytes */
#define GXP_Q7_DCACHE_WAYS 4
-#define GXP_Q7_DCACHE_SETS ((GXP_Q7_DCACHE_SIZE / GXP_Q7_DCACHE_WAYS) / \
- GXP_Q7_DCACHE_LINESIZE)
+#define GXP_Q7_DCACHE_SETS \
+ ((GXP_Q7_DCACHE_SIZE / GXP_Q7_DCACHE_WAYS) / GXP_Q7_DCACHE_LINESIZE)
#define GXP_Q7_DCACHE_WORDS_PER_LINE (GXP_Q7_DCACHE_LINESIZE / sizeof(u32))
#define GXP_Q7_NUM_AREGS 64
#define GXP_Q7_DCACHE_TAG_RAMS 2
@@ -188,6 +188,12 @@ struct gxp_debug_dump_manager {
* time
*/
struct mutex debug_dump_lock;
+ /*
+ * Array index maps to dsp cores. Array stores the pointer to the
+ * crashed VD that was running on the respective core. This is used
+ * only in mcu mode.
+ */
+ struct gxp_virtual_device *crashed_core_to_vd[GXP_NUM_CORES];
#if IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
struct sscd_segment segs[GXP_NUM_CORES][GXP_NUM_SEGMENTS_PER_CORE];
#endif
@@ -199,4 +205,31 @@ struct work_struct *gxp_debug_dump_get_notification_handler(struct gxp_dev *gxp,
uint core);
bool gxp_debug_dump_is_enabled(void);
+/**
+ * gxp_debug_dump_invalidate_segments() - Invalidate debug dump segments to enable
+ * firmware to populate them on next debug
+ * dump trigger.
+ *
+ * This function is not thread safe. Caller should take the necessary precautions.
+ *
+ * @gxp: The GXP device to obtain the handler for
+ * @core_id: physical id of core whose dump segments need to be invalidated.
+ */
+void gxp_debug_dump_invalidate_segments(struct gxp_dev *gxp, uint32_t core_id);
+
+/**
+ * gxp_debug_dump_process_dump_mcu_mode() - Checks and process the debug dump
+ * for cores from core_list.
+ * @gxp: The GXP device to obtain the handler for
+ * @core_list: A bitfield enumerating the physical cores on which crash is
+ * reported from firmware.
+ * @crashed_vd: vd that has crashed.
+ *
+ * Return:
+ * * 0 - Success.
+ * * -EINVAL - If vd state is not GXP_VD_UNAVAILABLE.
+ */
+int gxp_debug_dump_process_dump_mcu_mode(struct gxp_dev *gxp, uint core_list,
+ struct gxp_virtual_device *crashed_vd);
+
#endif /* __GXP_DEBUG_DUMP_H__ */
diff --git a/gxp-debugfs.c b/gxp-debugfs.c
index baf273f..47a45a1 100644
--- a/gxp-debugfs.c
+++ b/gxp-debugfs.c
@@ -510,10 +510,19 @@ static int gxp_cmu_mux2_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(gxp_cmu_mux2_fops, gxp_cmu_mux2_get, gxp_cmu_mux2_set,
"%llu\n");
-void gxp_create_debugfs(struct gxp_dev *gxp)
+void gxp_create_debugdir(struct gxp_dev *gxp)
{
gxp->d_entry = debugfs_create_dir(GXP_NAME, NULL);
- if (IS_ERR_OR_NULL(gxp->d_entry))
+ if (IS_ERR_OR_NULL(gxp->d_entry)) {
+ dev_warn(gxp->dev, "Create debugfs dir failed: %d",
+ PTR_ERR_OR_ZERO(gxp->d_entry));
+ gxp->d_entry = NULL;
+ }
+}
+
+void gxp_create_debugfs(struct gxp_dev *gxp)
+{
+ if (!gxp->d_entry)
return;
mutex_init(&gxp->debugfs_client_lock);
@@ -540,9 +549,9 @@ void gxp_create_debugfs(struct gxp_dev *gxp)
&gxp_cmu_mux2_fops);
}
-void gxp_remove_debugfs(struct gxp_dev *gxp)
+void gxp_remove_debugdir(struct gxp_dev *gxp)
{
- if (IS_GXP_TEST && !gxp->d_entry)
+ if (!gxp->d_entry)
return;
debugfs_remove_recursive(gxp->d_entry);
diff --git a/gxp-debugfs.h b/gxp-debugfs.h
index 4b42546..6ea8688 100644
--- a/gxp-debugfs.h
+++ b/gxp-debugfs.h
@@ -9,7 +9,12 @@
#include "gxp-internal.h"
+/*
+ * Creates the GXP debug FS directory and assigns to @gxp->d_entry.
+ * On failure a warning is logged and @gxp->d_entry is NULL.
+ */
+void gxp_create_debugdir(struct gxp_dev *gxp);
void gxp_create_debugfs(struct gxp_dev *gxp);
-void gxp_remove_debugfs(struct gxp_dev *gxp);
+void gxp_remove_debugdir(struct gxp_dev *gxp);
#endif /* __GXP_DEBUGFS_H__ */
diff --git a/gxp-firmware-data.c b/gxp-firmware-data.c
index cf2b3e0..684d08c 100644
--- a/gxp-firmware-data.c
+++ b/gxp-firmware-data.c
@@ -485,7 +485,7 @@ static struct app_metadata *gxp_fw_data_create_app_legacy(struct gxp_dev *gxp,
void *err;
int i;
- app = kzalloc(sizeof(struct app_metadata), GFP_KERNEL);
+ app = kzalloc(sizeof(*app), GFP_KERNEL);
if (!app)
return ERR_PTR(-ENOMEM);
diff --git a/gxp-firmware.c b/gxp-firmware.c
index 5cc0335..32d5dc3 100644
--- a/gxp-firmware.c
+++ b/gxp-firmware.c
@@ -167,7 +167,7 @@ static int elf_load_segments(struct gxp_dev *gxp, const u8 *elf_data,
* skipped while loading
*/
dev_err(gxp->dev,
- "Segment out of bounds: da 0x%llx mem 0x%x. Skipping...",
+ "Segment out of bounds: da %#llx mem %#x. Skipping...",
da, memsz);
continue;
}
@@ -193,7 +193,7 @@ static int elf_load_segments(struct gxp_dev *gxp, const u8 *elf_data,
/* grab the kernel address for this device address */
ptr = buffer->vaddr + (da - buffer->daddr);
if (!ptr) {
- dev_err(gxp->dev, "Bad phdr: da 0x%#llx mem 0x%#x", da,
+ dev_err(gxp->dev, "Bad phdr: da %#llx mem %#x", da,
memsz);
ret = -EINVAL;
break;
@@ -340,7 +340,7 @@ static void *get_scratchpad_base(struct gxp_dev *gxp,
if (vd && gxp_fw_data_use_per_vd_config(vd))
return vd->core_cfg.vaddr +
- vd->core_cfg.size / GXP_NUM_CORES * core;
+ (vd->core_cfg.size / GXP_NUM_CORES) * core;
if (!vd || !vd->rwdata_sgt[core])
return gxp->fwbufs[core].vaddr + AURORA_SCRATCHPAD_OFF;
diff --git a/gxp-kci.c b/gxp-kci.c
index 79fc069..5ff365b 100644
--- a/gxp-kci.c
+++ b/gxp-kci.c
@@ -14,6 +14,7 @@
#include "gxp-config.h"
#include "gxp-core-telemetry.h"
+#include "gxp-debug-dump.h"
#include "gxp-dma.h"
#include "gxp-kci.h"
#include "gxp-lpm.h"
@@ -129,11 +130,30 @@ static void gxp_kci_handle_rkci(struct gxp_kci *gkci,
gxp_kci_resp_rkci_ack(gkci, resp);
break;
}
- case GCIP_RKCI_CLIENT_FATAL_ERROR_NOTIFY:
- /* TODO(b/265092842): Create a debug dump of corresponding cores (resp->status). */
- gxp_vd_invalidate(gxp, resp->retval);
+ case GCIP_RKCI_CLIENT_FATAL_ERROR_NOTIFY: {
+ uint core_list = (uint)(resp->status);
+ int client_id = (int)(resp->retval);
+ /*
+ * core_list param is used for generating debug dumps of respective
+ * cores in core_list. Dumps are not required to be generated for
+ * secure client and hence resetting it irrespective of debug dumps
+ * being enabled or not.
+ */
+ if (client_id == SECURE_CLIENT_ID)
+ core_list = 0;
+ /*
+ * Inside gxp_vd_invalidate() after invalidating the client, debug dump
+ * if enabled would be checked and processed for individual cores in
+ * core_list. Due to debug dump processing being a time consuming task
+ * rkci ack is sent first to unblock the mcu to send furhter rkci's. Client
+ * lock inside gxp_vd_invalidate() would make sure the correctness of the
+ * logic against possible concurrent scenarios.
+ */
gxp_kci_resp_rkci_ack(gkci, resp);
+ gxp_vd_invalidate(gxp, client_id, core_list);
+
break;
+ }
default:
dev_warn(gxp->dev, "Unrecognized reverse KCI request: %#x",
resp->code);
diff --git a/gxp-mcu-firmware.c b/gxp-mcu-firmware.c
index ab0f866..8fa8c84 100644
--- a/gxp-mcu-firmware.c
+++ b/gxp-mcu-firmware.c
@@ -225,8 +225,8 @@ static int gxp_mcu_firmware_power_up(struct gxp_mcu_firmware *mcu_fw,
if (ret)
return ret;
/* Raise wakeup doorbell */
- dev_notice(gxp->dev, "Raising doorbell %d interrupt\n",
- CORE_WAKEUP_DOORBELL(GXP_MCU_CORE_ID));
+ dev_dbg(gxp->dev, "Raising doorbell %d interrupt\n",
+ CORE_WAKEUP_DOORBELL(GXP_MCU_CORE_ID));
gxp_doorbell_enable_for_core(gxp, CORE_WAKEUP_DOORBELL(GXP_MCU_CORE_ID),
GXP_MCU_CORE_ID);
gxp_doorbell_set(gxp, CORE_WAKEUP_DOORBELL(GXP_MCU_CORE_ID));
diff --git a/gxp-vd.c b/gxp-vd.c
index 0c0c1b0..adf0daa 100644
--- a/gxp-vd.c
+++ b/gxp-vd.c
@@ -58,7 +58,8 @@ void gxp_vd_destroy(struct gxp_dev *gxp)
}
/* Allocates an SGT and map @daddr to it. */
-static int map_ns_region(struct gxp_virtual_device *vd, dma_addr_t daddr, size_t size)
+static int map_ns_region(struct gxp_virtual_device *vd, dma_addr_t daddr,
+ size_t size)
{
struct gxp_dev *gxp = vd->gxp;
struct sg_table *sgt;
@@ -1402,11 +1403,13 @@ void gxp_vd_put(struct gxp_virtual_device *vd)
kfree(vd);
}
-void gxp_vd_invalidate(struct gxp_dev *gxp, int client_id)
+void gxp_vd_invalidate(struct gxp_dev *gxp, int client_id, uint core_list)
{
struct gxp_client *client = NULL, *c;
release_unconsumed_async_resps_t release_unconsumed_async_resps =
gxp->mailbox_mgr->release_unconsumed_async_resps;
+ int ret;
+ uint core;
/*
* Prevent @gxp->client_list is being changed while handling the crash.
@@ -1435,6 +1438,19 @@ void gxp_vd_invalidate(struct gxp_dev *gxp, int client_id)
if (!client) {
dev_err(gxp->dev, "Failed to find a VD, client_id=%d",
client_id);
+ /*
+ * Invalidate all debug dump segments if debug dump
+ * is enabled and core_list is not empty.
+ */
+ if (!gxp_debug_dump_is_enabled() || !core_list)
+ return;
+ for (core = 0; core < GXP_NUM_CORES; core++) {
+ if (!(BIT(core) & core_list))
+ continue;
+ mutex_lock(&gxp->debug_dump_mgr->debug_dump_lock);
+ gxp_debug_dump_invalidate_segments(gxp, core);
+ mutex_unlock(&gxp->debug_dump_mgr->debug_dump_lock);
+ }
return;
}
@@ -1456,5 +1472,19 @@ void gxp_vd_invalidate(struct gxp_dev *gxp, int client_id)
}
up_write(&gxp->vd_semaphore);
+ /*
+ * Process debug dump if its enabled and core_list is not empty.
+ * Keep on hold the client lock while processing the dumps. vd
+ * lock would be taken and released inside the debug dump
+ * implementation logic ahead.
+ */
+ if (gxp_debug_dump_is_enabled() && core_list != 0) {
+ ret = gxp_debug_dump_process_dump_mcu_mode(gxp, core_list,
+ client->vd);
+ if (ret)
+ dev_err(gxp->dev,
+ "debug dump processing failed (ret=%d).\n",
+ ret);
+ }
up_write(&client->semaphore);
}
diff --git a/gxp-vd.h b/gxp-vd.h
index fb6cace..9d78b45 100644
--- a/gxp-vd.h
+++ b/gxp-vd.h
@@ -371,13 +371,18 @@ void gxp_vd_put(struct gxp_virtual_device *vd);
/*
* Change the status of the vd of @client_id to GXP_VD_UNAVAILABLE.
- * Internally, it will discard all pending/unconsumed user commands and call the
- * `gxp_vd_block_unready` function.
+ * Internally, it will discard all pending/unconsumed user commands
+ * and call the `gxp_vd_block_unready` function.
*
- * This function will be called when the `CLIENT_FATAL_ERROR_NOTIFY` RKCI has been sent from the
- * firmware side.
+ * This function will be called when the `CLIENT_FATAL_ERROR_NOTIFY`
+ * RKCI has been sent from the firmware side.
+ *
+ * @gxp: The GXP device to obtain the handler for
+ * @client_id: client_id of the crashed vd.
+ * @core_list: A bitfield enumerating the physical cores on which
+ * crash is reported from firmware.
*/
-void gxp_vd_invalidate(struct gxp_dev *gxp, int client_id);
+void gxp_vd_invalidate(struct gxp_dev *gxp, int client_id, uint core_list);
/*
* An ID between 0~GXP_NUM_CORES-1 and is unique to each VD.