xref: /linux/include/media/media-request.h (revision 0ca0e844)
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  * @objects: List of @struct media_request_object request objects
57  * @num_incomplete_objects: The number of incomplete objects in the request
58  * @poll_wait: Wait queue for poll
59  * @lock: Serializes access to this struct
60  */
61 struct media_request {
62 	struct media_device *mdev;
63 	struct kref kref;
64 	char debug_str[TASK_COMM_LEN + 11];
65 	enum media_request_state state;
66 	unsigned int updating_count;
67 	struct list_head objects;
68 	unsigned int num_incomplete_objects;
69 	struct wait_queue_head poll_wait;
70 	spinlock_t lock;
71 };
72 
73 #ifdef CONFIG_MEDIA_CONTROLLER
74 
75 /**
76  * media_request_lock_for_update - Lock the request for updating its objects
77  *
78  * @req: The media request
79  *
80  * Use before updating a request, i.e. adding, modifying or removing a request
81  * object in it. A reference to the request must be held during the update. This
82  * usually takes place automatically through a file handle. Use
83  * @media_request_unlock_for_update when done.
84  */
85 static inline int __must_check
86 media_request_lock_for_update(struct media_request *req)
87 {
88 	unsigned long flags;
89 	int ret = 0;
90 
91 	spin_lock_irqsave(&req->lock, flags);
92 	if (req->state == MEDIA_REQUEST_STATE_IDLE ||
93 	    req->state == MEDIA_REQUEST_STATE_UPDATING) {
94 		req->state = MEDIA_REQUEST_STATE_UPDATING;
95 		req->updating_count++;
96 	} else {
97 		ret = -EBUSY;
98 	}
99 	spin_unlock_irqrestore(&req->lock, flags);
100 
101 	return ret;
102 }
103 
104 /**
105  * media_request_unlock_for_update - Unlock a request previously locked for
106  *				     update
107  *
108  * @req: The media request
109  *
110  * Unlock a request that has previously been locked using
111  * @media_request_lock_for_update.
112  */
113 static inline void media_request_unlock_for_update(struct media_request *req)
114 {
115 	unsigned long flags;
116 
117 	spin_lock_irqsave(&req->lock, flags);
118 	WARN_ON(req->updating_count <= 0);
119 	if (!--req->updating_count)
120 		req->state = MEDIA_REQUEST_STATE_IDLE;
121 	spin_unlock_irqrestore(&req->lock, flags);
122 }
123 
124 /**
125  * media_request_get - Get the media request
126  *
127  * @req: The media request
128  *
129  * Get the media request.
130  */
131 static inline void media_request_get(struct media_request *req)
132 {
133 	kref_get(&req->kref);
134 }
135 
136 /**
137  * media_request_put - Put the media request
138  *
139  * @req: The media request
140  *
141  * Put the media request. The media request will be released
142  * when the refcount reaches 0.
143  */
144 void media_request_put(struct media_request *req);
145 
146 /**
147  * media_request_get_by_fd - Get a media request by fd
148  *
149  * @mdev: Media device this request belongs to
150  * @request_fd: The file descriptor of the request
151  *
152  * Get the request represented by @request_fd that is owned
153  * by the media device.
154  *
155  * Return a -EPERM error pointer if requests are not supported
156  * by this driver. Return -ENOENT if the request was not found.
157  * Return the pointer to the request if found: the caller will
158  * have to call @media_request_put when it finished using the
159  * request.
160  */
161 struct media_request *
162 media_request_get_by_fd(struct media_device *mdev, int request_fd);
163 
164 /**
165  * media_request_alloc - Allocate the media request
166  *
167  * @mdev: Media device this request belongs to
168  * @alloc_fd: Store the request's file descriptor in this int
169  *
170  * Allocated the media request and put the fd in @alloc_fd.
171  */
172 int media_request_alloc(struct media_device *mdev,
173 			int *alloc_fd);
174 
175 #else
176 
177 static inline void media_request_get(struct media_request *req)
178 {
179 }
180 
181 static inline void media_request_put(struct media_request *req)
182 {
183 }
184 
185 static inline struct media_request *
186 media_request_get_by_fd(struct media_device *mdev, int request_fd)
187 {
188 	return ERR_PTR(-EPERM);
189 }
190 
191 #endif
192 
193 /**
194  * struct media_request_object_ops - Media request object operations
195  * @prepare: Validate and prepare the request object, optional.
196  * @unprepare: Unprepare the request object, optional.
197  * @queue: Queue the request object, optional.
198  * @unbind: Unbind the request object, optional.
199  * @release: Release the request object, required.
200  */
201 struct media_request_object_ops {
202 	int (*prepare)(struct media_request_object *object);
203 	void (*unprepare)(struct media_request_object *object);
204 	void (*queue)(struct media_request_object *object);
205 	void (*unbind)(struct media_request_object *object);
206 	void (*release)(struct media_request_object *object);
207 };
208 
209 /**
210  * struct media_request_object - An opaque object that belongs to a media
211  *				 request
212  *
213  * @ops: object's operations
214  * @priv: object's priv pointer
215  * @req: the request this object belongs to (can be NULL)
216  * @list: List entry of the object for @struct media_request
217  * @kref: Reference count of the object, acquire before releasing req->lock
218  * @completed: If true, then this object was completed.
219  *
220  * An object related to the request. This struct is always embedded in
221  * another struct that contains the actual data for this request object.
222  */
223 struct media_request_object {
224 	const struct media_request_object_ops *ops;
225 	void *priv;
226 	struct media_request *req;
227 	struct list_head list;
228 	struct kref kref;
229 	bool completed;
230 };
231 
232 #ifdef CONFIG_MEDIA_CONTROLLER
233 
234 /**
235  * media_request_object_get - Get a media request object
236  *
237  * @obj: The object
238  *
239  * Get a media request object.
240  */
241 static inline void media_request_object_get(struct media_request_object *obj)
242 {
243 	kref_get(&obj->kref);
244 }
245 
246 /**
247  * media_request_object_put - Put a media request object
248  *
249  * @obj: The object
250  *
251  * Put a media request object. Once all references are gone, the
252  * object's memory is released.
253  */
254 void media_request_object_put(struct media_request_object *obj);
255 
256 /**
257  * media_request_object_find - Find an object in a request
258  *
259  * @req: The media request
260  * @ops: Find an object with this ops value
261  * @priv: Find an object with this priv value
262  *
263  * Both @ops and @priv must be non-NULL.
264  *
265  * Returns the object pointer or NULL if not found. The caller must
266  * call media_request_object_put() once it finished using the object.
267  *
268  * Since this function needs to walk the list of objects it takes
269  * the @req->lock spin lock to make this safe.
270  */
271 struct media_request_object *
272 media_request_object_find(struct media_request *req,
273 			  const struct media_request_object_ops *ops,
274 			  void *priv);
275 
276 /**
277  * media_request_object_init - Initialise a media request object
278  *
279  * @obj: The object
280  *
281  * Initialise a media request object. The object will be released using the
282  * release callback of the ops once it has no references (this function
283  * initialises references to one).
284  */
285 void media_request_object_init(struct media_request_object *obj);
286 
287 /**
288  * media_request_object_bind - Bind a media request object to a request
289  *
290  * @req: The media request
291  * @ops: The object ops for this object
292  * @priv: A driver-specific priv pointer associated with this object
293  * @is_buffer: Set to true if the object a buffer object.
294  * @obj: The object
295  *
296  * Bind this object to the request and set the ops and priv values of
297  * the object so it can be found later with media_request_object_find().
298  *
299  * Every bound object must be unbound or completed by the kernel at some
300  * point in time, otherwise the request will never complete. When the
301  * request is released all completed objects will be unbound by the
302  * request core code.
303  *
304  * Buffer objects will be added to the end of the request's object
305  * list, non-buffer objects will be added to the front of the list.
306  * This ensures that all buffer objects are at the end of the list
307  * and that all non-buffer objects that they depend on are processed
308  * first.
309  */
310 int media_request_object_bind(struct media_request *req,
311 			      const struct media_request_object_ops *ops,
312 			      void *priv, bool is_buffer,
313 			      struct media_request_object *obj);
314 
315 /**
316  * media_request_object_unbind - Unbind a media request object
317  *
318  * @obj: The object
319  *
320  * Unbind the media request object from the request.
321  */
322 void media_request_object_unbind(struct media_request_object *obj);
323 
324 /**
325  * media_request_object_complete - Mark the media request object as complete
326  *
327  * @obj: The object
328  *
329  * Mark the media request object as complete. Only bound objects can
330  * be completed.
331  */
332 void media_request_object_complete(struct media_request_object *obj);
333 
334 #else
335 
336 static inline int __must_check
337 media_request_lock_for_update(struct media_request *req)
338 {
339 	return -EINVAL;
340 }
341 
342 static inline void media_request_unlock_for_update(struct media_request *req)
343 {
344 }
345 
346 static inline void media_request_object_get(struct media_request_object *obj)
347 {
348 }
349 
350 static inline void media_request_object_put(struct media_request_object *obj)
351 {
352 }
353 
354 static inline struct media_request_object *
355 media_request_object_find(struct media_request *req,
356 			  const struct media_request_object_ops *ops,
357 			  void *priv)
358 {
359 	return NULL;
360 }
361 
362 static inline void media_request_object_init(struct media_request_object *obj)
363 {
364 	obj->ops = NULL;
365 	obj->req = NULL;
366 }
367 
368 static inline int media_request_object_bind(struct media_request *req,
369 			       const struct media_request_object_ops *ops,
370 			       void *priv, bool is_buffer,
371 			       struct media_request_object *obj)
372 {
373 	return 0;
374 }
375 
376 static inline void media_request_object_unbind(struct media_request_object *obj)
377 {
378 }
379 
380 static inline void media_request_object_complete(struct media_request_object *obj)
381 {
382 }
383 
384 #endif
385 
386 #endif
387