Commit 2dd89591 authored by Tal Cohen's avatar Tal Cohen Committed by Oded Gabbay

habanalabs: support receiving ascii message from preboot f/w

An Ascii message that is sent from preboot towards the driver
will indicate the specific error that occurred on the f/w.
This commit supports that message and parse the ascii string
in order to print it into the kernel log

The commit also changes the way the descriptor struct is declared.
While its size increased (it now above 1024 bytes), it will be
allocated by using kmalloc instead of stack declaration.
Signed-off-by: default avatarTal Cohen <talcohen@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent 2b30873a
...@@ -1915,7 +1915,7 @@ static int hl_fw_dynamic_validate_memory_bound(struct hl_device *hdev, ...@@ -1915,7 +1915,7 @@ static int hl_fw_dynamic_validate_memory_bound(struct hl_device *hdev,
* *
* @hdev: pointer to the habanalabs device structure * @hdev: pointer to the habanalabs device structure
* @fw_loader: managing structure for loading device's FW * @fw_loader: managing structure for loading device's FW
* @fw_desc: the descriptor form FW * @fw_desc: the descriptor from FW
* *
* @return 0 on success, otherwise non-zero error code * @return 0 on success, otherwise non-zero error code
*/ */
...@@ -2007,6 +2007,43 @@ static int hl_fw_dynamic_validate_response(struct hl_device *hdev, ...@@ -2007,6 +2007,43 @@ static int hl_fw_dynamic_validate_response(struct hl_device *hdev,
return rc; return rc;
} }
/*
* hl_fw_dynamic_read_descriptor_msg - read and show the ascii msg that sent by fw
*
* @hdev: pointer to the habanalabs device structure
* @fw_desc: the descriptor from FW
*/
static void hl_fw_dynamic_read_descriptor_msg(struct hl_device *hdev,
struct lkd_fw_comms_desc *fw_desc)
{
int i;
char *msg;
for (i = 0 ; i < LKD_FW_ASCII_MSG_MAX ; i++) {
if (!fw_desc->ascii_msg[i].valid)
return;
/* force NULL termination */
msg = fw_desc->ascii_msg[i].msg;
msg[LKD_FW_ASCII_MSG_MAX_LEN - 1] = '\0';
switch (fw_desc->ascii_msg[i].msg_lvl) {
case LKD_FW_ASCII_MSG_ERR:
dev_err(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg);
break;
case LKD_FW_ASCII_MSG_WRN:
dev_warn(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg);
break;
case LKD_FW_ASCII_MSG_INF:
dev_info(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg);
break;
default:
dev_dbg(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg);
break;
}
}
}
/** /**
* hl_fw_dynamic_read_and_validate_descriptor - read and validate FW descriptor * hl_fw_dynamic_read_and_validate_descriptor - read and validate FW descriptor
* *
...@@ -2071,6 +2108,10 @@ static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, ...@@ -2071,6 +2108,10 @@ static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev,
rc = hl_fw_dynamic_validate_descriptor(hdev, fw_loader, rc = hl_fw_dynamic_validate_descriptor(hdev, fw_loader,
(struct lkd_fw_comms_desc *) temp_fw_desc); (struct lkd_fw_comms_desc *) temp_fw_desc);
if (!rc)
hl_fw_dynamic_read_descriptor_msg(hdev, temp_fw_desc);
vfree(temp_fw_desc); vfree(temp_fw_desc);
return rc; return rc;
...@@ -2491,51 +2532,54 @@ static void hl_fw_linux_update_state(struct hl_device *hdev, ...@@ -2491,51 +2532,54 @@ static void hl_fw_linux_update_state(struct hl_device *hdev,
static int hl_fw_dynamic_send_msg(struct hl_device *hdev, static int hl_fw_dynamic_send_msg(struct hl_device *hdev,
struct fw_load_mgr *fw_loader, u8 msg_type, void *data) struct fw_load_mgr *fw_loader, u8 msg_type, void *data)
{ {
struct lkd_msg_comms msg; struct lkd_msg_comms *msg;
int rc; int rc;
memset(&msg, 0, sizeof(msg)); msg = kzalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
/* create message to be sent */ /* create message to be sent */
msg.header.type = msg_type; msg->header.type = msg_type;
msg.header.size = cpu_to_le16(sizeof(struct comms_msg_header)); msg->header.size = cpu_to_le16(sizeof(struct comms_msg_header));
msg.header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC); msg->header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC);
switch (msg_type) { switch (msg_type) {
case HL_COMMS_RESET_CAUSE_TYPE: case HL_COMMS_RESET_CAUSE_TYPE:
msg.reset_cause = *(__u8 *) data; msg->reset_cause = *(__u8 *) data;
break; break;
default: default:
dev_err(hdev->dev, dev_err(hdev->dev,
"Send COMMS message - invalid message type %u\n", "Send COMMS message - invalid message type %u\n",
msg_type); msg_type);
return -EINVAL; rc = -EINVAL;
goto out;
} }
rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader,
sizeof(struct lkd_msg_comms)); sizeof(struct lkd_msg_comms));
if (rc) if (rc)
return rc; goto out;
/* copy message to space allocated by FW */ /* copy message to space allocated by FW */
rc = hl_fw_dynamic_copy_msg(hdev, &msg, fw_loader); rc = hl_fw_dynamic_copy_msg(hdev, msg, fw_loader);
if (rc) if (rc)
return rc; goto out;
rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY, rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY,
0, true, 0, true,
fw_loader->cpu_timeout); fw_loader->cpu_timeout);
if (rc) if (rc)
return rc; goto out;
rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC, rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC,
0, true, 0, true,
fw_loader->cpu_timeout); fw_loader->cpu_timeout);
if (rc)
return rc;
return 0; out:
kfree(msg);
return rc;
} }
/** /**
......
...@@ -523,6 +523,23 @@ struct comms_msg_header { ...@@ -523,6 +523,23 @@ struct comms_msg_header {
__u8 reserved[4]; /* pad to 64 bit */ __u8 reserved[4]; /* pad to 64 bit */
}; };
enum lkd_fw_ascii_msg_lvls {
LKD_FW_ASCII_MSG_ERR = 0,
LKD_FW_ASCII_MSG_WRN = 1,
LKD_FW_ASCII_MSG_INF = 2,
LKD_FW_ASCII_MSG_DBG = 3,
};
#define LKD_FW_ASCII_MSG_MAX_LEN 128
#define LKD_FW_ASCII_MSG_MAX 4 /* consider ABI when changing */
struct lkd_fw_ascii_msg {
__u8 valid;
__u8 msg_lvl;
__u8 reserved[6];
char msg[LKD_FW_ASCII_MSG_MAX_LEN];
};
/* this is the main FW descriptor - consider ABI when changing */ /* this is the main FW descriptor - consider ABI when changing */
struct lkd_fw_comms_desc { struct lkd_fw_comms_desc {
struct comms_desc_header header; struct comms_desc_header header;
...@@ -533,6 +550,7 @@ struct lkd_fw_comms_desc { ...@@ -533,6 +550,7 @@ struct lkd_fw_comms_desc {
char reserved0[VERSION_MAX_LEN]; char reserved0[VERSION_MAX_LEN];
__le64 img_addr; /* address for next FW component load */ __le64 img_addr; /* address for next FW component load */
struct lkd_fw_binning_info binning_info; struct lkd_fw_binning_info binning_info;
struct lkd_fw_ascii_msg ascii_msg[LKD_FW_ASCII_MSG_MAX];
}; };
enum comms_reset_cause { enum comms_reset_cause {
...@@ -558,6 +576,7 @@ struct lkd_fw_comms_msg { ...@@ -558,6 +576,7 @@ struct lkd_fw_comms_msg {
/* address for next FW component load */ /* address for next FW component load */
__le64 img_addr; __le64 img_addr;
struct lkd_fw_binning_info binning_info; struct lkd_fw_binning_info binning_info;
struct lkd_fw_ascii_msg ascii_msg[LKD_FW_ASCII_MSG_MAX];
}; };
struct { struct {
__u8 reset_cause; __u8 reset_cause;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment