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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
/*
* Copyright (C) 2013 Samsung Electronics Co.Ltd
* Authors:
* Inki Dae <inki.dae@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/dma-buf.h>
enum dmabuf_sync_status {
DMABUF_SYNC_GOT = 1,
DMABUF_SYNC_LOCKED,
};
struct dmabuf_sync_reservation {
struct ww_mutex sync_lock;
struct mutex lock;
atomic_t shared_cnt;
unsigned int accessed_type;
unsigned int shared;
unsigned int locked;
};
/*
* A structure for dmabuf_sync_object.
*
* @head: A list head to be added to syncs list.
* @robj: A reservation_object object.
* @dma_buf: A dma_buf object.
* @access_type: Indicate how a current task tries to access
* a given buffer.
*/
struct dmabuf_sync_object {
struct list_head head;
struct dmabuf_sync_reservation *robj;
struct dma_buf *dmabuf;
unsigned int access_type;
};
/*
* A structure for dmabuf_sync.
*
* @syncs: A list head to sync object and this is global to system.
* @list: A list entry used as committed list node
* @lock: A mutex lock to current sync object.
* @ctx: A current context for ww mutex.
* @work: A work struct to release resources at timeout.
* @priv: A private data.
* @name: A string to dmabuf sync owner.
* @timer: A timer list to avoid lockup and release resources.
* @status: Indicate current status (DMABUF_SYNC_GOT or DMABUF_SYNC_LOCKED).
*/
struct dmabuf_sync {
struct list_head syncs;
struct list_head list;
struct mutex lock;
struct ww_acquire_ctx ctx;
struct work_struct work;
void *priv;
char name[64];
struct timer_list timer;
unsigned int status;
};
#ifdef CONFIG_DMABUF_SYNC
extern struct ww_class dmabuf_sync_ww_class;
static inline void dmabuf_sync_reservation_init(struct dma_buf *dmabuf)
{
struct dmabuf_sync_reservation *obj;
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
return;
dmabuf->sync = obj;
ww_mutex_init(&obj->sync_lock, &dmabuf_sync_ww_class);
mutex_init(&obj->lock);
atomic_set(&obj->shared_cnt, 1);
}
static inline void dmabuf_sync_reservation_fini(struct dma_buf *dmabuf)
{
struct dmabuf_sync_reservation *obj;
if (!dmabuf->sync)
return;
obj = dmabuf->sync;
ww_mutex_destroy(&obj->sync_lock);
kfree(obj);
}
extern bool is_dmabuf_sync_supported(void);
extern struct dmabuf_sync *dmabuf_sync_init(void *priv, const char *name);
extern void dmabuf_sync_fini(struct dmabuf_sync *sync);
extern int dmabuf_sync_lock(struct dmabuf_sync *sync);
extern int dmabuf_sync_unlock(struct dmabuf_sync *sync);
int dmabuf_sync_single_lock(struct dma_buf *dmabuf, unsigned int type,
bool wait);
void dmabuf_sync_single_unlock(struct dma_buf *dmabuf);
extern int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf,
unsigned int type);
extern void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf);
extern void dmabuf_sync_put_all(struct dmabuf_sync *sync);
#else
static inline void dmabuf_sync_reservation_init(struct dma_buf *dmabuf) { }
static inline void dmabuf_sync_reservation_fini(struct dma_buf *dmabuf) { }
static inline bool is_dmabuf_sync_supported(void) { return false; }
static inline struct dmabuf_sync *dmabuf_sync_init(void *priv,
const char *names)
{
return ERR_PTR(0);
}
static inline void dmabuf_sync_fini(struct dmabuf_sync *sync) { }
static inline int dmabuf_sync_lock(struct dmabuf_sync *sync)
{
return 0;
}
static inline int dmabuf_sync_unlock(struct dmabuf_sync *sync)
{
return 0;
}
static inline int dmabuf_sync_single_lock(struct dma_buf *dmabuf,
unsigned int type,
bool wait)
{
return 0;
}
static inline void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
{
return;
}
static inline int dmabuf_sync_get(struct dmabuf_sync *sync,
void *sync_buf,
unsigned int type)
{
return 0;
}
static inline void dmabuf_sync_put(struct dmabuf_sync *sync,
struct dma_buf *dmabuf) { }
static inline void dmabuf_sync_put_all(struct dmabuf_sync *sync) { }
#endif
|