From ec2e64f0bb54d942059d75ccc7c4ab6daa775f78 Mon Sep 17 00:00:00 2001 From: Aurora pro automerger Date: Tue, 14 Mar 2023 02:07:34 +0000 Subject: gxp: [Copybara Auto Merge] Merge branch 'gs201-u' into 'android13-gs-pixel-5.10-udc' gxp: fix compiler warning in gxp-thermal gxp: move fw_rw_section into if-guard gxp: fix memory leak with invalid telemetry type Bug: 273254318 gxp: remove unneeded checks in vd.c gxp: skip configuring when missing VD config gxp: remove unused host-dev structs Bug: 265748027 gxp: remove unused range-alloc module gxp: entirely remove app_metadata Bug: 265748027 (repeat) gxp: remove legacy firmware data init Bug: 265748027 (repeat) gxp: remove legacy telemetry descriptor Bug: 265748027 (repeat) gxp: move system cfg population to device probe Bug: 265748027 (repeat) gxp: add gxp_fw_data_system_cfg Bug: 265748027 (repeat) gxp: add gxp_fw_data_resource Bug: 265748027 (repeat) gxp: bump version 1.11 Bugs: gxp: fix panic on buffer flushing Bug: 268389591 gxp: Do not put core in reset if already in ACG Bug: 272664140 gxp: add cached core telemetry desc Bug: 265748027 (repeat) gxp: Adpot GCIP thermal Bug: 264729080 Bug: 213272324 gxp: remove core_boot parameter Bug: 251612313 gxp: use GPL-2.0-only license Bug: 271797962 gxp: authenticates firmware through GSA Bug: 260533620 gxp: Enable debug dump for imageconfig 2. Bug: 271371895 gxp: Add size check while loading image to memory Bug: 265105909 gxp: refactor MCU firmware life cycle Bug: 233159020 gxp: Create a function for gxp_core_boot Bug: 271716712 gxp: Increase UCI command timeout to 2 seconds Bug: 271622596 gxp: remove checks of data_mgr gxp: skip mapping core resources in MCU mode gxp: add gxp_firmware_loader module gxp: log a warning on failing to map CMU reg gxp: disable out-dated auth mechanism in MCU mode Bug: 260533620 (repeat) gxp: refactor core firmware loading gxp: stop mapping core->TPU queues gxp: get core_count by counting bits Bug: 270097855 gxp: set SSMT to bypass in both mode Bug: 269855604 gxp: Skip gxp_vd_block_unready if gxp_vd_block_ready was not executed Bug: 268427254 gcip: Make gcip_pm_{get_count,is_powered} lockless Bug: 271756295 gcip: generalize mem_pool gcip: utilize mock files on unittests Bug: 272216562 gcip: use GPL-2.0-only license Bug: 271797962 (repeat) gcip: Remove gcip_pm_put_async Bug: 271756295 (repeat) gcip: Only call .power_up if needed gcip: Print GCIP_FW_LOG_LEVEL_FATAL as error message Bug: 271596603 gcip: Postfix gcip_firmware_tracing_restore gcip: fix undefined variable on !THERMAL gcip: always return NULL on domain alloc error gcip: Add gcip_thermal_destroy Bug; 264729080 (repeat) gcip: Add thermal votes Bug: 271194361 Bug: 264729080 (repeat) gcip: Cleanup abandoned domains on domain-pool destroy gcip: Prefix MAX_NUM_THERMAL_STATES Bug: 264729080 (repeat) gcip: Add const to thermal_cooling_device_ops Bug: 264729080 (repeat) gcip: Add thermal support Bug: 264729080 (repeat) gcip: remove redundant else in pm.c GCIP_MAIN_REV_ID: a5b6843ab58f30d6ce086016214cbf56a46610a8 gcip: Add gcip_pm_lock Bug: 264729080 (repeat) gcip: Make gcip_pm_{get_count,is_powered} lockless Bug: 271756295 (repeat) gcip: generalize mem_pool gcip: use GPL-2.0-only license Bug: 271797962 (repeat) gcip: Remove gcip_pm_put_async Bug: 271756295 (repeat) gcip: Add gcip_pm_trylock Bug: 271756295 (repeat) gcip: Add level -3 (FATAL) for firmware log Bug: 271596603 (repeat) gcip: Update outdated comments gcip: Postfix gcip_firmware_tracing_restore gcip: Add gcip_thermal_destroy Bug: 264729080 (repeat) gcip: Add thermal votes Bug: 271194361 (repeat) Bug: 264729080 (repeat) gcip: Add missing includes to gcip-domain-pool.h gcip: Add list of dynamic domains to domain-pool gcip: Prefix MAX_NUM_THERMAL_STATES Bug: 264729080 (repeat) gcip: add watchdog timeout crash type Bug:255416846 gcip: Add thermal header Bug: 264729080 (repeat) GCIP_HEADERS_REV_ID: 126a2bd1e5ac72231c88425fbddb4b9fe2fd85b1 GitOrigin-RevId: 03d9970af576cb6267f25715de67d4ffd3e2934c Change-Id: Ia0e7a0d8113d209e0bb57e160bc3f2d89b1d4c5e --- gxp-firmware.c | 289 ++++++++++++++++++++++----------------------------------- 1 file changed, 113 insertions(+), 176 deletions(-) (limited to 'gxp-firmware.c') diff --git a/gxp-firmware.c b/gxp-firmware.c index b0453d5..d532fdf 100644 --- a/gxp-firmware.c +++ b/gxp-firmware.c @@ -26,6 +26,7 @@ #include "gxp-debug-dump.h" #include "gxp-doorbell.h" #include "gxp-firmware-data.h" +#include "gxp-firmware-loader.h" #include "gxp-firmware.h" #include "gxp-host-device-structs.h" #include "gxp-internal.h" @@ -44,42 +45,6 @@ static int gxp_dsp_fw_auth_disable; module_param_named(dsp_fw_auth_disable, gxp_dsp_fw_auth_disable, int, 0660); -bool gxp_core_boot = true; -module_param_named(core_boot, gxp_core_boot, bool, 0660); - -/* - * Fetches and records image config of the first firmware. - */ -static void gxp_firmware_get_image_config(struct gxp_dev *gxp, - struct gxp_firmware_manager *mgr) -{ - struct gcip_common_image_header *hdr = - (struct gcip_common_image_header *)mgr->firmwares[0]->data; - struct gcip_image_config *cfg; - - if (unlikely(mgr->firmwares[0]->size < FW_HEADER_SIZE)) - return; - cfg = get_image_config_from_hdr(hdr); - if (cfg) - mgr->img_cfg = *cfg; - else - dev_warn(gxp->dev, - "Firmware doesn't have a valid image config"); -} - -/* - * Call this function when mgr->firmwares have been populated. - * This function sets is_firmware_requested to true. - * - * Caller holds mgr->dsp_firmware_lock. - */ -static void gxp_firmware_has_requested(struct gxp_dev *gxp, - struct gxp_firmware_manager *mgr) -{ - gxp_firmware_get_image_config(gxp, mgr); - mgr->is_firmware_requested = true; -} - static int request_dsp_firmware(struct gxp_dev *gxp, char *name_prefix, const struct firmware *out_firmwares[GXP_NUM_CORES]) @@ -117,8 +82,10 @@ request_dsp_firmware(struct gxp_dev *gxp, char *name_prefix, return ret; err: - for (core -= 1; core >= 0; core--) + for (core -= 1; core >= 0; core--) { release_firmware(out_firmwares[core]); + out_firmwares[core] = NULL; + } kfree(name_buf); return ret; } @@ -238,6 +205,9 @@ gxp_firmware_authenticate(struct gxp_dev *gxp, return 0; } + if (!gxp_is_direct_mode(gxp)) + return 0; + for (core = 0; core < GXP_NUM_CORES; core++) { data = firmwares[core]->data; size = firmwares[core]->size; @@ -302,9 +272,6 @@ error: return ret; } -/* Forward declaration for usage inside gxp_firmware_load(..). */ -static void gxp_firmware_unload(struct gxp_dev *gxp, uint core); - static void gxp_program_reset_vector(struct gxp_dev *gxp, uint core, uint phys_core, bool verbose) { @@ -383,40 +350,6 @@ static void reset_core_config_region(struct gxp_dev *gxp, } } -static int gxp_firmware_load(struct gxp_dev *gxp, struct gxp_virtual_device *vd, - uint core) -{ - struct gxp_firmware_manager *mgr = gxp->firmware_mgr; - int ret; - - if (!mgr->firmwares[core]) - return -ENODEV; - if (mgr->loaded[core]) - return 0; - - /* Load firmware to System RAM */ - ret = elf_load_segments(gxp, - mgr->firmwares[core]->data + FW_HEADER_SIZE, - mgr->firmwares[core]->size - FW_HEADER_SIZE, - &gxp->fwbufs[core]); - if (ret) { - dev_err(gxp->dev, "Unable to load elf file\n"); - goto out_firmware_unload; - } - - /* TODO(b/188970444): Cleanup logging of addresses */ - dev_notice(gxp->dev, - "ELF loaded at virtual: %pK and physical: %#llx\n", - gxp->fwbufs[core].vaddr, gxp->fwbufs[core].paddr); - mgr->loaded[core] = true; - - return 0; - -out_firmware_unload: - gxp_firmware_unload(gxp, core); - return ret; -} - static int gxp_firmware_handshake(struct gxp_dev *gxp, struct gxp_virtual_device *vd, uint core, uint phys_core) @@ -515,9 +448,64 @@ static int gxp_firmware_handshake(struct gxp_dev *gxp, return 0; } -static void gxp_firmware_unload(struct gxp_dev *gxp, uint core) +static int +gxp_firmware_load_into_memories(struct gxp_dev *gxp, + const struct firmware *firmwares[GXP_NUM_CORES]) +{ + int core; + int ret; + + for (core = 0; core < GXP_NUM_CORES; core++) { + /* Load firmware to System RAM */ + if (FW_HEADER_SIZE > firmwares[core]->size) { + dev_err(gxp->dev, + "Invalid Core %u firmware Image size (%d > %zu)\n", + core, FW_HEADER_SIZE, firmwares[core]->size); + ret = -EINVAL; + goto error; + } + + if ((firmwares[core]->size - FW_HEADER_SIZE) > + gxp->fwbufs[core].size) { + dev_err(gxp->dev, + "Core %u firmware image does not fit (%zu > %llu)\n", + core, firmwares[core]->size - FW_HEADER_SIZE, + gxp->fwbufs[core].size); + ret = -EINVAL; + goto error; + } + memcpy_toio(gxp->fwbufs[core].vaddr, + firmwares[core]->data + FW_HEADER_SIZE, + firmwares[core]->size - FW_HEADER_SIZE); + } + return 0; +error: + /* Zero out firmware buffers if we got invalid size on any core. */ + for (core -= 1; core >= 0; core--) + memset_io(gxp->fwbufs[core].vaddr, 0, gxp->fwbufs[core].size); + return ret; +} + +int gxp_firmware_rearrange_elf(struct gxp_dev *gxp, + const struct firmware *firmwares[GXP_NUM_CORES]) { - /* NO-OP for now. */ + int ret = 0; + uint core; + + for (core = 0; core < GXP_NUM_CORES; core++) { + /* Re-arrange ELF firmware in System RAM */ + ret = elf_load_segments(gxp, + firmwares[core]->data + FW_HEADER_SIZE, + firmwares[core]->size - FW_HEADER_SIZE, + &gxp->fwbufs[core]); + if (ret) { + dev_err(gxp->dev, + "Failed to parse ELF firmware on core %u\n", + core); + return ret; + } + } + return ret; } /* Helper function to parse name written to sysfs "load_dsp_firmware" node */ @@ -544,17 +532,11 @@ static ssize_t load_dsp_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gxp_dev *gxp = dev_get_drvdata(dev); - struct gxp_firmware_manager *mgr = gxp->firmware_mgr; ssize_t ret; + char *firmware_name = gxp_firmware_loader_get_core_fw_name(gxp); - mutex_lock(&mgr->dsp_firmware_lock); - - ret = scnprintf(buf, PAGE_SIZE, "%s\n", - mgr->firmware_name ? mgr->firmware_name : - DSP_FIRMWARE_DEFAULT_PREFIX); - - mutex_unlock(&mgr->dsp_firmware_lock); - + ret = scnprintf(buf, PAGE_SIZE, "%s\n", firmware_name); + kfree(firmware_name); return ret; } @@ -564,10 +546,8 @@ static ssize_t load_dsp_firmware_store(struct device *dev, { struct gxp_dev *gxp = dev_get_drvdata(dev); struct gxp_firmware_manager *mgr = gxp->firmware_mgr; - const struct firmware *firmwares[GXP_NUM_CORES]; char *name_buf = NULL; int ret; - int core; /* * Lock the VD semaphore to ensure no core is executing the firmware @@ -589,43 +569,28 @@ static ssize_t load_dsp_firmware_store(struct device *dev, goto err_out; } - mutex_lock(&mgr->dsp_firmware_lock); - dev_notice(gxp->dev, "Requesting firmware be reloaded: %s\n", name_buf); - ret = request_dsp_firmware(gxp, name_buf, firmwares); + /* + * It's possible a race condition bug here that someone opens a gxp + * device and loads the firmware between below unload/load functions in + * another thread, but this interface is only for developer debugging. + * We don't insist on preventing the race condition bug. + */ + gxp_firmware_loader_unload(gxp); + gxp_firmware_loader_set_core_fw_name(gxp, name_buf); + ret = gxp_firmware_loader_load_if_needed(gxp); if (ret) { - dev_err(gxp->dev, - "Failed to request firmwares with names \"%sX\" (ret=%d)\n", - name_buf, ret); - goto err_request_firmware; + dev_err(gxp->dev, "Failed to load core firmware: %s\n", name_buf); + goto err_firmware_load; } - ret = gxp_firmware_authenticate(gxp, firmwares); - if (ret) - goto err_authenticate_firmware; - - for (core = 0; core < GXP_NUM_CORES; core++) { - if (mgr->firmwares[core]) - release_firmware(mgr->firmwares[core]); - mgr->firmwares[core] = firmwares[core]; - mgr->loaded[core] = false; - } - - kfree(mgr->firmware_name); - mgr->firmware_name = name_buf; - gxp_firmware_has_requested(gxp, mgr); - - mutex_unlock(&mgr->dsp_firmware_lock); + kfree(name_buf); up_read(&gxp->vd_semaphore); return count; -err_authenticate_firmware: - for (core = 0; core < GXP_NUM_CORES; core++) - release_firmware(firmwares[core]); -err_request_firmware: +err_firmware_load: kfree(name_buf); - mutex_unlock(&mgr->dsp_firmware_lock); err_out: up_read(&gxp->vd_semaphore); return ret; @@ -654,7 +619,6 @@ int gxp_fw_init(struct gxp_dev *gxp) if (!mgr) return -ENOMEM; gxp->firmware_mgr = mgr; - mutex_init(&mgr->dsp_firmware_lock); /* Power on BLK_AUR to read the revision and processor ID registers */ gxp_pm_blk_on(gxp); @@ -750,53 +714,34 @@ void gxp_fw_destroy(struct gxp_dev *gxp) memunmap(gxp->fwbufs[core].vaddr); gxp->fwbufs[core].vaddr = NULL; } - - if (mgr->firmwares[core]) { - release_firmware(mgr->firmwares[core]); - mgr->firmwares[core] = NULL; - } } - - kfree(mgr->firmware_name); } -int gxp_firmware_request_if_needed(struct gxp_dev *gxp) +int gxp_firmware_load_core_firmware( + struct gxp_dev *gxp, char *name_prefix, + const struct firmware *core_firmware[GXP_NUM_CORES]) { - int ret = 0; uint core; - struct gxp_firmware_manager *mgr = gxp->firmware_mgr; - char *name = NULL; - - mutex_lock(&mgr->dsp_firmware_lock); - - if (mgr->is_firmware_requested) - goto out; - - if (mgr->firmware_name == NULL) - name = DSP_FIRMWARE_DEFAULT_PREFIX; - else - name = mgr->firmware_name; + int ret; - ret = request_dsp_firmware(gxp, name, mgr->firmwares); + if (name_prefix == NULL) + name_prefix = DSP_FIRMWARE_DEFAULT_PREFIX; + ret = request_dsp_firmware(gxp, name_prefix, core_firmware); if (ret) - goto out; - - ret = gxp_firmware_authenticate(gxp, mgr->firmwares); + return ret; + ret = gxp_firmware_load_into_memories(gxp, core_firmware); if (ret) - goto err_authenticate_firmware; - - gxp_firmware_has_requested(gxp, mgr); - -out: - mutex_unlock(&mgr->dsp_firmware_lock); - return ret; + goto error; + ret = gxp_firmware_authenticate(gxp, core_firmware); + if (ret) + goto error; -err_authenticate_firmware: + return 0; +error: for (core = 0; core < GXP_NUM_CORES; core++) { - release_firmware(mgr->firmwares[core]); - mgr->firmwares[core] = NULL; + release_firmware(core_firmware[core]); + core_firmware[core] = NULL; } - mutex_unlock(&mgr->dsp_firmware_lock); return ret; } @@ -811,7 +756,7 @@ static void enable_core_interrupts(struct gxp_dev *gxp, uint core) gxp_write_32(gxp, GXP_CORE_REG_DEDICATED_INT_MASK(core), 0xffffffff); } -static void disable_core_interrupts(struct gxp_dev *gxp, uint core) +void gxp_firmware_disable_ext_interrupts(struct gxp_dev *gxp, uint core) { gxp_write_32(gxp, GXP_CORE_REG_COMMON_INT_MASK_0(core), 0); gxp_write_32(gxp, GXP_CORE_REG_COMMON_INT_MASK_1(core), 0); @@ -831,31 +776,24 @@ static int gxp_firmware_setup(struct gxp_dev *gxp, int ret = 0; struct gxp_firmware_manager *mgr = gxp->firmware_mgr; - if (gxp_core_boot && mgr->firmware_running & BIT(phys_core)) { + if (gxp_core_boot(gxp) && mgr->firmware_running & BIT(phys_core)) { dev_err(gxp->dev, "Firmware is already running on core %u\n", phys_core); return -EBUSY; } - ret = gxp_firmware_load(gxp, vd, core); - if (ret) { - dev_err(gxp->dev, "Failed to load firmware on core %u\n", - phys_core); - return ret; - } /* Configure bus performance monitors */ gxp_bpm_configure(gxp, phys_core, INST_BPM_OFFSET, BPM_EVENT_READ_XFER); gxp_bpm_configure(gxp, phys_core, DATA_BPM_OFFSET, BPM_EVENT_WRITE_XFER); /* Mark this as a cold boot */ - if (gxp_core_boot) { + if (gxp_core_boot(gxp)) { reset_core_config_region(gxp, vd, core); ret = gxp_firmware_setup_hw_after_block_off(gxp, core, phys_core, /*verbose=*/true); if (ret) { dev_err(gxp->dev, "Failed to power up core %u\n", core); - gxp_firmware_unload(gxp, core); return ret; } enable_core_interrupts(gxp, phys_core); @@ -889,7 +827,7 @@ static int gxp_firmware_finish_startup(struct gxp_dev *gxp, int ret = 0; uint core = select_core(vd, virt_core, phys_core); - if (gxp_core_boot) { + if (gxp_core_boot(gxp)) { ret = gxp_firmware_handshake(gxp, vd, core, phys_core); if (ret) { dev_err(gxp->dev, @@ -931,9 +869,8 @@ static int gxp_firmware_finish_startup(struct gxp_dev *gxp, return ret; err_firmware_off: - if (gxp_core_boot) + if (gxp_core_boot(gxp)) gxp_pm_core_off(gxp, phys_core); - gxp_firmware_unload(gxp, core); return ret; } @@ -943,7 +880,7 @@ static void gxp_firmware_stop_core(struct gxp_dev *gxp, { struct gxp_firmware_manager *mgr = gxp->firmware_mgr; - if (gxp_core_boot && !(mgr->firmware_running & BIT(phys_core))) + if (gxp_core_boot(gxp) && !(mgr->firmware_running & BIT(phys_core))) dev_err(gxp->dev, "Firmware is not running on core %u\n", phys_core); @@ -954,7 +891,7 @@ static void gxp_firmware_stop_core(struct gxp_dev *gxp, gxp_notification_unregister_handler(gxp, phys_core, HOST_NOTIF_CORE_TELEMETRY_STATUS); - if (gxp_core_boot) { + if (gxp_core_boot(gxp)) { if (gxp->mailbox_mgr->release_mailbox) { gxp->mailbox_mgr->release_mailbox( gxp->mailbox_mgr, vd, virt_core, @@ -968,12 +905,10 @@ static void gxp_firmware_stop_core(struct gxp_dev *gxp, * Disable interrupts to prevent cores from being woken up * unexpectedly. */ - disable_core_interrupts(gxp, phys_core); + gxp_firmware_disable_ext_interrupts(gxp, phys_core); gxp_pm_core_off(gxp, phys_core); } } - - gxp_firmware_unload(gxp, select_core(vd, virt_core, phys_core)); } int gxp_firmware_run(struct gxp_dev *gxp, struct gxp_virtual_device *vd, @@ -1007,14 +942,11 @@ int gxp_firmware_run(struct gxp_dev *gxp, struct gxp_virtual_device *vd, */ virt_core = 0; for (phys_core = 0; phys_core < GXP_NUM_CORES; phys_core++) { - uint core = select_core(vd, virt_core, phys_core); - if (!(core_list & BIT(phys_core))) continue; if (!(failed_cores & BIT(phys_core))) { - if (gxp_core_boot) + if (gxp_core_boot(gxp)) gxp_pm_core_off(gxp, phys_core); - gxp_firmware_unload(gxp, core); } virt_core++; } @@ -1034,7 +966,7 @@ int gxp_firmware_run(struct gxp_dev *gxp, struct gxp_virtual_device *vd, } #endif /* Switch clock mux to the normal state to guarantee LPM works */ - if (gxp_core_boot) { + if (gxp_core_boot(gxp)) { gxp_pm_force_clkmux_normal(gxp); gxp_firmware_wakeup_cores(gxp, core_list); } @@ -1065,7 +997,7 @@ int gxp_firmware_run(struct gxp_dev *gxp, struct gxp_virtual_device *vd, } } /* Check if we need to set clock mux to low state as requested */ - if (gxp_core_boot) + if (gxp_core_boot(gxp)) gxp_pm_resume_clkmux(gxp); return ret; @@ -1138,3 +1070,8 @@ u32 gxp_firmware_get_boot_status(struct gxp_dev *gxp, core_cfg = get_scratchpad_base(gxp, vd, core); return core_cfg->boot_status; } + +bool gxp_core_boot(struct gxp_dev *gxp) +{ + return gxp_is_direct_mode(gxp); +} -- cgit v1.2.3