Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 <hverkuil@kernel.org>
9 * Author: Sakari Ailus <sakari.ailus@linux.intel.com>
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 */
37enum 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
47struct 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 * @manual_completion: if true, then the request won't be marked as completed
60 * when @num_incomplete_objects reaches 0. Call media_request_manual_complete()
61 * to complete the request after @num_incomplete_objects == 0.
62 * @poll_wait: Wait queue for poll
63 * @lock: Serializes access to this struct
64 */
65struct media_request {
66 struct media_device *mdev;
67 struct kref kref;
68 char debug_str[TASK_COMM_LEN + 11];
69 enum media_request_state state;
70 unsigned int updating_count;
71 unsigned int access_count;
72 struct list_head objects;
73 unsigned int num_incomplete_objects;
74 bool manual_completion;
75 wait_queue_head_t poll_wait;
76 spinlock_t lock;
77};
78
79#ifdef CONFIG_MEDIA_CONTROLLER
80
81/**
82 * media_request_lock_for_access - Lock the request to access its objects
83 *
84 * @req: The media request
85 *
86 * Use before accessing a completed request. A reference to the request must
87 * be held during the access. This usually takes place automatically through
88 * a file handle. Use @media_request_unlock_for_access when done.
89 */
90static inline int __must_check
91media_request_lock_for_access(struct media_request *req)
92{
93 unsigned long flags;
94 int ret = -EBUSY;
95
96 spin_lock_irqsave(&req->lock, flags);
97 if (req->state == MEDIA_REQUEST_STATE_COMPLETE) {
98 req->access_count++;
99 ret = 0;
100 }
101 spin_unlock_irqrestore(&req->lock, flags);
102
103 return ret;
104}
105
106/**
107 * media_request_unlock_for_access - Unlock a request previously locked for
108 * access
109 *
110 * @req: The media request
111 *
112 * Unlock a request that has previously been locked using
113 * @media_request_lock_for_access.
114 */
115static inline void media_request_unlock_for_access(struct media_request *req)
116{
117 unsigned long flags;
118
119 spin_lock_irqsave(&req->lock, flags);
120 if (!WARN_ON(!req->access_count))
121 req->access_count--;
122 spin_unlock_irqrestore(&req->lock, flags);
123}
124
125/**
126 * media_request_lock_for_update - Lock the request for updating its objects
127 *
128 * @req: The media request
129 *
130 * Use before updating a request, i.e. adding, modifying or removing a request
131 * object in it. A reference to the request must be held during the update. This
132 * usually takes place automatically through a file handle. Use
133 * @media_request_unlock_for_update when done.
134 */
135static inline int __must_check
136media_request_lock_for_update(struct media_request *req)
137{
138 unsigned long flags;
139 int ret = 0;
140
141 spin_lock_irqsave(&req->lock, flags);
142 if (req->state == MEDIA_REQUEST_STATE_IDLE ||
143 req->state == MEDIA_REQUEST_STATE_UPDATING) {
144 req->state = MEDIA_REQUEST_STATE_UPDATING;
145 req->updating_count++;
146 } else {
147 ret = -EBUSY;
148 }
149 spin_unlock_irqrestore(&req->lock, flags);
150
151 return ret;
152}
153
154/**
155 * media_request_unlock_for_update - Unlock a request previously locked for
156 * update
157 *
158 * @req: The media request
159 *
160 * Unlock a request that has previously been locked using
161 * @media_request_lock_for_update.
162 */
163static inline void media_request_unlock_for_update(struct media_request *req)
164{
165 unsigned long flags;
166
167 spin_lock_irqsave(&req->lock, flags);
168 WARN_ON(req->updating_count <= 0);
169 if (!--req->updating_count)
170 req->state = MEDIA_REQUEST_STATE_IDLE;
171 spin_unlock_irqrestore(&req->lock, flags);
172}
173
174/**
175 * media_request_get - Get the media request
176 *
177 * @req: The media request
178 *
179 * Get the media request.
180 */
181static inline void media_request_get(struct media_request *req)
182{
183 kref_get(&req->kref);
184}
185
186/**
187 * media_request_put - Put the media request
188 *
189 * @req: The media request
190 *
191 * Put the media request. The media request will be released
192 * when the refcount reaches 0.
193 */
194void media_request_put(struct media_request *req);
195
196/**
197 * media_request_get_by_fd - Get a media request by fd
198 *
199 * @mdev: Media device this request belongs to
200 * @request_fd: The file descriptor of the request
201 *
202 * Get the request represented by @request_fd that is owned
203 * by the media device.
204 *
205 * Return a -EBADR error pointer if requests are not supported
206 * by this driver. Return -EINVAL if the request was not found.
207 * Return the pointer to the request if found: the caller will
208 * have to call @media_request_put when it finished using the
209 * request.
210 */
211struct media_request *
212media_request_get_by_fd(struct media_device *mdev, int request_fd);
213
214/**
215 * media_request_alloc - Allocate the media request
216 *
217 * @mdev: Media device this request belongs to
218 * @alloc_fd: Store the request's file descriptor in this int
219 *
220 * Allocated the media request and put the fd in @alloc_fd.
221 */
222int media_request_alloc(struct media_device *mdev,
223 int *alloc_fd);
224
225/**
226 * media_request_mark_manual_completion - Enable manual completion
227 *
228 * @req: The request
229 *
230 * Mark that the request has to be manually completed by calling
231 * media_request_manual_complete().
232 *
233 * This function shall be called in the req_queue callback.
234 */
235static inline void
236media_request_mark_manual_completion(struct media_request *req)
237{
238 req->manual_completion = true;
239}
240
241/**
242 * media_request_manual_complete - Mark the request as completed
243 *
244 * @req: The request
245 *
246 * This function completes a request that was marked for manual completion by an
247 * earlier call to media_request_mark_manual_completion(). The request's
248 * @manual_completion field is reset to false.
249 *
250 * All objects contained in the request must have been completed previously. It
251 * is an error to call this function otherwise. If such an error occurred, the
252 * function will WARN and the object completion will be delayed until
253 * @num_incomplete_objects is 0.
254 */
255void media_request_manual_complete(struct media_request *req);
256
257#else
258
259static inline void media_request_get(struct media_request *req)
260{
261}
262
263static inline void media_request_put(struct media_request *req)
264{
265}
266
267static inline struct media_request *
268media_request_get_by_fd(struct media_device *mdev, int request_fd)
269{
270 return ERR_PTR(-EBADR);
271}
272
273#endif
274
275/**
276 * struct media_request_object_ops - Media request object operations
277 * @prepare: Validate and prepare the request object, optional.
278 * @unprepare: Unprepare the request object, optional.
279 * @queue: Queue the request object, optional.
280 * @unbind: Unbind the request object, optional.
281 * @release: Release the request object, required.
282 */
283struct media_request_object_ops {
284 int (*prepare)(struct media_request_object *object);
285 void (*unprepare)(struct media_request_object *object);
286 void (*queue)(struct media_request_object *object);
287 void (*unbind)(struct media_request_object *object);
288 void (*release)(struct media_request_object *object);
289};
290
291/**
292 * struct media_request_object - An opaque object that belongs to a media
293 * request
294 *
295 * @mdev: Media device this object belongs to
296 * @ops: object's operations
297 * @priv: object's priv pointer
298 * @req: the request this object belongs to (can be NULL)
299 * @list: List entry of the object for @struct media_request
300 * @kref: Reference count of the object, acquire before releasing req->lock
301 * @completed: If true, then this object was completed.
302 *
303 * An object related to the request. This struct is always embedded in
304 * another struct that contains the actual data for this request object.
305 */
306struct media_request_object {
307 struct media_device *mdev;
308 const struct media_request_object_ops *ops;
309 void *priv;
310 struct media_request *req;
311 struct list_head list;
312 struct kref kref;
313 bool completed;
314};
315
316#ifdef CONFIG_MEDIA_CONTROLLER
317
318/**
319 * media_request_object_get - Get a media request object
320 *
321 * @obj: The object
322 *
323 * Get a media request object.
324 */
325static inline void media_request_object_get(struct media_request_object *obj)
326{
327 kref_get(&obj->kref);
328}
329
330/**
331 * media_request_object_put - Put a media request object
332 *
333 * @obj: The object
334 *
335 * Put a media request object. Once all references are gone, the
336 * object's memory is released.
337 */
338void media_request_object_put(struct media_request_object *obj);
339
340/**
341 * media_request_object_find - Find an object in a request
342 *
343 * @req: The media request
344 * @ops: Find an object with this ops value
345 * @priv: Find an object with this priv value
346 *
347 * Both @ops and @priv must be non-NULL.
348 *
349 * Returns the object pointer or NULL if not found. The caller must
350 * call media_request_object_put() once it finished using the object.
351 *
352 * Since this function needs to walk the list of objects it takes
353 * the @req->lock spin lock to make this safe.
354 */
355struct media_request_object *
356media_request_object_find(struct media_request *req,
357 const struct media_request_object_ops *ops,
358 void *priv);
359
360/**
361 * media_request_object_init - Initialise a media request object
362 *
363 * @obj: The object
364 *
365 * Initialise a media request object. The object will be released using the
366 * release callback of the ops once it has no references (this function
367 * initialises references to one).
368 */
369void media_request_object_init(struct media_request_object *obj);
370
371/**
372 * media_request_object_bind - Bind a media request object to a request
373 *
374 * @req: The media request
375 * @ops: The object ops for this object
376 * @priv: A driver-specific priv pointer associated with this object
377 * @is_buffer: Set to true if the object is a buffer object.
378 * @obj: The object
379 *
380 * Bind this object to the request and set the ops and priv values of
381 * the object so it can be found later with media_request_object_find().
382 *
383 * Every bound object must be unbound or completed by the kernel at some
384 * point in time, otherwise the request will never complete. When the
385 * request is released all completed objects will be unbound by the
386 * request core code.
387 *
388 * Buffer objects will be added to the end of the request's object
389 * list, non-buffer objects will be added to the front of the list.
390 * This ensures that all buffer objects are at the end of the list
391 * and that all non-buffer objects that they depend on are processed
392 * first.
393 */
394int media_request_object_bind(struct media_request *req,
395 const struct media_request_object_ops *ops,
396 void *priv, bool is_buffer,
397 struct media_request_object *obj);
398
399/**
400 * media_request_object_unbind - Unbind a media request object
401 *
402 * @obj: The object
403 *
404 * Unbind the media request object from the request.
405 */
406void media_request_object_unbind(struct media_request_object *obj);
407
408/**
409 * media_request_object_complete - Mark the media request object as complete
410 *
411 * @obj: The object
412 *
413 * Mark the media request object as complete. Only bound objects can
414 * be completed.
415 */
416void media_request_object_complete(struct media_request_object *obj);
417
418#else
419
420static inline int __must_check
421media_request_lock_for_access(struct media_request *req)
422{
423 return -EINVAL;
424}
425
426static inline void media_request_unlock_for_access(struct media_request *req)
427{
428}
429
430static inline int __must_check
431media_request_lock_for_update(struct media_request *req)
432{
433 return -EINVAL;
434}
435
436static inline void media_request_unlock_for_update(struct media_request *req)
437{
438}
439
440static inline void media_request_object_get(struct media_request_object *obj)
441{
442}
443
444static inline void media_request_object_put(struct media_request_object *obj)
445{
446}
447
448static inline struct media_request_object *
449media_request_object_find(struct media_request *req,
450 const struct media_request_object_ops *ops,
451 void *priv)
452{
453 return NULL;
454}
455
456static inline void media_request_object_init(struct media_request_object *obj)
457{
458 obj->ops = NULL;
459 obj->req = NULL;
460}
461
462static inline int media_request_object_bind(struct media_request *req,
463 const struct media_request_object_ops *ops,
464 void *priv, bool is_buffer,
465 struct media_request_object *obj)
466{
467 return 0;
468}
469
470static inline void media_request_object_unbind(struct media_request_object *obj)
471{
472}
473
474static inline void media_request_object_complete(struct media_request_object *obj)
475{
476}
477
478#endif
479
480#endif