|
17 | 17 | #define CREATE_TRACE_POINTS |
18 | 18 | #include "optee_trace.h" |
19 | 19 |
|
20 | | -struct optee_call_waiter { |
21 | | - struct list_head list_node; |
22 | | - struct completion c; |
23 | | -}; |
24 | | - |
25 | | -static void optee_cq_wait_init(struct optee_call_queue *cq, |
26 | | - struct optee_call_waiter *w) |
27 | | -{ |
28 | | - /* |
29 | | - * We're preparing to make a call to secure world. In case we can't |
30 | | - * allocate a thread in secure world we'll end up waiting in |
31 | | - * optee_cq_wait_for_completion(). |
32 | | - * |
33 | | - * Normally if there's no contention in secure world the call will |
34 | | - * complete and we can cleanup directly with optee_cq_wait_final(). |
35 | | - */ |
36 | | - mutex_lock(&cq->mutex); |
37 | | - |
38 | | - /* |
39 | | - * We add ourselves to the queue, but we don't wait. This |
40 | | - * guarantees that we don't lose a completion if secure world |
41 | | - * returns busy and another thread just exited and try to complete |
42 | | - * someone. |
43 | | - */ |
44 | | - init_completion(&w->c); |
45 | | - list_add_tail(&w->list_node, &cq->waiters); |
46 | | - |
47 | | - mutex_unlock(&cq->mutex); |
48 | | -} |
49 | | - |
50 | | -static void optee_cq_wait_for_completion(struct optee_call_queue *cq, |
51 | | - struct optee_call_waiter *w) |
52 | | -{ |
53 | | - wait_for_completion(&w->c); |
54 | | - |
55 | | - mutex_lock(&cq->mutex); |
56 | | - |
57 | | - /* Move to end of list to get out of the way for other waiters */ |
58 | | - list_del(&w->list_node); |
59 | | - reinit_completion(&w->c); |
60 | | - list_add_tail(&w->list_node, &cq->waiters); |
61 | | - |
62 | | - mutex_unlock(&cq->mutex); |
63 | | -} |
64 | | - |
65 | | -static void optee_cq_complete_one(struct optee_call_queue *cq) |
66 | | -{ |
67 | | - struct optee_call_waiter *w; |
68 | | - |
69 | | - list_for_each_entry(w, &cq->waiters, list_node) { |
70 | | - if (!completion_done(&w->c)) { |
71 | | - complete(&w->c); |
72 | | - break; |
73 | | - } |
74 | | - } |
75 | | -} |
76 | | - |
77 | | -static void optee_cq_wait_final(struct optee_call_queue *cq, |
78 | | - struct optee_call_waiter *w) |
79 | | -{ |
80 | | - /* |
81 | | - * We're done with the call to secure world. The thread in secure |
82 | | - * world that was used for this call is now available for some |
83 | | - * other task to use. |
84 | | - */ |
85 | | - mutex_lock(&cq->mutex); |
86 | | - |
87 | | - /* Get out of the list */ |
88 | | - list_del(&w->list_node); |
89 | | - |
90 | | - /* Wake up one eventual waiting task */ |
91 | | - optee_cq_complete_one(cq); |
92 | | - |
93 | | - /* |
94 | | - * If we're completed we've got a completion from another task that |
95 | | - * was just done with its call to secure world. Since yet another |
96 | | - * thread now is available in secure world wake up another eventual |
97 | | - * waiting task. |
98 | | - */ |
99 | | - if (completion_done(&w->c)) |
100 | | - optee_cq_complete_one(cq); |
101 | | - |
102 | | - mutex_unlock(&cq->mutex); |
103 | | -} |
104 | | - |
105 | 20 | /* Requires the filpstate mutex to be held */ |
106 | 21 | static struct optee_session *find_session(struct optee_context_data *ctxdata, |
107 | 22 | u32 session_id) |
|
0 commit comments