diff options
author | Ohad Sharabi <osharabi@habana.ai> | 2022-06-28 12:09:21 +0300 |
---|---|---|
committer | Oded Gabbay <ogabbay@kernel.org> | 2022-07-12 09:09:28 +0300 |
commit | 2b9e583d0aadcf6578e2595c07d3b1e898013d17 (patch) | |
tree | fb6b47e46825b27f20aa3d9e5aef122d0df2cea7 /drivers/misc/habanalabs/common/firmware_if.c | |
parent | a85e389a845825a1ed3d26dd95fe24d5ad71531d (diff) |
habanalabs: wait for preboot ready after hard reset
Currently we are not waiting for preboot ready after hard reset.
This leads to a race in which COMMs protocol begins but will get no
response from the f/w.
Signed-off-by: Ohad Sharabi <osharabi@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
Diffstat (limited to 'drivers/misc/habanalabs/common/firmware_if.c')
-rw-r--r-- | drivers/misc/habanalabs/common/firmware_if.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c index 9f0a24ee5af4..64c5cdfc6dcf 100644 --- a/drivers/misc/habanalabs/common/firmware_if.c +++ b/drivers/misc/habanalabs/common/firmware_if.c @@ -1245,15 +1245,10 @@ static void detect_cpu_boot_status(struct hl_device *hdev, u32 status) } } -static int hl_fw_read_preboot_caps(struct hl_device *hdev, - u32 cpu_boot_status_reg, - u32 sts_boot_dev_sts0_reg, - u32 sts_boot_dev_sts1_reg, - u32 boot_err0_reg, u32 boot_err1_reg, - u32 timeout) +static int hl_fw_wait_preboot_ready(struct hl_device *hdev) { - struct asic_fixed_properties *prop = &hdev->asic_prop; - u32 status, reg_val; + struct pre_fw_load_props *pre_fw_load = &hdev->fw_loader.pre_fw_load; + u32 status; int rc; /* Need to check two possible scenarios: @@ -1266,13 +1261,13 @@ static int hl_fw_read_preboot_caps(struct hl_device *hdev, */ rc = hl_poll_timeout( hdev, - cpu_boot_status_reg, + pre_fw_load->cpu_boot_status_reg, status, (status == CPU_BOOT_STATUS_NIC_FW_RDY) || (status == CPU_BOOT_STATUS_READY_TO_BOOT) || (status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT), hdev->fw_poll_interval_usec, - timeout); + pre_fw_load->wait_for_preboot_timeout); if (rc) { dev_err(hdev->dev, "CPU boot ready status timeout\n"); @@ -1282,12 +1277,32 @@ static int hl_fw_read_preboot_caps(struct hl_device *hdev, * of reading specific errors */ if (status != -1) - fw_read_errors(hdev, boot_err0_reg, boot_err1_reg, - sts_boot_dev_sts0_reg, - sts_boot_dev_sts1_reg); + fw_read_errors(hdev, pre_fw_load->boot_err0_reg, + pre_fw_load->boot_err1_reg, + pre_fw_load->sts_boot_dev_sts0_reg, + pre_fw_load->sts_boot_dev_sts1_reg); return -EIO; } + hdev->fw_loader.fw_comp_loaded |= FW_TYPE_PREBOOT_CPU; + + return 0; +} + +static int hl_fw_read_preboot_caps(struct hl_device *hdev) +{ + struct pre_fw_load_props *pre_fw_load; + struct asic_fixed_properties *prop; + u32 reg_val; + int rc; + + prop = &hdev->asic_prop; + pre_fw_load = &hdev->fw_loader.pre_fw_load; + + rc = hl_fw_wait_preboot_ready(hdev); + if (rc) + return rc; + /* * the registers DEV_STS* contain FW capabilities/features. * We can rely on this registers only if bit CPU_BOOT_DEV_STS*_ENABLED @@ -1298,13 +1313,13 @@ static int hl_fw_read_preboot_caps(struct hl_device *hdev, * In case it is not enabled the stored value will be left 0- all * caps/features are off */ - reg_val = RREG32(sts_boot_dev_sts0_reg); + reg_val = RREG32(pre_fw_load->sts_boot_dev_sts0_reg); if (reg_val & CPU_BOOT_DEV_STS0_ENABLED) { prop->fw_cpu_boot_dev_sts0_valid = true; prop->fw_preboot_cpu_boot_dev_sts0 = reg_val; } - reg_val = RREG32(sts_boot_dev_sts1_reg); + reg_val = RREG32(pre_fw_load->sts_boot_dev_sts1_reg); if (reg_val & CPU_BOOT_DEV_STS1_ENABLED) { prop->fw_cpu_boot_dev_sts1_valid = true; prop->fw_preboot_cpu_boot_dev_sts1 = reg_val; @@ -1447,24 +1462,21 @@ static int hl_fw_static_read_preboot_status(struct hl_device *hdev) return 0; } -int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 sts_boot_dev_sts0_reg, - u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, - u32 boot_err1_reg, u32 timeout) +int hl_fw_read_preboot_status(struct hl_device *hdev) { int rc; if (!(hdev->fw_components & FW_TYPE_PREBOOT_CPU)) return 0; + /* get FW pre-load parameters */ + hdev->asic_funcs->init_firmware_preload_params(hdev); + /* * In order to determine boot method (static VS dymanic) we need to * read the boot caps register */ - rc = hl_fw_read_preboot_caps(hdev, cpu_boot_status_reg, - sts_boot_dev_sts0_reg, - sts_boot_dev_sts1_reg, boot_err0_reg, - boot_err1_reg, timeout); + rc = hl_fw_read_preboot_caps(hdev); if (rc) return rc; @@ -2454,6 +2466,13 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, */ dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; + /* if no preboot loaded indication- wait for preboot */ + if (!(hdev->fw_loader.fw_comp_loaded & FW_TYPE_PREBOOT_CPU)) { + rc = hl_fw_wait_preboot_ready(hdev); + if (rc) + return -EIO; + } + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_RST_STATE, 0, true, fw_loader->cpu_timeout); |