From 2bf9abc13cf59c4a0f98804169ac3173459ef75b Mon Sep 17 00:00:00 2001 From: Kasin Li Date: Fri, 5 Mar 2021 23:16:50 +0800 Subject: [PATCH] soc: qcom: hgsl: decouple ifence and doorbell In systems doorbell is not valid, could set db-off flag to 1. Then the driver still could probe and disable doorbell and hfence commands. ifence still works. Change-Id: I6d4e171d64dfc183f5d500fbd1180adb4b108a63 Signed-off-by: Kasin Li --- drivers/soc/qcom/hgsl/hgsl.c | 80 ++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/drivers/soc/qcom/hgsl/hgsl.c b/drivers/soc/qcom/hgsl/hgsl.c index 0d5a6cad2616..2cf0bfc23e69 100644 --- a/drivers/soc/qcom/hgsl/hgsl.c +++ b/drivers/soc/qcom/hgsl/hgsl.c @@ -289,6 +289,9 @@ struct qcom_hgsl { struct doorbell_queue dbq[MAX_DB_QUEUE]; + /* Could disable db and use isync only */ + bool db_off; + /* global doorbell tcsr */ struct hgsl_tcsr *tcsr[HGSL_TCSR_NUM][HGSL_TCSR_ROLE_MAX]; int tcsr_idx; @@ -550,6 +553,11 @@ static int hgsl_cmdstream_db_issueib(struct file *filep, int idx; int ret = 0; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + copy_from_user(&submit_info, USRPTR(arg), sizeof(submit_info)); if (!hgsl_ctx_dbq_ready(priv)) { @@ -665,6 +673,11 @@ static int hgsl_dbq_assign(struct file *filep, unsigned long arg) struct doorbell_queue *dbq; unsigned int dbq_idx; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + if (copy_from_user(&dbq_idx, USRPTR(arg), sizeof(dbq_idx))) return -EFAULT; @@ -875,6 +888,11 @@ static int hgsl_dbq_init(struct file *filep, unsigned long arg) int tcsr_idx; int ret; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + copy_from_user(¶m, USRPTR(arg), sizeof(param)); if (param.fd < 0) { dev_err(hgsl->dev, "Invalid dbq fd\n"); @@ -969,6 +987,11 @@ static int hgsl_context_create(struct file *filep, unsigned long arg) struct hgsl_context *ctxt; int ret = 0; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + if (!hgsl->contexts) { dev_err(hgsl->dev, "DBQ not initialized propertily\n"); return -ENODEV; @@ -1068,6 +1091,11 @@ static int hgsl_context_destroy(struct file *filep, unsigned long arg, uint32_t context_id; struct hgsl_context *ctxt; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + if (!is_global_db(hgsl->tcsr_idx)) { dev_err(hgsl->dev, "Global doorbell not supported for this process\n"); return -ENODEV; @@ -1120,6 +1148,11 @@ static int hgsl_wait_timestamp(struct file *filep, unsigned long arg) unsigned int timestamp; int ret; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + if (!is_global_db(hgsl->tcsr_idx)) { dev_err(hgsl->dev, "Global doorbell not supported for this process\n"); return -ENODEV; @@ -1193,6 +1226,11 @@ static int hgsl_dbq_release(struct file *filep, unsigned long arg, struct hgsl_dbq_release_info rel_info; int ret = 0; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + if (!force_cleanup) ret = copy_from_user(&rel_info, USRPTR(arg), sizeof(rel_info)); @@ -1272,10 +1310,13 @@ static ssize_t hgsl_read(struct file *filep, char __user *buf, size_t count, uint32_t release = 0; char buff[100]; - hgsl_reg_read(&hgsl->reg_ver, 0, &version); - hgsl_reg_read(&hgsl->reg_ver, 4, &release); - snprintf(buff, 100, "gpu HW Version:%x HW Release:%x\n", + if (!hgsl->db_off) { + hgsl_reg_read(&hgsl->reg_ver, 0, &version); + hgsl_reg_read(&hgsl->reg_ver, 4, &release); + snprintf(buff, 100, "gpu HW Version:%x HW Release:%x\n", version, release); + } else + snprintf(buff, 100, "Doorbell closed\n"); return simple_read_from_buffer(buf, count, pos, buff, strlen(buff) + 1); @@ -1290,6 +1331,11 @@ static int hgsl_ioctl_hsync_fence_create(struct file *filep, struct hgsl_context *ctxt; int ret = 0; + if (hgsl->db_off) { + dev_err(hgsl->dev, "Doorbell not open\n"); + return -EPERM; + } + copy_from_user(¶m, USRPTR(arg), sizeof(param)); read_lock(&hgsl->ctxt_lock); @@ -1529,6 +1575,18 @@ static void qcom_hgsl_deregister(struct platform_device *pdev) unregister_chrdev_region(hgsl_dev->device_no, HGSL_DEV_NUM); } +static bool hgsl_is_db_off(struct platform_device *pdev) +{ + uint32_t db_off = 0; + + if (pdev == NULL) + return true; + + of_property_read_u32(pdev->dev.of_node, "db-off", &db_off); + + return db_off == 1 ? true : false; +} + static int hgsl_reg_map(struct platform_device *pdev, char *res_name, struct reg *reg) { @@ -1600,13 +1658,19 @@ static int qcom_hgsl_probe(struct platform_device *pdev) return ret; } - ret = hgsl_reg_map(pdev, IORESOURCE_HWINF, &hgsl_dev->reg_ver); - if (ret < 0) { - dev_err(&pdev->dev, "Unable to map resource:%s\n", - IORESOURCE_HWINF); - goto exit_dereg; + hgsl_dev->db_off = hgsl_is_db_off(pdev); + + if (!hgsl_dev->db_off) { + ret = hgsl_reg_map(pdev, IORESOURCE_HWINF, + &hgsl_dev->reg_ver); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to map resource:%s\n", + IORESOURCE_HWINF); + goto exit_dereg; + } } + for (i = 0; i < MAX_DB_QUEUE; i++) { mutex_init(&hgsl_dev->dbq[i].lock); hgsl_dev->dbq[i].state = DB_STATE_Q_UNINIT;