hc
2023-12-04 f33f61bdb7ca6d5ebe7a78f9d8694b91360279ac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
 * Copyright (c) 2015, Linaro Limited
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include "tee_wait_queue.h"
 
struct tee_wait_queue {
   struct list_head link;
   struct completion comp;
   u32 key;
};
 
void tee_wait_queue_init(struct tee_wait_queue_private *priv)
{
   mutex_init(&priv->mu);
   INIT_LIST_HEAD(&priv->db);
}
EXPORT_SYMBOL(tee_wait_queue_init);
 
void tee_wait_queue_exit(struct tee_wait_queue_private *priv)
{
   mutex_destroy(&priv->mu);
}
EXPORT_SYMBOL(tee_wait_queue_exit);
 
static struct tee_wait_queue *tee_wait_queue_get(struct device *dev,
               struct tee_wait_queue_private *priv, u32 key)
{
   struct tee_wait_queue *w;
 
   mutex_lock(&priv->mu);
 
   list_for_each_entry(w, &priv->db, link)
       if (w->key == key)
           goto out;
 
   w = kmalloc(sizeof(struct tee_wait_queue), GFP_KERNEL);
   if (!w)
       goto out;
 
   init_completion(&w->comp);
   w->key = key;
   list_add_tail(&w->link, &priv->db);
out:
   mutex_unlock(&priv->mu);
   return w;
}
 
void tee_wait_queue_sleep(struct device *dev,
           struct tee_wait_queue_private *priv, u32 key)
{
   struct tee_wait_queue *w = tee_wait_queue_get(dev, priv, key);
 
   if (!w)
       return;
 
   wait_for_completion(&w->comp);
   mutex_lock(&priv->mu);
   list_del(&w->link);
   mutex_unlock(&priv->mu);
   kfree(w);
}
EXPORT_SYMBOL(tee_wait_queue_sleep);
 
void tee_wait_queue_wakeup(struct device *dev,
           struct tee_wait_queue_private *priv, u32 key)
{
   struct tee_wait_queue *w = tee_wait_queue_get(dev, priv, key);
 
   if (!w)
       return;
 
   complete(&w->comp);
}
EXPORT_SYMBOL(tee_wait_queue_wakeup);