mmc: core: Fix HS switch failure in mmc_select_hs400
[firefly-linux-kernel-4.4.55.git] / security / optee_linuxdriver / core / tee_mutex_wait.c
1 /*
2  * Copyright (c) 2014, Linaro Limited
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License Version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  */
13 #include <linux/slab.h>
14 #include "tee_mutex_wait.h"
15
16 struct tee_mutex_wait {
17         struct list_head link;
18         struct completion comp;
19         struct mutex mu;
20         u32 wait_after;
21         u32 key;
22 };
23
24 /*
25  * Compares two serial numbers using Serial Number Arithmetic
26  * (https://www.ietf.org/rfc/rfc1982.txt).
27  */
28 #define TICK_GT(t1, t2) \
29         (((t1) < (t2) && (t2) - (t1) > 0xFFFFFFFFu) || \
30         ((t1) > (t2) && (t1) - (t2) < 0xFFFFFFFFu))
31
32 static struct tee_mutex_wait *tee_mutex_wait_get(struct device *dev,
33                                 struct tee_mutex_wait_private *priv, u32 key)
34 {
35         struct tee_mutex_wait *w;
36
37         mutex_lock(&priv->mu);
38
39         list_for_each_entry(w, &priv->db, link)
40                 if (w->key == key)
41                         goto out;
42
43         w = kmalloc(sizeof(struct tee_mutex_wait), GFP_KERNEL);
44         if (!w) {
45                 dev_err(dev, "kmalloc <struct tee_mutex_wait> failed\n");
46                 goto out;
47         }
48
49         init_completion(&w->comp);
50         mutex_init(&w->mu);
51         w->wait_after = 0;
52         w->key = key;
53         list_add_tail(&w->link, &priv->db);
54 out:
55         mutex_unlock(&priv->mu);
56         return w;
57 }
58
59 static void tee_mutex_wait_delete_entry(struct tee_mutex_wait *w)
60 {
61         list_del(&w->link);
62         mutex_destroy(&w->mu);
63         kfree(w);
64 }
65
66 void tee_mutex_wait_delete(struct device *dev,
67                         struct tee_mutex_wait_private *priv,
68                         u32 key)
69 {
70         struct tee_mutex_wait *w;
71
72         mutex_lock(&priv->mu);
73
74         list_for_each_entry(w, &priv->db, link) {
75                 if (w->key == key) {
76                         tee_mutex_wait_delete_entry(w);
77                         break;
78                 }
79         }
80
81         mutex_unlock(&priv->mu);
82 }
83 EXPORT_SYMBOL(tee_mutex_wait_delete);
84
85 void tee_mutex_wait_wakeup(struct device *dev,
86                         struct tee_mutex_wait_private *priv,
87                         u32 key, u32 wait_after)
88 {
89         struct tee_mutex_wait *w = tee_mutex_wait_get(dev, priv, key);
90
91         if (!w)
92                 return;
93
94         mutex_lock(&w->mu);
95         w->wait_after = wait_after;
96         mutex_unlock(&w->mu);
97         complete(&w->comp);
98 }
99 EXPORT_SYMBOL(tee_mutex_wait_wakeup);
100
101 void tee_mutex_wait_sleep(struct device *dev,
102                         struct tee_mutex_wait_private *priv,
103                         u32 key, u32 wait_tick)
104 {
105         struct tee_mutex_wait *w = tee_mutex_wait_get(dev, priv, key);
106         u32 wait_after;
107
108         if (!w)
109                 return;
110
111         mutex_lock(&w->mu);
112         wait_after = w->wait_after;
113         mutex_unlock(&w->mu);
114
115         if (TICK_GT(wait_tick, wait_after))
116                 wait_for_completion_timeout(&w->comp, HZ);
117 }
118 EXPORT_SYMBOL(tee_mutex_wait_sleep);
119
120 int tee_mutex_wait_init(struct tee_mutex_wait_private *priv)
121 {
122         mutex_init(&priv->mu);
123         INIT_LIST_HEAD(&priv->db);
124         return 0;
125 }
126 EXPORT_SYMBOL(tee_mutex_wait_init);
127
128 void tee_mutex_wait_exit(struct tee_mutex_wait_private *priv)
129 {
130         /*
131          * It's the callers responibility to ensure that no one is using
132          * anything inside priv.
133          */
134
135         mutex_destroy(&priv->mu);
136         while (!list_empty(&priv->db)) {
137                 struct tee_mutex_wait *w =
138                                 list_first_entry(&priv->db,
139                                                  struct tee_mutex_wait,
140                                                  link);
141                 tee_mutex_wait_delete_entry(w);
142         }
143 }
144 EXPORT_SYMBOL(tee_mutex_wait_exit);