soc: qcom: spss_utils: protect from event signaled twice

avoid event signaled twice.
add ioctl to check if event was signaled.

Change-Id: Ie75b9db86f2badddc08d65eee30ecd6a15795256
Signed-off-by: Amir Samuelov <amirs@codeaurora.org>
This commit is contained in:
Amir Samuelov 2020-05-12 12:43:25 +03:00
commit a50479ab2e
2 changed files with 133 additions and 22 deletions

View file

@ -94,6 +94,10 @@ static phys_addr_t cmac_mem_addr;
/* 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
@ -428,6 +432,8 @@ static int spss_wait_for_event(struct spss_ioc_wait_for_event *req)
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;
@ -440,16 +446,52 @@ 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;
}
@ -464,10 +506,7 @@ static long spss_utils_ioctl(struct file *file,
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;
void *req = (void *) data;
if (buf == NULL) {
pr_err("invalid ioctl arg\n");
@ -528,10 +567,10 @@ static long spss_utils_ioctl(struct file *file,
pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size);
return -EINVAL;
}
ret = spss_wait_for_event(wait_req);
ret = spss_wait_for_event(req);
copy_to_user((void __user *)arg, data, size);
if (ret < 0)
return ret;
copy_to_user((void __user *)arg, data, size);
break;
case SPSS_IOC_SIGNAL_EVENT:
@ -540,10 +579,22 @@ static long spss_utils_ioctl(struct file *file,
pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size);
return -EINVAL;
}
ret = spss_signal_event(signal_req);
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:
@ -1035,22 +1086,56 @@ static int spss_utils_pil_callback(struct notifier_block *nb,
unsigned long code,
void *data)
{
int i;
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");
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");
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 */
@ -1076,6 +1161,7 @@ static int spss_utils_pil_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;
@ -1140,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;
@ -1147,8 +1239,6 @@ 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);
@ -1166,9 +1256,6 @@ 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;
}

View file

@ -19,22 +19,37 @@
#define SPSS_IOC_MAGIC 'S'
/* ---------- set fw cmac --------------------------------- */
#define NUM_SPU_UEFI_APPS 3
#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 ------------------------------ */
#define SPSS_NUM_EVENTS 8
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,
#define EVENT_STATUS_SIGNALED 0xAAAA
#define EVENT_STATUS_TIMEOUT 0xEEE1
#define EVENT_STATUS_ABORTED 0xEEE2
/* 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 */
@ -54,4 +69,13 @@ struct spss_ioc_signal_event {
#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_ */