From 09c2045118b2ea135a63b86950e9eb260b39ce10 Mon Sep 17 00:00:00 2001 From: Amir Samuelov Date: Mon, 11 May 2020 12:53:28 +0300 Subject: [PATCH] soc: qcom: spss_utils: add spss events support Add IOCTL for wait/signal spss events. Change-Id: Ia8ad37a1632de21e6ae4e70013ca72b4b35c68ba Signed-off-by: Amir Samuelov --- drivers/soc/qcom/spss_utils.c | 118 ++++++++++++++++++++++++++++++-- include/uapi/linux/spss_utils.h | 29 +++++++- 2 files changed, 139 insertions(+), 8 deletions(-) diff --git a/drivers/soc/qcom/spss_utils.c b/drivers/soc/qcom/spss_utils.c index 3314b137c9f9..a88f3c195f62 100644 --- a/drivers/soc/qcom/spss_utils.c +++ b/drivers/soc/qcom/spss_utils.c @@ -33,6 +33,7 @@ #include #include /* SZ_4K */ #include /* copy_from_user() */ +#include /* wait_for_completion_timeout() */ #include #include @@ -91,6 +92,9 @@ static phys_addr_t cmac_mem_addr; #define SPU_EMULATUION (BIT(0) | BIT(1)) #define SPU_PRESENT_IN_EMULATION BIT(0) +/* Events notification */ +static struct completion spss_events[SPSS_NUM_EVENTS]; + /** * struct device state */ @@ -386,15 +390,84 @@ static void spss_destroy_sysfs(struct device *dev) /*==========================================================================*/ /* IOCTL */ /*==========================================================================*/ +static int spss_wait_for_event(struct spss_ioc_wait_for_event *req) +{ + int ret; + uint32_t event_id; + uint32_t timeout_sec; + long timeleft = 1; + + event_id = req->event_id; + timeout_sec = req->timeout_sec; + + if (event_id >= SPSS_NUM_EVENTS) { + pr_err("event_id [%d] invalid\n", event_id); + return -EINVAL; + } + + pr_debug("wait for event [%d], timeout_sec [%d]\n", + event_id, timeout_sec); + + if (timeout_sec) { + unsigned long jiffies = 0; + + jiffies = msecs_to_jiffies(timeout_sec*1000); + timeleft = wait_for_completion_interruptible_timeout( + &spss_events[event_id], jiffies); + ret = timeleft; + } else { + ret = wait_for_completion_interruptible( + &spss_events[event_id]); + } + + if (timeleft == 0) { + pr_err("wait for event [%d] timeout [%d] sec expired\n", + event_id, timeout_sec); + req->status = EVENT_STATUS_TIMEOUT; + } else if (ret < 0) { + pr_err("wait for event [%d] interrupted. ret [%d]\n", + event_id, ret); + req->status = EVENT_STATUS_ABORTED; + } else { + pr_debug("wait for event [%d] completed.\n", event_id); + req->status = EVENT_STATUS_SIGNALED; + } + + return 0; +} + +static int spss_signal_event(struct spss_ioc_signal_event *req) +{ + uint32_t event_id; + + event_id = req->event_id; + + if (event_id >= SPSS_NUM_EVENTS) { + pr_err("event_id [%d] invalid\n", event_id); + return -EINVAL; + } + + pr_debug("signal event [%d]\n", event_id); + complete_all(&spss_events[event_id]); + req->status = EVENT_STATUS_SIGNALED; + + return 0; +} + static long spss_utils_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + int ret; void *buf = (void *) arg; unsigned char data[64] = {0}; size_t size = 0; u32 i = 0; /* Saved cmacs of spu firmware and UEFI loaded spu apps */ u32 fw_and_apps_cmacs[FW_AND_APPS_CMAC_SIZE]; + struct spss_ioc_wait_for_event *wait_req = + (struct spss_ioc_wait_for_event *) data; + struct spss_ioc_signal_event *signal_req = + (struct spss_ioc_signal_event *) data; if (buf == NULL) { pr_err("invalid ioctl arg\n"); @@ -439,7 +512,7 @@ static long spss_utils_ioctl(struct file *file, /* * SPSS is loaded now by UEFI, - * so IAR callback is not being called on powerup by PIL. + * so IAR callback is not being called on power-up by PIL. * therefore read the spu pbl fw cmac and apps cmac from ioctl. * The callback shall be called on spss SSR. */ @@ -449,6 +522,30 @@ static long spss_utils_ioctl(struct file *file, spss_get_saved_uefi_apps_cmac(); break; + case SPSS_IOC_WAIT_FOR_EVENT: + /* check input params */ + if (size != sizeof(struct spss_ioc_wait_for_event)) { + pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size); + return -EINVAL; + } + ret = spss_wait_for_event(wait_req); + if (ret < 0) + return ret; + copy_to_user((void __user *)arg, data, size); + break; + + case SPSS_IOC_SIGNAL_EVENT: + /* check input params */ + if (size != sizeof(struct spss_ioc_signal_event)) { + pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size); + return -EINVAL; + } + ret = spss_signal_event(signal_req); + if (ret < 0) + return ret; + copy_to_user((void __user *)arg, data, size); + break; + default: pr_err("invalid ioctl cmd [0x%x]\n", cmd); return -EINVAL; @@ -797,7 +894,7 @@ static int spss_parse_dt(struct device_node *node) iar_state = val1; - pr_info("iar_state [%d]\n", iar_state); + pr_debug("iar_state [%d]\n", iar_state); return 0; } @@ -934,13 +1031,11 @@ static int spss_set_saved_uefi_apps_cmac(void) return 0; } -static int spss_utils_iar_callback(struct notifier_block *nb, +static int spss_utils_pil_callback(struct notifier_block *nb, unsigned long code, void *data) { - /* do nothing if IAR is not active */ - if (!is_iar_active) - return NOTIFY_OK; + int i; switch (code) { case SUBSYS_BEFORE_SHUTDOWN: @@ -951,11 +1046,16 @@ static int spss_utils_iar_callback(struct notifier_block *nb, break; case SUBSYS_BEFORE_POWERUP: pr_debug("[SUBSYS_BEFORE_POWERUP] event.\n"); + for (i = 0 ; i < SPSS_NUM_EVENTS; i++) + reinit_completion(&spss_events[i]); break; case SUBSYS_AFTER_POWERUP: pr_debug("[SUBSYS_AFTER_POWERUP] event.\n"); break; case SUBSYS_BEFORE_AUTH_AND_RESET: + /* do nothing if IAR is not active */ + if (!is_iar_active) + return NOTIFY_OK; pr_debug("[SUBSYS_BEFORE_AUTH_AND_RESET] event.\n"); /* Called on SSR as spss firmware is loaded by UEFI */ spss_set_fw_cmac(cmac_buf, sizeof(cmac_buf)); @@ -1030,7 +1130,7 @@ static int spss_probe(struct platform_device *pdev) if (!iar_nb) return -ENOMEM; - iar_nb->notifier_call = spss_utils_iar_callback; + iar_nb->notifier_call = spss_utils_pil_callback; iar_notif_handle = subsys_notif_register_notifier("spss", iar_nb); if (IS_ERR_OR_NULL(iar_notif_handle)) { @@ -1047,6 +1147,7 @@ static int spss_probe(struct platform_device *pdev) static int spss_remove(struct platform_device *pdev) { + int i; spss_utils_destroy_chardev(); spss_destroy_sysfs(spss_dev); @@ -1065,6 +1166,9 @@ static int spss_remove(struct platform_device *pdev) cmac_mem = NULL; } + for (i = 0 ; i < SPSS_NUM_EVENTS; i++) + init_completion(&spss_events[i]); + return 0; } diff --git a/include/uapi/linux/spss_utils.h b/include/uapi/linux/spss_utils.h index c767dbcc531e..5f17c0c5c663 100644 --- a/include/uapi/linux/spss_utils.h +++ b/include/uapi/linux/spss_utils.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _UAPI_SPSS_UTILS_H_ @@ -17,6 +17,8 @@ */ #define SPSS_IOC_MAGIC 'S' + +/* ---------- set fw cmac --------------------------------- */ #define NUM_SPU_UEFI_APPS 3 struct spss_ioc_set_fw_cmac { @@ -27,4 +29,29 @@ struct spss_ioc_set_fw_cmac { #define SPSS_IOC_SET_FW_CMAC \ _IOWR(SPSS_IOC_MAGIC, 1, struct spss_ioc_set_fw_cmac) +/* ---------- wait for event ------------------------------ */ +#define SPSS_NUM_EVENTS 8 + +#define EVENT_STATUS_SIGNALED 0xAAAA +#define EVENT_STATUS_TIMEOUT 0xEEE1 +#define EVENT_STATUS_ABORTED 0xEEE2 + +struct spss_ioc_wait_for_event { + uint32_t event_id; /* input */ + uint32_t timeout_sec; /* input */ + uint32_t status; /* output */ +} __packed; + +#define SPSS_IOC_WAIT_FOR_EVENT \ + _IOWR(SPSS_IOC_MAGIC, 2, struct spss_ioc_wait_for_event) + +/* ---------- signal event ------------------------------ */ +struct spss_ioc_signal_event { + uint32_t event_id; /* input */ + uint32_t status; /* output */ +} __packed; + +#define SPSS_IOC_SIGNAL_EVENT \ + _IOWR(SPSS_IOC_MAGIC, 3, struct spss_ioc_signal_event) + #endif /* _UAPI_SPSS_UTILS_H_ */