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
media_request_lock_for_access(struct media_request * req)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   */
media_request_unlock_for_access(struct media_request * req)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
media_request_lock_for_update(struct media_request * req)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   */
media_request_unlock_for_update(struct media_request * req)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   */
media_request_get(struct media_request * req)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  
media_request_get(struct media_request * req)223  static inline void media_request_get(struct media_request *req)
224  {
225  }
226  
media_request_put(struct media_request * req)227  static inline void media_request_put(struct media_request *req)
228  {
229  }
230  
231  static inline struct media_request *
media_request_get_by_fd(struct media_device * mdev,int request_fd)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   */
media_request_object_get(struct media_request_object * obj)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
media_request_lock_for_access(struct media_request * req)383  media_request_lock_for_access(struct media_request *req)
384  {
385  	return -EINVAL;
386  }
387  
media_request_unlock_for_access(struct media_request * req)388  static inline void media_request_unlock_for_access(struct media_request *req)
389  {
390  }
391  
392  static inline int __must_check
media_request_lock_for_update(struct media_request * req)393  media_request_lock_for_update(struct media_request *req)
394  {
395  	return -EINVAL;
396  }
397  
media_request_unlock_for_update(struct media_request * req)398  static inline void media_request_unlock_for_update(struct media_request *req)
399  {
400  }
401  
media_request_object_get(struct media_request_object * obj)402  static inline void media_request_object_get(struct media_request_object *obj)
403  {
404  }
405  
media_request_object_put(struct media_request_object * obj)406  static inline void media_request_object_put(struct media_request_object *obj)
407  {
408  }
409  
410  static inline struct media_request_object *
media_request_object_find(struct media_request * req,const struct media_request_object_ops * ops,void * priv)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  
media_request_object_init(struct media_request_object * obj)418  static inline void media_request_object_init(struct media_request_object *obj)
419  {
420  	obj->ops = NULL;
421  	obj->req = NULL;
422  }
423  
media_request_object_bind(struct media_request * req,const struct media_request_object_ops * ops,void * priv,bool is_buffer,struct media_request_object * obj)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  
media_request_object_unbind(struct media_request_object * obj)432  static inline void media_request_object_unbind(struct media_request_object *obj)
433  {
434  }
435  
media_request_object_complete(struct media_request_object * obj)436  static inline void media_request_object_complete(struct media_request_object *obj)
437  {
438  }
439  
440  #endif
441  
442  #endif
443