Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/media/media-request.h
26281 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Media device request objects
4
*
5
* Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6
* Copyright (C) 2018 Intel Corporation
7
*
8
* Author: Hans Verkuil <[email protected]>
9
* Author: Sakari Ailus <[email protected]>
10
*/
11
12
#ifndef MEDIA_REQUEST_H
13
#define MEDIA_REQUEST_H
14
15
#include <linux/list.h>
16
#include <linux/slab.h>
17
#include <linux/spinlock.h>
18
#include <linux/refcount.h>
19
20
#include <media/media-device.h>
21
22
/**
23
* enum media_request_state - media request state
24
*
25
* @MEDIA_REQUEST_STATE_IDLE: Idle
26
* @MEDIA_REQUEST_STATE_VALIDATING: Validating the request, no state changes
27
* allowed
28
* @MEDIA_REQUEST_STATE_QUEUED: Queued
29
* @MEDIA_REQUEST_STATE_COMPLETE: Completed, the request is done
30
* @MEDIA_REQUEST_STATE_CLEANING: Cleaning, the request is being re-inited
31
* @MEDIA_REQUEST_STATE_UPDATING: The request is being updated, i.e.
32
* request objects are being added,
33
* modified or removed
34
* @NR_OF_MEDIA_REQUEST_STATE: The number of media request states, used
35
* internally for sanity check purposes
36
*/
37
enum media_request_state {
38
MEDIA_REQUEST_STATE_IDLE,
39
MEDIA_REQUEST_STATE_VALIDATING,
40
MEDIA_REQUEST_STATE_QUEUED,
41
MEDIA_REQUEST_STATE_COMPLETE,
42
MEDIA_REQUEST_STATE_CLEANING,
43
MEDIA_REQUEST_STATE_UPDATING,
44
NR_OF_MEDIA_REQUEST_STATE,
45
};
46
47
struct media_request_object;
48
49
/**
50
* struct media_request - Media device request
51
* @mdev: Media device this request belongs to
52
* @kref: Reference count
53
* @debug_str: Prefix for debug messages (process name:fd)
54
* @state: The state of the request
55
* @updating_count: count the number of request updates that are in progress
56
* @access_count: count the number of request accesses that are in progress
57
* @objects: List of @struct media_request_object request objects
58
* @num_incomplete_objects: The number of incomplete objects in the request
59
* @poll_wait: Wait queue for poll
60
* @lock: Serializes access to this struct
61
*/
62
struct media_request {
63
struct media_device *mdev;
64
struct kref kref;
65
char debug_str[TASK_COMM_LEN + 11];
66
enum media_request_state state;
67
unsigned int updating_count;
68
unsigned int access_count;
69
struct list_head objects;
70
unsigned int num_incomplete_objects;
71
wait_queue_head_t poll_wait;
72
spinlock_t lock;
73
};
74
75
#ifdef CONFIG_MEDIA_CONTROLLER
76
77
/**
78
* media_request_lock_for_access - Lock the request to access its objects
79
*
80
* @req: The media request
81
*
82
* Use before accessing a completed request. A reference to the request must
83
* be held during the access. This usually takes place automatically through
84
* a file handle. Use @media_request_unlock_for_access when done.
85
*/
86
static inline int __must_check
87
media_request_lock_for_access(struct media_request *req)
88
{
89
unsigned long flags;
90
int ret = -EBUSY;
91
92
spin_lock_irqsave(&req->lock, flags);
93
if (req->state == MEDIA_REQUEST_STATE_COMPLETE) {
94
req->access_count++;
95
ret = 0;
96
}
97
spin_unlock_irqrestore(&req->lock, flags);
98
99
return ret;
100
}
101
102
/**
103
* media_request_unlock_for_access - Unlock a request previously locked for
104
* access
105
*
106
* @req: The media request
107
*
108
* Unlock a request that has previously been locked using
109
* @media_request_lock_for_access.
110
*/
111
static inline void media_request_unlock_for_access(struct media_request *req)
112
{
113
unsigned long flags;
114
115
spin_lock_irqsave(&req->lock, flags);
116
if (!WARN_ON(!req->access_count))
117
req->access_count--;
118
spin_unlock_irqrestore(&req->lock, flags);
119
}
120
121
/**
122
* media_request_lock_for_update - Lock the request for updating its objects
123
*
124
* @req: The media request
125
*
126
* Use before updating a request, i.e. adding, modifying or removing a request
127
* object in it. A reference to the request must be held during the update. This
128
* usually takes place automatically through a file handle. Use
129
* @media_request_unlock_for_update when done.
130
*/
131
static inline int __must_check
132
media_request_lock_for_update(struct media_request *req)
133
{
134
unsigned long flags;
135
int ret = 0;
136
137
spin_lock_irqsave(&req->lock, flags);
138
if (req->state == MEDIA_REQUEST_STATE_IDLE ||
139
req->state == MEDIA_REQUEST_STATE_UPDATING) {
140
req->state = MEDIA_REQUEST_STATE_UPDATING;
141
req->updating_count++;
142
} else {
143
ret = -EBUSY;
144
}
145
spin_unlock_irqrestore(&req->lock, flags);
146
147
return ret;
148
}
149
150
/**
151
* media_request_unlock_for_update - Unlock a request previously locked for
152
* update
153
*
154
* @req: The media request
155
*
156
* Unlock a request that has previously been locked using
157
* @media_request_lock_for_update.
158
*/
159
static inline void media_request_unlock_for_update(struct media_request *req)
160
{
161
unsigned long flags;
162
163
spin_lock_irqsave(&req->lock, flags);
164
WARN_ON(req->updating_count <= 0);
165
if (!--req->updating_count)
166
req->state = MEDIA_REQUEST_STATE_IDLE;
167
spin_unlock_irqrestore(&req->lock, flags);
168
}
169
170
/**
171
* media_request_get - Get the media request
172
*
173
* @req: The media request
174
*
175
* Get the media request.
176
*/
177
static inline void media_request_get(struct media_request *req)
178
{
179
kref_get(&req->kref);
180
}
181
182
/**
183
* media_request_put - Put the media request
184
*
185
* @req: The media request
186
*
187
* Put the media request. The media request will be released
188
* when the refcount reaches 0.
189
*/
190
void media_request_put(struct media_request *req);
191
192
/**
193
* media_request_get_by_fd - Get a media request by fd
194
*
195
* @mdev: Media device this request belongs to
196
* @request_fd: The file descriptor of the request
197
*
198
* Get the request represented by @request_fd that is owned
199
* by the media device.
200
*
201
* Return a -EBADR error pointer if requests are not supported
202
* by this driver. Return -EINVAL if the request was not found.
203
* Return the pointer to the request if found: the caller will
204
* have to call @media_request_put when it finished using the
205
* request.
206
*/
207
struct media_request *
208
media_request_get_by_fd(struct media_device *mdev, int request_fd);
209
210
/**
211
* media_request_alloc - Allocate the media request
212
*
213
* @mdev: Media device this request belongs to
214
* @alloc_fd: Store the request's file descriptor in this int
215
*
216
* Allocated the media request and put the fd in @alloc_fd.
217
*/
218
int media_request_alloc(struct media_device *mdev,
219
int *alloc_fd);
220
221
#else
222
223
static inline void media_request_get(struct media_request *req)
224
{
225
}
226
227
static inline void media_request_put(struct media_request *req)
228
{
229
}
230
231
static inline struct media_request *
232
media_request_get_by_fd(struct media_device *mdev, int request_fd)
233
{
234
return ERR_PTR(-EBADR);
235
}
236
237
#endif
238
239
/**
240
* struct media_request_object_ops - Media request object operations
241
* @prepare: Validate and prepare the request object, optional.
242
* @unprepare: Unprepare the request object, optional.
243
* @queue: Queue the request object, optional.
244
* @unbind: Unbind the request object, optional.
245
* @release: Release the request object, required.
246
*/
247
struct media_request_object_ops {
248
int (*prepare)(struct media_request_object *object);
249
void (*unprepare)(struct media_request_object *object);
250
void (*queue)(struct media_request_object *object);
251
void (*unbind)(struct media_request_object *object);
252
void (*release)(struct media_request_object *object);
253
};
254
255
/**
256
* struct media_request_object - An opaque object that belongs to a media
257
* request
258
*
259
* @ops: object's operations
260
* @priv: object's priv pointer
261
* @req: the request this object belongs to (can be NULL)
262
* @list: List entry of the object for @struct media_request
263
* @kref: Reference count of the object, acquire before releasing req->lock
264
* @completed: If true, then this object was completed.
265
*
266
* An object related to the request. This struct is always embedded in
267
* another struct that contains the actual data for this request object.
268
*/
269
struct media_request_object {
270
const struct media_request_object_ops *ops;
271
void *priv;
272
struct media_request *req;
273
struct list_head list;
274
struct kref kref;
275
bool completed;
276
};
277
278
#ifdef CONFIG_MEDIA_CONTROLLER
279
280
/**
281
* media_request_object_get - Get a media request object
282
*
283
* @obj: The object
284
*
285
* Get a media request object.
286
*/
287
static inline void media_request_object_get(struct media_request_object *obj)
288
{
289
kref_get(&obj->kref);
290
}
291
292
/**
293
* media_request_object_put - Put a media request object
294
*
295
* @obj: The object
296
*
297
* Put a media request object. Once all references are gone, the
298
* object's memory is released.
299
*/
300
void media_request_object_put(struct media_request_object *obj);
301
302
/**
303
* media_request_object_find - Find an object in a request
304
*
305
* @req: The media request
306
* @ops: Find an object with this ops value
307
* @priv: Find an object with this priv value
308
*
309
* Both @ops and @priv must be non-NULL.
310
*
311
* Returns the object pointer or NULL if not found. The caller must
312
* call media_request_object_put() once it finished using the object.
313
*
314
* Since this function needs to walk the list of objects it takes
315
* the @req->lock spin lock to make this safe.
316
*/
317
struct media_request_object *
318
media_request_object_find(struct media_request *req,
319
const struct media_request_object_ops *ops,
320
void *priv);
321
322
/**
323
* media_request_object_init - Initialise a media request object
324
*
325
* @obj: The object
326
*
327
* Initialise a media request object. The object will be released using the
328
* release callback of the ops once it has no references (this function
329
* initialises references to one).
330
*/
331
void media_request_object_init(struct media_request_object *obj);
332
333
/**
334
* media_request_object_bind - Bind a media request object to a request
335
*
336
* @req: The media request
337
* @ops: The object ops for this object
338
* @priv: A driver-specific priv pointer associated with this object
339
* @is_buffer: Set to true if the object a buffer object.
340
* @obj: The object
341
*
342
* Bind this object to the request and set the ops and priv values of
343
* the object so it can be found later with media_request_object_find().
344
*
345
* Every bound object must be unbound or completed by the kernel at some
346
* point in time, otherwise the request will never complete. When the
347
* request is released all completed objects will be unbound by the
348
* request core code.
349
*
350
* Buffer objects will be added to the end of the request's object
351
* list, non-buffer objects will be added to the front of the list.
352
* This ensures that all buffer objects are at the end of the list
353
* and that all non-buffer objects that they depend on are processed
354
* first.
355
*/
356
int media_request_object_bind(struct media_request *req,
357
const struct media_request_object_ops *ops,
358
void *priv, bool is_buffer,
359
struct media_request_object *obj);
360
361
/**
362
* media_request_object_unbind - Unbind a media request object
363
*
364
* @obj: The object
365
*
366
* Unbind the media request object from the request.
367
*/
368
void media_request_object_unbind(struct media_request_object *obj);
369
370
/**
371
* media_request_object_complete - Mark the media request object as complete
372
*
373
* @obj: The object
374
*
375
* Mark the media request object as complete. Only bound objects can
376
* be completed.
377
*/
378
void media_request_object_complete(struct media_request_object *obj);
379
380
#else
381
382
static inline int __must_check
383
media_request_lock_for_access(struct media_request *req)
384
{
385
return -EINVAL;
386
}
387
388
static inline void media_request_unlock_for_access(struct media_request *req)
389
{
390
}
391
392
static inline int __must_check
393
media_request_lock_for_update(struct media_request *req)
394
{
395
return -EINVAL;
396
}
397
398
static inline void media_request_unlock_for_update(struct media_request *req)
399
{
400
}
401
402
static inline void media_request_object_get(struct media_request_object *obj)
403
{
404
}
405
406
static inline void media_request_object_put(struct media_request_object *obj)
407
{
408
}
409
410
static inline struct media_request_object *
411
media_request_object_find(struct media_request *req,
412
const struct media_request_object_ops *ops,
413
void *priv)
414
{
415
return NULL;
416
}
417
418
static inline void media_request_object_init(struct media_request_object *obj)
419
{
420
obj->ops = NULL;
421
obj->req = NULL;
422
}
423
424
static inline int media_request_object_bind(struct media_request *req,
425
const struct media_request_object_ops *ops,
426
void *priv, bool is_buffer,
427
struct media_request_object *obj)
428
{
429
return 0;
430
}
431
432
static inline void media_request_object_unbind(struct media_request_object *obj)
433
{
434
}
435
436
static inline void media_request_object_complete(struct media_request_object *obj)
437
{
438
}
439
440
#endif
441
442
#endif
443
444