From 5f8dad185b3e3a381fe2e3d16580a8a8e99f9db0 Mon Sep 17 00:00:00 2001 From: Bhavik Patel Date: Wed, 30 Sep 2020 09:06:52 +0200 Subject: MLBEDSW-3094 Improve soft reset of ETHOSU when running jobs The ETHOSU is soft-reset only if the previous job failed or if the current privilege level is not user or if the current security level is not secure. Change-Id: Id10b96058d67805d179ac693537606d55e10379b --- src/ethosu_device.c | 16 ++++++++++++++++ src/ethosu_driver.c | 34 ++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ethosu_device.c b/src/ethosu_device.c index 973caad..85dc022 100644 --- a/src/ethosu_device.c +++ b/src/ethosu_device.c @@ -193,6 +193,8 @@ enum ethosu_error_codes ethosu_soft_reset(struct ethosu_device *dev) ethosu_write_reg(dev, NPU_REG_RESET, reset.word); return_code = ethosu_wait_for_reset(dev); + + dev->reset = ethosu_read_reg(dev, NPU_REG_PROT); #else UNUSED(dev); #endif @@ -618,3 +620,17 @@ enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev) return ETHOSU_SUCCESS; } + +bool ethosu_status_has_error(struct ethosu_device *dev) +{ + bool status_error = false; +#if !defined(ARM_NPU_STUB) + struct status_r status; + status.word = ethosu_read_reg(dev, NPU_REG_STATUS); + status_error = ((1 == status.bus_status) || (1 == status.cmd_parse_error) || (1 == status.wd_fault) || + (1 == status.ecc_fault)); +#else + UNUSED(dev); +#endif + return status_error; +} diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c index 2a2423f..6c55b0b 100644 --- a/src/ethosu_driver.c +++ b/src/ethosu_driver.c @@ -149,8 +149,9 @@ struct opt_cfg_s ******************************************************************************/ struct ethosu_driver ethosu_drv = { - .dev = {.base_address = 0, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, - .abort_inference = false}; + .dev = {.base_address = NULL, .reset = 0, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, + .abort_inference = false, + .status_error = false}; // IRQ static volatile bool irq_triggered = false; @@ -172,9 +173,15 @@ void ethosu_irq_handler(void) // Clear interrupt (void)ethosu_clear_irq_status(ðosu_drv.dev); - // Verify that interrupt has been successfully cleard + // Verify that interrupt has been successfully cleared (void)ethosu_is_irq_raised(ðosu_drv.dev, &irq_raised); ASSERT(irq_raised == 0); + + if (ethosu_status_has_error(ðosu_drv.dev)) + { + ethosu_soft_reset(ðosu_drv.dev); + ethosu_drv.status_error = true; + } } static inline void wait_for_irq(struct ethosu_driver *drv) @@ -257,6 +264,7 @@ int ethosu_init_v2(const void *base_address, const void *fast_memory, const size LOG_ERR("Failed reset of Ethos-U\n"); return -1; } + ethosu_drv.status_error = false; return return_code; } @@ -339,7 +347,11 @@ int ethosu_invoke_v2(const void *custom_data_ptr, } } - ethosu_soft_reset(ðosu_drv.dev); + if (ethosu_drv.dev.reset != ethosu_read_reg(ðosu_drv.dev, NPU_REG_PROT)) + { + ethosu_soft_reset(ðosu_drv.dev); + } + ethosu_drv.status_error = false; ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_DISABLE); ethosu_restore_pmu_config(ðosu_drv.dev); @@ -405,8 +417,11 @@ int ethosu_invoke_v2(const void *custom_data_ptr, } } - ethosu_save_pmu_config(ðosu_drv.dev); - ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE); + if (!ethosu_drv.status_error) + { + ethosu_save_pmu_config(ðosu_drv.dev); + ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE); + } return return_code; } @@ -560,6 +575,13 @@ static int handle_command_stream(struct ethosu_driver *drv, wait_for_irq(drv); + if (drv->status_error) + { + return -1; + } + + // ETHOSU would have been reset in the IRQ handler if there were + // status error(s). So don't read the QREAD register. (void)ethosu_get_qread(&drv->dev, &qread); if (qread != cms_bytes) { -- cgit v1.2.1