#include <linux/firmware.h>
#include <linux/crc32.h>
#include <linux/slab.h>
+#include <linux/ctype.h>
#define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */
#define FW_CPU_STATUS_POLL_INTERVAL_USEC 10000
+static char *extract_fw_ver_from_str(const char *fw_str)
+{
+ char *str, *fw_ver, *whitespace;
+
+ fw_ver = kmalloc(16, GFP_KERNEL);
+ if (!fw_ver)
+ return NULL;
+
+ str = strnstr(fw_str, "fw-", VERSION_MAX_LEN);
+ if (!str)
+ goto free_fw_ver;
+
+ /* Skip the fw- part */
+ str += 3;
+
+ /* Copy until the next whitespace */
+ whitespace = strnstr(str, " ", 15);
+ if (!whitespace)
+ goto free_fw_ver;
+
+ strscpy(fw_ver, str, whitespace - str + 1);
+
+ return fw_ver;
+
+free_fw_ver:
+ kfree(fw_ver);
+ return NULL;
+}
+
static int hl_request_fw(struct hl_device *hdev,
const struct firmware **firmware_p,
const char *fw_name)
{
struct asic_fixed_properties *prop = &hdev->asic_prop;
struct cpucp_packet pkt = {};
- void *cpucp_info_cpu_addr;
dma_addr_t cpucp_info_dma_addr;
+ void *cpucp_info_cpu_addr;
+ char *kernel_ver;
u64 result;
int rc;
goto out;
}
+ kernel_ver = extract_fw_ver_from_str(prop->cpucp_info.kernel_version);
+ if (kernel_ver) {
+ dev_info(hdev->dev, "Linux version %s", kernel_ver);
+ kfree(kernel_ver);
+ }
+
/* assume EQ code doesn't need to check eqe index */
hdev->event_queue.check_eqe_index = false;
static int hl_fw_static_read_device_fw_version(struct hl_device *hdev,
enum hl_fw_component fwc)
{
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
struct fw_load_mgr *fw_loader = &hdev->fw_loader;
struct static_fw_load_mgr *static_loader;
- const char *name;
+ char *dest, *boot_ver, *preboot_ver;
u32 ver_off, limit;
- char *dest;
+ const char *name;
+ char btl_ver[32];
static_loader = &hdev->fw_loader.static_loader;
switch (fwc) {
case FW_COMP_BOOT_FIT:
ver_off = RREG32(static_loader->boot_fit_version_offset_reg);
- dest = hdev->asic_prop.uboot_ver;
+ dest = prop->uboot_ver;
name = "Boot-fit";
limit = static_loader->boot_fit_version_max_off;
break;
case FW_COMP_PREBOOT:
ver_off = RREG32(static_loader->preboot_version_offset_reg);
- dest = hdev->asic_prop.preboot_ver;
+ dest = prop->preboot_ver;
name = "Preboot";
limit = static_loader->preboot_version_max_off;
break;
return -EIO;
}
+ if (fwc == FW_COMP_BOOT_FIT) {
+ boot_ver = extract_fw_ver_from_str(prop->uboot_ver);
+ if (boot_ver) {
+ dev_info(hdev->dev, "boot-fit version %s\n", boot_ver);
+ kfree(boot_ver);
+ }
+ } else if (fwc == FW_COMP_PREBOOT) {
+ preboot_ver = strnstr(prop->preboot_ver, "Preboot",
+ VERSION_MAX_LEN);
+ if (preboot_ver && preboot_ver != prop->preboot_ver) {
+ strscpy(btl_ver, prop->preboot_ver,
+ min((int) (preboot_ver - prop->preboot_ver),
+ 31));
+ dev_info(hdev->dev, "%s\n", btl_ver);
+ }
+
+ preboot_ver = extract_fw_ver_from_str(prop->preboot_ver);
+ if (preboot_ver) {
+ dev_info(hdev->dev, "preboot version %s\n",
+ preboot_ver);
+ kfree(preboot_ver);
+ }
+ }
+
return 0;
}
enum hl_fw_component fwc,
const char *fw_version)
{
- char *dest;
+ struct asic_fixed_properties *prop = &hdev->asic_prop;
+ char *preboot_ver, *boot_ver;
+ char btl_ver[32];
switch (fwc) {
case FW_COMP_BOOT_FIT:
- dest = hdev->asic_prop.uboot_ver;
+ strscpy(prop->uboot_ver, fw_version, VERSION_MAX_LEN);
+ boot_ver = extract_fw_ver_from_str(prop->uboot_ver);
+ if (boot_ver) {
+ dev_info(hdev->dev, "boot-fit version %s\n", boot_ver);
+ kfree(boot_ver);
+ }
+
break;
case FW_COMP_PREBOOT:
- dest = hdev->asic_prop.preboot_ver;
+ strscpy(prop->preboot_ver, fw_version, VERSION_MAX_LEN);
+ preboot_ver = strnstr(prop->preboot_ver, "Preboot",
+ VERSION_MAX_LEN);
+ if (preboot_ver && preboot_ver != prop->preboot_ver) {
+ strscpy(btl_ver, prop->preboot_ver,
+ min((int) (preboot_ver - prop->preboot_ver),
+ 31));
+ dev_info(hdev->dev, "%s\n", btl_ver);
+ }
+
+ preboot_ver = extract_fw_ver_from_str(prop->preboot_ver);
+ if (preboot_ver) {
+ dev_info(hdev->dev, "preboot version %s\n",
+ preboot_ver);
+ kfree(preboot_ver);
+ }
+
break;
default:
dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc);
return;
}
-
- strscpy(dest, fw_version, VERSION_MAX_LEN);
}
/**