xref: /linux/include/media/media-request.h (revision 69050f8d6d075dc01af7a5f2f550a8067510366f)
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  */
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  * @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  */
65 struct 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  */
90 static inline int __must_check
91 media_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  */
115 static 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  */
135 static inline int __must_check
136 media_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  */
163 static 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  */
181 static 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  */
194 void 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  */
211 struct media_request *
212 media_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  */
222 int 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  */
235 static inline void
236 media_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  */
255 void media_request_manual_complete(struct media_request *req);
256 
257 #else
258 
259 static inline void media_request_get(struct media_request *req)
260 {
261 }
262 
263 static inline void media_request_put(struct media_request *req)
264 {
265 }
266 
267 static inline struct media_request *
268 media_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  */
283 struct 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  */
306 struct 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  */
325 static 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  */
338 void 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  */
355 struct media_request_object *
356 media_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  */
369 void 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  */
394 int 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  */
406 void 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  */
416 void media_request_object_complete(struct media_request_object *obj);
417 
418 #else
419 
420 static inline int __must_check
421 media_request_lock_for_access(struct media_request *req)
422 {
423 	return -EINVAL;
424 }
425 
426 static inline void media_request_unlock_for_access(struct media_request *req)
427 {
428 }
429 
430 static inline int __must_check
431 media_request_lock_for_update(struct media_request *req)
432 {
433 	return -EINVAL;
434 }
435 
436 static inline void media_request_unlock_for_update(struct media_request *req)
437 {
438 }
439 
440 static inline void media_request_object_get(struct media_request_object *obj)
441 {
442 }
443 
444 static inline void media_request_object_put(struct media_request_object *obj)
445 {
446 }
447 
448 static inline struct media_request_object *
449 media_request_object_find(struct media_request *req,
450 			  const struct media_request_object_ops *ops,
451 			  void *priv)
452 {
453 	return NULL;
454 }
455 
456 static inline void media_request_object_init(struct media_request_object *obj)
457 {
458 	obj->ops = NULL;
459 	obj->req = NULL;
460 }
461 
462 static 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 
470 static inline void media_request_object_unbind(struct media_request_object *obj)
471 {
472 }
473 
474 static inline void media_request_object_complete(struct media_request_object *obj)
475 {
476 }
477 
478 #endif
479 
480 #endif
481