mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
This was done entirely with mindless brute force, using
git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' |
xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/'
to convert the new alloc_obj() users that had a simple GFP_KERNEL
argument to just drop that argument.
Note that due to the extreme simplicity of the scripting, any slightly
more complex cases spread over multiple lines would not be triggered:
they definitely exist, but this covers the vast bulk of the cases, and
the resulting diff is also then easier to check automatically.
For the same reason the 'flex' versions will be done as a separate
conversion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
131 lines
2.6 KiB
C
131 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2015-2021, Linaro Limited
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/arm-smccc.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/tee_core.h>
|
|
#include "optee_private.h"
|
|
|
|
struct notif_entry {
|
|
struct list_head link;
|
|
struct completion c;
|
|
u_int key;
|
|
};
|
|
|
|
static bool have_key(struct optee *optee, u_int key)
|
|
{
|
|
struct notif_entry *entry;
|
|
|
|
list_for_each_entry(entry, &optee->notif.db, link)
|
|
if (entry->key == key)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
int optee_notif_wait(struct optee *optee, u_int key, u32 timeout)
|
|
{
|
|
unsigned long flags;
|
|
struct notif_entry *entry;
|
|
int rc = 0;
|
|
|
|
if (key > optee->notif.max_key)
|
|
return -EINVAL;
|
|
|
|
entry = kmalloc_obj(*entry);
|
|
if (!entry)
|
|
return -ENOMEM;
|
|
init_completion(&entry->c);
|
|
entry->key = key;
|
|
|
|
spin_lock_irqsave(&optee->notif.lock, flags);
|
|
|
|
/*
|
|
* If the bit is already set it means that the key has already
|
|
* been posted and we must not wait.
|
|
*/
|
|
if (test_bit(key, optee->notif.bitmap)) {
|
|
clear_bit(key, optee->notif.bitmap);
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Check if someone is already waiting for this key. If there is
|
|
* it's a programming error.
|
|
*/
|
|
if (have_key(optee, key)) {
|
|
rc = -EBUSY;
|
|
goto out;
|
|
}
|
|
|
|
list_add_tail(&entry->link, &optee->notif.db);
|
|
|
|
/*
|
|
* Unlock temporarily and wait for completion.
|
|
*/
|
|
spin_unlock_irqrestore(&optee->notif.lock, flags);
|
|
if (timeout != 0) {
|
|
if (!wait_for_completion_timeout(&entry->c, timeout))
|
|
rc = -ETIMEDOUT;
|
|
} else {
|
|
wait_for_completion(&entry->c);
|
|
}
|
|
spin_lock_irqsave(&optee->notif.lock, flags);
|
|
|
|
list_del(&entry->link);
|
|
out:
|
|
spin_unlock_irqrestore(&optee->notif.lock, flags);
|
|
|
|
kfree(entry);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int optee_notif_send(struct optee *optee, u_int key)
|
|
{
|
|
unsigned long flags;
|
|
struct notif_entry *entry;
|
|
|
|
if (key > optee->notif.max_key)
|
|
return -EINVAL;
|
|
|
|
spin_lock_irqsave(&optee->notif.lock, flags);
|
|
|
|
list_for_each_entry(entry, &optee->notif.db, link)
|
|
if (entry->key == key) {
|
|
complete(&entry->c);
|
|
goto out;
|
|
}
|
|
|
|
/* Only set the bit in case there where nobody waiting */
|
|
set_bit(key, optee->notif.bitmap);
|
|
out:
|
|
spin_unlock_irqrestore(&optee->notif.lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int optee_notif_init(struct optee *optee, u_int max_key)
|
|
{
|
|
spin_lock_init(&optee->notif.lock);
|
|
INIT_LIST_HEAD(&optee->notif.db);
|
|
optee->notif.bitmap = bitmap_zalloc(max_key, GFP_KERNEL);
|
|
if (!optee->notif.bitmap)
|
|
return -ENOMEM;
|
|
|
|
optee->notif.max_key = max_key;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void optee_notif_uninit(struct optee *optee)
|
|
{
|
|
bitmap_free(optee->notif.bitmap);
|
|
}
|