1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015-2021, Linaro Limited
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/arm-smccc.h>
9 #include <linux/errno.h>
10 #include <linux/slab.h>
11 #include <linux/spinlock.h>
12 #include <linux/tee_core.h>
13 #include "optee_private.h"
16 struct list_head link
;
21 static bool have_key(struct optee
*optee
, u_int key
)
23 struct notif_entry
*entry
;
25 list_for_each_entry(entry
, &optee
->notif
.db
, link
)
26 if (entry
->key
== key
)
32 int optee_notif_wait(struct optee
*optee
, u_int key
, u32 timeout
)
35 struct notif_entry
*entry
;
38 if (key
> optee
->notif
.max_key
)
41 entry
= kmalloc(sizeof(*entry
), GFP_KERNEL
);
44 init_completion(&entry
->c
);
47 spin_lock_irqsave(&optee
->notif
.lock
, flags
);
50 * If the bit is already set it means that the key has already
51 * been posted and we must not wait.
53 if (test_bit(key
, optee
->notif
.bitmap
)) {
54 clear_bit(key
, optee
->notif
.bitmap
);
59 * Check if someone is already waiting for this key. If there is
60 * it's a programming error.
62 if (have_key(optee
, key
)) {
67 list_add_tail(&entry
->link
, &optee
->notif
.db
);
70 * Unlock temporarily and wait for completion.
72 spin_unlock_irqrestore(&optee
->notif
.lock
, flags
);
74 if (!wait_for_completion_timeout(&entry
->c
, timeout
))
77 wait_for_completion(&entry
->c
);
79 spin_lock_irqsave(&optee
->notif
.lock
, flags
);
81 list_del(&entry
->link
);
83 spin_unlock_irqrestore(&optee
->notif
.lock
, flags
);
90 int optee_notif_send(struct optee
*optee
, u_int key
)
93 struct notif_entry
*entry
;
95 if (key
> optee
->notif
.max_key
)
98 spin_lock_irqsave(&optee
->notif
.lock
, flags
);
100 list_for_each_entry(entry
, &optee
->notif
.db
, link
)
101 if (entry
->key
== key
) {
106 /* Only set the bit in case there where nobody waiting */
107 set_bit(key
, optee
->notif
.bitmap
);
109 spin_unlock_irqrestore(&optee
->notif
.lock
, flags
);
114 int optee_notif_init(struct optee
*optee
, u_int max_key
)
116 spin_lock_init(&optee
->notif
.lock
);
117 INIT_LIST_HEAD(&optee
->notif
.db
);
118 optee
->notif
.bitmap
= bitmap_zalloc(max_key
, GFP_KERNEL
);
119 if (!optee
->notif
.bitmap
)
122 optee
->notif
.max_key
= max_key
;
127 void optee_notif_uninit(struct optee
*optee
)
129 bitmap_free(optee
->notif
.bitmap
);