mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
Merge "soc: qcom: spss_utils: protect from event signaled twice"
This commit is contained in:
commit
182eb05c1e
2 changed files with 254 additions and 12 deletions
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/notifier.h>
|
||||
#include <linux/sizes.h> /* SZ_4K */
|
||||
#include <linux/uaccess.h> /* copy_from_user() */
|
||||
#include <linux/completion.h> /* wait_for_completion_timeout() */
|
||||
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
#include <soc/qcom/subsystem_restart.h>
|
||||
|
|
@ -91,6 +92,13 @@ 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];
|
||||
static bool spss_events_signaled[SPSS_NUM_EVENTS];
|
||||
|
||||
/* Protect from ioctl signal func called by multiple-proc at the same time */
|
||||
static struct mutex event_lock;
|
||||
|
||||
/**
|
||||
* struct device state
|
||||
*/
|
||||
|
|
@ -386,15 +394,119 @@ 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;
|
||||
if (ret == -ERESTARTSYS) /* handle LPM event */
|
||||
return ret;
|
||||
} 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;
|
||||
|
||||
mutex_lock(&event_lock);
|
||||
|
||||
event_id = req->event_id;
|
||||
|
||||
if (event_id >= SPSS_NUM_EVENTS) {
|
||||
pr_err("event_id [%d] invalid\n", event_id);
|
||||
mutex_unlock(&event_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (spss_events_signaled[event_id]) {
|
||||
pr_err("event_id [%d] already signaled\n", event_id);
|
||||
mutex_unlock(&event_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("signal event [%d]\n", event_id);
|
||||
complete_all(&spss_events[event_id]);
|
||||
req->status = EVENT_STATUS_SIGNALED;
|
||||
spss_events_signaled[event_id] = true;
|
||||
|
||||
mutex_unlock(&event_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spss_is_event_signaled(struct spss_ioc_is_signaled *req)
|
||||
{
|
||||
uint32_t event_id;
|
||||
|
||||
mutex_lock(&event_lock);
|
||||
|
||||
event_id = req->event_id;
|
||||
|
||||
if (event_id >= SPSS_NUM_EVENTS) {
|
||||
pr_err("event_id [%d] invalid\n", event_id);
|
||||
mutex_unlock(&event_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (spss_events_signaled[event_id])
|
||||
req->status = EVENT_STATUS_SIGNALED;
|
||||
else
|
||||
req->status = EVENT_STATUS_NOT_SIGNALED;
|
||||
|
||||
mutex_unlock(&event_lock);
|
||||
|
||||
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];
|
||||
void *req = (void *) data;
|
||||
|
||||
if (buf == NULL) {
|
||||
pr_err("invalid ioctl arg\n");
|
||||
|
|
@ -439,7 +551,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 +561,42 @@ 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(req);
|
||||
copy_to_user((void __user *)arg, data, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
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(req);
|
||||
copy_to_user((void __user *)arg, data, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case SPSS_IOC_IS_EVENT_SIGNALED:
|
||||
/* check input params */
|
||||
if (size != sizeof(struct spss_ioc_is_signaled)) {
|
||||
pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = spss_is_event_signaled(req);
|
||||
copy_to_user((void __user *)arg, data, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("invalid ioctl cmd [0x%x]\n", cmd);
|
||||
return -EINVAL;
|
||||
|
|
@ -797,7 +945,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,28 +1082,65 @@ 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, event_id;
|
||||
|
||||
switch (code) {
|
||||
case SUBSYS_BEFORE_SHUTDOWN:
|
||||
pr_debug("[SUBSYS_BEFORE_SHUTDOWN] event.\n");
|
||||
mutex_lock(&event_lock);
|
||||
/* Reset NVM-ready and SPU-ready events */
|
||||
for (i = SPSS_EVENT_ID_NVM_READY;
|
||||
i <= SPSS_EVENT_ID_SPU_READY; i++) {
|
||||
reinit_completion(&spss_events[i]);
|
||||
spss_events_signaled[i] = false;
|
||||
}
|
||||
mutex_unlock(&event_lock);
|
||||
pr_debug("reset spss events.\n");
|
||||
break;
|
||||
case SUBSYS_AFTER_SHUTDOWN:
|
||||
pr_debug("[SUBSYS_AFTER_SHUTDOWN] event.\n");
|
||||
mutex_lock(&event_lock);
|
||||
event_id = SPSS_EVENT_ID_SPU_POWER_DOWN;
|
||||
complete_all(&spss_events[event_id]);
|
||||
spss_events_signaled[event_id] = true;
|
||||
|
||||
event_id = SPSS_EVENT_ID_SPU_POWER_UP;
|
||||
reinit_completion(&spss_events[event_id]);
|
||||
spss_events_signaled[event_id] = false;
|
||||
mutex_unlock(&event_lock);
|
||||
break;
|
||||
case SUBSYS_BEFORE_POWERUP:
|
||||
pr_debug("[SUBSYS_BEFORE_POWERUP] event.\n");
|
||||
break;
|
||||
case SUBSYS_AFTER_POWERUP:
|
||||
pr_debug("[SUBSYS_AFTER_POWERUP] event.\n");
|
||||
mutex_lock(&event_lock);
|
||||
event_id = SPSS_EVENT_ID_SPU_POWER_UP;
|
||||
complete_all(&spss_events[event_id]);
|
||||
spss_events_signaled[event_id] = true;
|
||||
|
||||
event_id = SPSS_EVENT_ID_SPU_POWER_DOWN;
|
||||
reinit_completion(&spss_events[event_id]);
|
||||
spss_events_signaled[event_id] = false;
|
||||
mutex_unlock(&event_lock);
|
||||
break;
|
||||
case SUBSYS_RAMDUMP_NOTIFICATION:
|
||||
pr_debug("[SUBSYS_RAMDUMP_NOTIFICATION] event.\n");
|
||||
break;
|
||||
case SUBSYS_PROXY_VOTE:
|
||||
pr_debug("[SUBSYS_PROXY_VOTE] event.\n");
|
||||
break;
|
||||
case SUBSYS_PROXY_UNVOTE:
|
||||
pr_debug("[SUBSYS_PROXY_UNVOTE] 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));
|
||||
|
|
@ -976,6 +1161,7 @@ static int spss_utils_iar_callback(struct notifier_block *nb,
|
|||
static int spss_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
struct device_node *np = NULL;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
|
|
@ -1030,7 +1216,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)) {
|
||||
|
|
@ -1040,6 +1226,12 @@ static int spss_probe(struct platform_device *pdev)
|
|||
iar_nb = NULL;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < SPSS_NUM_EVENTS; i++) {
|
||||
init_completion(&spss_events[i]);
|
||||
spss_events_signaled[i] = false;
|
||||
}
|
||||
mutex_init(&event_lock);
|
||||
|
||||
pr_info("Probe completed successfully, [%s].\n", firmware_name);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1047,7 +1239,6 @@ static int spss_probe(struct platform_device *pdev)
|
|||
|
||||
static int spss_remove(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
spss_utils_destroy_chardev();
|
||||
spss_destroy_sysfs(spss_dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,14 +17,65 @@
|
|||
*/
|
||||
|
||||
#define SPSS_IOC_MAGIC 'S'
|
||||
#define NUM_SPU_UEFI_APPS 3
|
||||
|
||||
/* ---------- set fw cmac --------------------------------- */
|
||||
#define NUM_SPU_UEFI_APPS 3
|
||||
#define CMAC_SIZE_IN_WORDS 4
|
||||
|
||||
struct spss_ioc_set_fw_cmac {
|
||||
__u32 cmac[4];
|
||||
__u32 app_cmacs[NUM_SPU_UEFI_APPS][4];
|
||||
uint32_t cmac[CMAC_SIZE_IN_WORDS];
|
||||
uint32_t app_cmacs[NUM_SPU_UEFI_APPS][CMAC_SIZE_IN_WORDS];
|
||||
} __packed;
|
||||
|
||||
#define SPSS_IOC_SET_FW_CMAC \
|
||||
_IOWR(SPSS_IOC_MAGIC, 1, struct spss_ioc_set_fw_cmac)
|
||||
|
||||
/* ---------- wait for event ------------------------------ */
|
||||
enum spss_event_id {
|
||||
/* signaled from user */
|
||||
SPSS_EVENT_ID_PIL_CALLED = 0,
|
||||
SPSS_EVENT_ID_NVM_READY = 1,
|
||||
SPSS_EVENT_ID_SPU_READY = 2,
|
||||
SPSS_NUM_USER_EVENTS,
|
||||
|
||||
/* signaled from kernel */
|
||||
SPSS_EVENT_ID_SPU_POWER_DOWN = 6,
|
||||
SPSS_EVENT_ID_SPU_POWER_UP = 7,
|
||||
SPSS_NUM_EVENTS,
|
||||
};
|
||||
|
||||
enum spss_event_status {
|
||||
EVENT_STATUS_SIGNALED = 0xAAAA,
|
||||
EVENT_STATUS_NOT_SIGNALED = 0xFFFF,
|
||||
EVENT_STATUS_TIMEOUT = 0xEEE1,
|
||||
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)
|
||||
|
||||
/* ---------- is event isgnaled ------------------------------ */
|
||||
struct spss_ioc_is_signaled {
|
||||
uint32_t event_id; /* input */
|
||||
uint32_t status; /* output */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SPSS_IOC_IS_EVENT_SIGNALED \
|
||||
_IOWR(SPSS_IOC_MAGIC, 4, struct spss_ioc_is_signaled)
|
||||
|
||||
#endif /* _UAPI_SPSS_UTILS_H_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue