diff options
author | Aurora zuma automerger <aurora-zuma-automerger@google.com> | 2023-02-02 09:28:41 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-02-02 01:56:33 -0800 |
commit | 77edbbfcd394cd9844ba7e675ed4e5358d6cf8b4 (patch) | |
tree | d0b0721d694bbd62e9d446e1b7fbda9e129f4626 | |
parent | df93ed835156837cd4c6e2dfd32d34e015250055 (diff) | |
download | zuma-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.h | 16 | ||||
-rw-r--r-- | gcip-kernel-driver/include/gcip/gcip-kci.h | 10 | ||||
-rw-r--r-- | gxp-common-platform.c | 7 | ||||
-rw-r--r-- | gxp-debug-dump.c | 82 | ||||
-rw-r--r-- | gxp-debug-dump.h | 47 | ||||
-rw-r--r-- | gxp-debugfs.c | 17 | ||||
-rw-r--r-- | gxp-debugfs.h | 7 | ||||
-rw-r--r-- | gxp-firmware-data.c | 2 | ||||
-rw-r--r-- | gxp-firmware.c | 6 | ||||
-rw-r--r-- | gxp-kci.c | 26 | ||||
-rw-r--r-- | gxp-mcu-firmware.c | 4 | ||||
-rw-r--r-- | gxp-vd.c | 34 | ||||
-rw-r--r-- | gxp-vd.h | 15 |
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; @@ -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)); @@ -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); } @@ -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. |