NVIDIA: SAUCE: hsierrrptinj: update driver

BugLink: https://bugs.launchpad.net/bugs/2072591

Add support to return Err Rpt Inj success/failure status
to GOS user when the error is sent from GOS to FSI.

http://nvbugs/4080686

Signed-off-by: Prasun Kumar <prasunk@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Prathamesh Shete <pshete@nvidia.com>
Tested-by: Prathamesh Shete <pshete@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Acked-by: Jacob Martin <jacob.martin@canonical.com>
Acked-by: Noah Wager <noah.wager@canonical.com>
Signed-off-by: Noah Wager <noah.wager@canonical.com>
This commit is contained in:
Prasun Kumar
2023-04-22 01:10:50 +05:30
committed by Noah Wager
parent af31461933
commit 2cceb6e9ed
+77 -3
View File
@@ -70,13 +70,13 @@ struct hsm_error_report_frame {
* PSC - 1
* I2C = 10
* QSPI - 2
* SDMMC - 2
* SDMMC - 5
* TSEC - 1
* THERM - 1
* SMMU - 1
* DLA - 2
*/
static unsigned int ip_instances[NUM_IPS] = {1, 1, 5, 20, 11, 1, 10, 2, 2, 1, 1, 1, 2};
static unsigned int ip_instances[NUM_IPS] = {1, 1, 5, 20, 11, 1, 10, 2, 5, 1, 1, 1, 2};
/* This directory entry will point to `/sys/kernel/debug/tegra_hsierrrptinj`. */
static struct dentry *hsierrrptinj_debugfs_root;
@@ -101,6 +101,14 @@ struct hsierrrptinj_hsp_sm {
static struct hsierrrptinj_hsp_sm hsierrrptinj_tx;
/* Buffer len to store HSI Err Rpt Inj status */
#define ERR_INJ_STATUS_LEN 31U
/* Store stayus of error report injection */
static bool hsierrrptinj_status = true;
/* Stores the timestamp value when error was injected */
static uint32_t error_report_timestamp = 1U;
/* Register Error callbacks from IP Drivers */
int hsierrrpt_reg_cb(hsierrrpt_ipid_t ip_id, unsigned int instance_id,
@@ -219,16 +227,22 @@ static ssize_t hsierrrptinj_inject(struct file *file, const char __user *buf,
pr_debug("tegra-hsierrrptinj: Inject Error Report\n");
if (buf == NULL) {
pr_err("tegra-hsierrrptinj: Invalid null input.\n");
hsierrrptinj_status = false;
error_report_timestamp = 0;
return -EINVAL;
}
if (lbuf != ERR_RPT_LEN) {
pr_err("tegra-hsierrrptinj: Invalid input length.\n");
hsierrrptinj_status = false;
error_report_timestamp = 0;
return -EINVAL;
}
if (copy_from_user(&ubuf, buf, ERR_RPT_LEN)) {
pr_err("tegra-hsierrrptinj: Failed to copy from input buffer.\n");
hsierrrptinj_status = false;
error_report_timestamp = 0;
return -EFAULT;
}
@@ -240,12 +254,16 @@ static ssize_t hsierrrptinj_inject(struct file *file, const char __user *buf,
token = strsep(&cur, delim);
if (token == NULL) {
pr_err("tegra-hsierrrptinj: Failed to obtain token\n");
hsierrrptinj_status = false;
error_report_timestamp = 0;
return -EFAULT;
}
ret = kstrtoul(token, 16, &val);
if (ret < 0) {
pr_err("tegra-hsierrrptinj: Parsing failed. Error: %d\n", ret);
hsierrrptinj_status = false;
error_report_timestamp = 0;
return ret;
}
@@ -282,6 +300,8 @@ static ssize_t hsierrrptinj_inject(struct file *file, const char __user *buf,
if (count != NUM_INPUTS) {
pr_err("tegra-hsierrrptinj: Invalid Input format.\n");
hsierrrptinj_status = false;
error_report_timestamp = 0;
return -EINVAL;
}
@@ -300,6 +320,8 @@ static ssize_t hsierrrptinj_inject(struct file *file, const char __user *buf,
if (instance_id >= ip_instances[ip_id]) {
pr_err("tegra-hsierrrptinj: Invalid instance for IP Driver 0x%04x\n", ip_id);
hsierrrptinj_status = false;
error_report_timestamp = 0;
return -EINVAL;
}
@@ -345,11 +367,63 @@ done:
pr_err("tegra-hsierrrptinj: HSI Error ID: 0x%08x\n", error_report.error_code);
pr_err("tegra-hsierrrptinj: Timestamp: %u\n", error_report.timestamp);
if (ret != ERR_RPT_LEN) {
hsierrrptinj_status = false;
error_report_timestamp = 0;
} else {
hsierrrptinj_status = true;
error_report_timestamp = error_report.timestamp;
}
return ret;
}
/* Report the status of HSI error report injection to user */
static ssize_t hsierrrptinj_result(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
{
char ubuf[ERR_INJ_STATUS_LEN] = {0};
size_t len = 0, space = 0;
loff_t zero_offset = 0;
pr_debug("tegra-hsierrrptinj: Error Report Injection status\n");
if (buf == NULL) {
pr_err("tegra-hsierrrptinj: Invalid null buffer.\n");
return -EINVAL;
}
space = max(ERR_INJ_STATUS_LEN - *ppos, zero_offset);
len = min(space, lbuf);
if (len <= 0)
return 0;
if (hsierrrptinj_status) {
if (snprintf(ubuf, ERR_INJ_STATUS_LEN, "Success. Timestamp: %u",
error_report_timestamp) <= 0)
return -EFAULT;
} else {
if (snprintf(ubuf, ERR_INJ_STATUS_LEN, "Failure. Timestamp: %u",
error_report_timestamp) <= 0)
return -EFAULT;
}
if (*ppos < 0) {
pr_err("tegra-hsierrrptinj: Invalid offset.\n");
return -EINVAL;
}
if (copy_to_user(buf, ubuf + *ppos, len)) {
pr_err("tegra-hsierrrptinj: Failed to report status to user\n");
return -EFAULT;
}
*ppos += len;
return len;
}
static const struct file_operations hsierrrptinj_fops = {
.read = NULL,
.read = hsierrrptinj_result,
.write = hsierrrptinj_inject,
};