~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/include/media/media-request.h

Version: ~ [ linux-5.10-rc6 ] ~ [ linux-5.9.12 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.81 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.161 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.210 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.247 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.247 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 <hans.verkuil@cisco.com>
  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  */
 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp