blob: 1c3e5d804d07695d00eec2489883da0263f7d8e8 [file] [log] [blame]
Hans Verkuil10905d72018-05-21 04:54:27 -04001// 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 */
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 * @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 */
61struct 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 */
85static inline int __must_check
86media_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 */
113static 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 */
131static 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 */
144void media_request_put(struct media_request *req);
145
146/**
Hans Verkuilbe9d6d42018-05-21 04:54:28 -0400147 * 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 */
161struct media_request *
162media_request_get_by_fd(struct media_device *mdev, int request_fd);
163
164/**
Hans Verkuil10905d72018-05-21 04:54:27 -0400165 * 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 */
172int media_request_alloc(struct media_device *mdev,
173 int *alloc_fd);
174
175#else
176
177static inline void media_request_get(struct media_request *req)
178{
179}
180
181static inline void media_request_put(struct media_request *req)
182{
183}
184
Hans Verkuilbe9d6d42018-05-21 04:54:28 -0400185static inline struct media_request *
186media_request_get_by_fd(struct media_device *mdev, int request_fd)
187{
188 return ERR_PTR(-EPERM);
189}
190
Hans Verkuil10905d72018-05-21 04:54:27 -0400191#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 */
201struct 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 */
223struct 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 */
241static 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 */
254void media_request_object_put(struct media_request_object *obj);
255
256/**
257 * media_request_object_init - Initialise a media request object
258 *
259 * @obj: The object
260 *
261 * Initialise a media request object. The object will be released using the
262 * release callback of the ops once it has no references (this function
263 * initialises references to one).
264 */
265void media_request_object_init(struct media_request_object *obj);
266
267/**
268 * media_request_object_bind - Bind a media request object to a request
269 *
270 * @req: The media request
271 * @ops: The object ops for this object
272 * @priv: A driver-specific priv pointer associated with this object
273 * @is_buffer: Set to true if the object a buffer object.
274 * @obj: The object
275 *
276 * Bind this object to the request and set the ops and priv values of
277 * the object so it can be found later with media_request_object_find().
278 *
279 * Every bound object must be unbound or completed by the kernel at some
280 * point in time, otherwise the request will never complete. When the
281 * request is released all completed objects will be unbound by the
282 * request core code.
283 *
284 * Buffer objects will be added to the end of the request's object
285 * list, non-buffer objects will be added to the front of the list.
286 * This ensures that all buffer objects are at the end of the list
287 * and that all non-buffer objects that they depend on are processed
288 * first.
289 */
290int media_request_object_bind(struct media_request *req,
291 const struct media_request_object_ops *ops,
292 void *priv, bool is_buffer,
293 struct media_request_object *obj);
294
295/**
296 * media_request_object_unbind - Unbind a media request object
297 *
298 * @obj: The object
299 *
300 * Unbind the media request object from the request.
301 */
302void media_request_object_unbind(struct media_request_object *obj);
303
304/**
305 * media_request_object_complete - Mark the media request object as complete
306 *
307 * @obj: The object
308 *
309 * Mark the media request object as complete. Only bound objects can
310 * be completed.
311 */
312void media_request_object_complete(struct media_request_object *obj);
313
314#else
315
316static inline int __must_check
317media_request_lock_for_update(struct media_request *req)
318{
319 return -EINVAL;
320}
321
322static inline void media_request_unlock_for_update(struct media_request *req)
323{
324}
325
326static inline void media_request_object_get(struct media_request_object *obj)
327{
328}
329
330static inline void media_request_object_put(struct media_request_object *obj)
331{
332}
333
334static inline void media_request_object_init(struct media_request_object *obj)
335{
336 obj->ops = NULL;
337 obj->req = NULL;
338}
339
340static inline int media_request_object_bind(struct media_request *req,
341 const struct media_request_object_ops *ops,
342 void *priv, bool is_buffer,
343 struct media_request_object *obj)
344{
345 return 0;
346}
347
348static inline void media_request_object_unbind(struct media_request_object *obj)
349{
350}
351
352static inline void media_request_object_complete(struct media_request_object *obj)
353{
354}
355
356#endif
357
358#endif