Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Media device request objects
0004  *
0005  * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
0006  * Copyright (C) 2018 Intel Corporation
0007  *
0008  * Author: Hans Verkuil <hans.verkuil@cisco.com>
0009  * Author: Sakari Ailus <sakari.ailus@linux.intel.com>
0010  */
0011 
0012 #ifndef MEDIA_REQUEST_H
0013 #define MEDIA_REQUEST_H
0014 
0015 #include <linux/list.h>
0016 #include <linux/slab.h>
0017 #include <linux/spinlock.h>
0018 #include <linux/refcount.h>
0019 
0020 #include <media/media-device.h>
0021 
0022 /**
0023  * enum media_request_state - media request state
0024  *
0025  * @MEDIA_REQUEST_STATE_IDLE:       Idle
0026  * @MEDIA_REQUEST_STATE_VALIDATING: Validating the request, no state changes
0027  *                  allowed
0028  * @MEDIA_REQUEST_STATE_QUEUED:     Queued
0029  * @MEDIA_REQUEST_STATE_COMPLETE:   Completed, the request is done
0030  * @MEDIA_REQUEST_STATE_CLEANING:   Cleaning, the request is being re-inited
0031  * @MEDIA_REQUEST_STATE_UPDATING:   The request is being updated, i.e.
0032  *                  request objects are being added,
0033  *                  modified or removed
0034  * @NR_OF_MEDIA_REQUEST_STATE:      The number of media request states, used
0035  *                  internally for sanity check purposes
0036  */
0037 enum media_request_state {
0038     MEDIA_REQUEST_STATE_IDLE,
0039     MEDIA_REQUEST_STATE_VALIDATING,
0040     MEDIA_REQUEST_STATE_QUEUED,
0041     MEDIA_REQUEST_STATE_COMPLETE,
0042     MEDIA_REQUEST_STATE_CLEANING,
0043     MEDIA_REQUEST_STATE_UPDATING,
0044     NR_OF_MEDIA_REQUEST_STATE,
0045 };
0046 
0047 struct media_request_object;
0048 
0049 /**
0050  * struct media_request - Media device request
0051  * @mdev: Media device this request belongs to
0052  * @kref: Reference count
0053  * @debug_str: Prefix for debug messages (process name:fd)
0054  * @state: The state of the request
0055  * @updating_count: count the number of request updates that are in progress
0056  * @access_count: count the number of request accesses that are in progress
0057  * @objects: List of @struct media_request_object request objects
0058  * @num_incomplete_objects: The number of incomplete objects in the request
0059  * @poll_wait: Wait queue for poll
0060  * @lock: Serializes access to this struct
0061  */
0062 struct media_request {
0063     struct media_device *mdev;
0064     struct kref kref;
0065     char debug_str[TASK_COMM_LEN + 11];
0066     enum media_request_state state;
0067     unsigned int updating_count;
0068     unsigned int access_count;
0069     struct list_head objects;
0070     unsigned int num_incomplete_objects;
0071     wait_queue_head_t poll_wait;
0072     spinlock_t lock;
0073 };
0074 
0075 #ifdef CONFIG_MEDIA_CONTROLLER
0076 
0077 /**
0078  * media_request_lock_for_access - Lock the request to access its objects
0079  *
0080  * @req: The media request
0081  *
0082  * Use before accessing a completed request. A reference to the request must
0083  * be held during the access. This usually takes place automatically through
0084  * a file handle. Use @media_request_unlock_for_access when done.
0085  */
0086 static inline int __must_check
0087 media_request_lock_for_access(struct media_request *req)
0088 {
0089     unsigned long flags;
0090     int ret = -EBUSY;
0091 
0092     spin_lock_irqsave(&req->lock, flags);
0093     if (req->state == MEDIA_REQUEST_STATE_COMPLETE) {
0094         req->access_count++;
0095         ret = 0;
0096     }
0097     spin_unlock_irqrestore(&req->lock, flags);
0098 
0099     return ret;
0100 }
0101 
0102 /**
0103  * media_request_unlock_for_access - Unlock a request previously locked for
0104  *                   access
0105  *
0106  * @req: The media request
0107  *
0108  * Unlock a request that has previously been locked using
0109  * @media_request_lock_for_access.
0110  */
0111 static inline void media_request_unlock_for_access(struct media_request *req)
0112 {
0113     unsigned long flags;
0114 
0115     spin_lock_irqsave(&req->lock, flags);
0116     if (!WARN_ON(!req->access_count))
0117         req->access_count--;
0118     spin_unlock_irqrestore(&req->lock, flags);
0119 }
0120 
0121 /**
0122  * media_request_lock_for_update - Lock the request for updating its objects
0123  *
0124  * @req: The media request
0125  *
0126  * Use before updating a request, i.e. adding, modifying or removing a request
0127  * object in it. A reference to the request must be held during the update. This
0128  * usually takes place automatically through a file handle. Use
0129  * @media_request_unlock_for_update when done.
0130  */
0131 static inline int __must_check
0132 media_request_lock_for_update(struct media_request *req)
0133 {
0134     unsigned long flags;
0135     int ret = 0;
0136 
0137     spin_lock_irqsave(&req->lock, flags);
0138     if (req->state == MEDIA_REQUEST_STATE_IDLE ||
0139         req->state == MEDIA_REQUEST_STATE_UPDATING) {
0140         req->state = MEDIA_REQUEST_STATE_UPDATING;
0141         req->updating_count++;
0142     } else {
0143         ret = -EBUSY;
0144     }
0145     spin_unlock_irqrestore(&req->lock, flags);
0146 
0147     return ret;
0148 }
0149 
0150 /**
0151  * media_request_unlock_for_update - Unlock a request previously locked for
0152  *                   update
0153  *
0154  * @req: The media request
0155  *
0156  * Unlock a request that has previously been locked using
0157  * @media_request_lock_for_update.
0158  */
0159 static inline void media_request_unlock_for_update(struct media_request *req)
0160 {
0161     unsigned long flags;
0162 
0163     spin_lock_irqsave(&req->lock, flags);
0164     WARN_ON(req->updating_count <= 0);
0165     if (!--req->updating_count)
0166         req->state = MEDIA_REQUEST_STATE_IDLE;
0167     spin_unlock_irqrestore(&req->lock, flags);
0168 }
0169 
0170 /**
0171  * media_request_get - Get the media request
0172  *
0173  * @req: The media request
0174  *
0175  * Get the media request.
0176  */
0177 static inline void media_request_get(struct media_request *req)
0178 {
0179     kref_get(&req->kref);
0180 }
0181 
0182 /**
0183  * media_request_put - Put the media request
0184  *
0185  * @req: The media request
0186  *
0187  * Put the media request. The media request will be released
0188  * when the refcount reaches 0.
0189  */
0190 void media_request_put(struct media_request *req);
0191 
0192 /**
0193  * media_request_get_by_fd - Get a media request by fd
0194  *
0195  * @mdev: Media device this request belongs to
0196  * @request_fd: The file descriptor of the request
0197  *
0198  * Get the request represented by @request_fd that is owned
0199  * by the media device.
0200  *
0201  * Return a -EBADR error pointer if requests are not supported
0202  * by this driver. Return -EINVAL if the request was not found.
0203  * Return the pointer to the request if found: the caller will
0204  * have to call @media_request_put when it finished using the
0205  * request.
0206  */
0207 struct media_request *
0208 media_request_get_by_fd(struct media_device *mdev, int request_fd);
0209 
0210 /**
0211  * media_request_alloc - Allocate the media request
0212  *
0213  * @mdev: Media device this request belongs to
0214  * @alloc_fd: Store the request's file descriptor in this int
0215  *
0216  * Allocated the media request and put the fd in @alloc_fd.
0217  */
0218 int media_request_alloc(struct media_device *mdev,
0219             int *alloc_fd);
0220 
0221 #else
0222 
0223 static inline void media_request_get(struct media_request *req)
0224 {
0225 }
0226 
0227 static inline void media_request_put(struct media_request *req)
0228 {
0229 }
0230 
0231 static inline struct media_request *
0232 media_request_get_by_fd(struct media_device *mdev, int request_fd)
0233 {
0234     return ERR_PTR(-EBADR);
0235 }
0236 
0237 #endif
0238 
0239 /**
0240  * struct media_request_object_ops - Media request object operations
0241  * @prepare: Validate and prepare the request object, optional.
0242  * @unprepare: Unprepare the request object, optional.
0243  * @queue: Queue the request object, optional.
0244  * @unbind: Unbind the request object, optional.
0245  * @release: Release the request object, required.
0246  */
0247 struct media_request_object_ops {
0248     int (*prepare)(struct media_request_object *object);
0249     void (*unprepare)(struct media_request_object *object);
0250     void (*queue)(struct media_request_object *object);
0251     void (*unbind)(struct media_request_object *object);
0252     void (*release)(struct media_request_object *object);
0253 };
0254 
0255 /**
0256  * struct media_request_object - An opaque object that belongs to a media
0257  *               request
0258  *
0259  * @ops: object's operations
0260  * @priv: object's priv pointer
0261  * @req: the request this object belongs to (can be NULL)
0262  * @list: List entry of the object for @struct media_request
0263  * @kref: Reference count of the object, acquire before releasing req->lock
0264  * @completed: If true, then this object was completed.
0265  *
0266  * An object related to the request. This struct is always embedded in
0267  * another struct that contains the actual data for this request object.
0268  */
0269 struct media_request_object {
0270     const struct media_request_object_ops *ops;
0271     void *priv;
0272     struct media_request *req;
0273     struct list_head list;
0274     struct kref kref;
0275     bool completed;
0276 };
0277 
0278 #ifdef CONFIG_MEDIA_CONTROLLER
0279 
0280 /**
0281  * media_request_object_get - Get a media request object
0282  *
0283  * @obj: The object
0284  *
0285  * Get a media request object.
0286  */
0287 static inline void media_request_object_get(struct media_request_object *obj)
0288 {
0289     kref_get(&obj->kref);
0290 }
0291 
0292 /**
0293  * media_request_object_put - Put a media request object
0294  *
0295  * @obj: The object
0296  *
0297  * Put a media request object. Once all references are gone, the
0298  * object's memory is released.
0299  */
0300 void media_request_object_put(struct media_request_object *obj);
0301 
0302 /**
0303  * media_request_object_find - Find an object in a request
0304  *
0305  * @req: The media request
0306  * @ops: Find an object with this ops value
0307  * @priv: Find an object with this priv value
0308  *
0309  * Both @ops and @priv must be non-NULL.
0310  *
0311  * Returns the object pointer or NULL if not found. The caller must
0312  * call media_request_object_put() once it finished using the object.
0313  *
0314  * Since this function needs to walk the list of objects it takes
0315  * the @req->lock spin lock to make this safe.
0316  */
0317 struct media_request_object *
0318 media_request_object_find(struct media_request *req,
0319               const struct media_request_object_ops *ops,
0320               void *priv);
0321 
0322 /**
0323  * media_request_object_init - Initialise a media request object
0324  *
0325  * @obj: The object
0326  *
0327  * Initialise a media request object. The object will be released using the
0328  * release callback of the ops once it has no references (this function
0329  * initialises references to one).
0330  */
0331 void media_request_object_init(struct media_request_object *obj);
0332 
0333 /**
0334  * media_request_object_bind - Bind a media request object to a request
0335  *
0336  * @req: The media request
0337  * @ops: The object ops for this object
0338  * @priv: A driver-specific priv pointer associated with this object
0339  * @is_buffer: Set to true if the object a buffer object.
0340  * @obj: The object
0341  *
0342  * Bind this object to the request and set the ops and priv values of
0343  * the object so it can be found later with media_request_object_find().
0344  *
0345  * Every bound object must be unbound or completed by the kernel at some
0346  * point in time, otherwise the request will never complete. When the
0347  * request is released all completed objects will be unbound by the
0348  * request core code.
0349  *
0350  * Buffer objects will be added to the end of the request's object
0351  * list, non-buffer objects will be added to the front of the list.
0352  * This ensures that all buffer objects are at the end of the list
0353  * and that all non-buffer objects that they depend on are processed
0354  * first.
0355  */
0356 int media_request_object_bind(struct media_request *req,
0357                   const struct media_request_object_ops *ops,
0358                   void *priv, bool is_buffer,
0359                   struct media_request_object *obj);
0360 
0361 /**
0362  * media_request_object_unbind - Unbind a media request object
0363  *
0364  * @obj: The object
0365  *
0366  * Unbind the media request object from the request.
0367  */
0368 void media_request_object_unbind(struct media_request_object *obj);
0369 
0370 /**
0371  * media_request_object_complete - Mark the media request object as complete
0372  *
0373  * @obj: The object
0374  *
0375  * Mark the media request object as complete. Only bound objects can
0376  * be completed.
0377  */
0378 void media_request_object_complete(struct media_request_object *obj);
0379 
0380 #else
0381 
0382 static inline int __must_check
0383 media_request_lock_for_access(struct media_request *req)
0384 {
0385     return -EINVAL;
0386 }
0387 
0388 static inline void media_request_unlock_for_access(struct media_request *req)
0389 {
0390 }
0391 
0392 static inline int __must_check
0393 media_request_lock_for_update(struct media_request *req)
0394 {
0395     return -EINVAL;
0396 }
0397 
0398 static inline void media_request_unlock_for_update(struct media_request *req)
0399 {
0400 }
0401 
0402 static inline void media_request_object_get(struct media_request_object *obj)
0403 {
0404 }
0405 
0406 static inline void media_request_object_put(struct media_request_object *obj)
0407 {
0408 }
0409 
0410 static inline struct media_request_object *
0411 media_request_object_find(struct media_request *req,
0412               const struct media_request_object_ops *ops,
0413               void *priv)
0414 {
0415     return NULL;
0416 }
0417 
0418 static inline void media_request_object_init(struct media_request_object *obj)
0419 {
0420     obj->ops = NULL;
0421     obj->req = NULL;
0422 }
0423 
0424 static inline int media_request_object_bind(struct media_request *req,
0425                    const struct media_request_object_ops *ops,
0426                    void *priv, bool is_buffer,
0427                    struct media_request_object *obj)
0428 {
0429     return 0;
0430 }
0431 
0432 static inline void media_request_object_unbind(struct media_request_object *obj)
0433 {
0434 }
0435 
0436 static inline void media_request_object_complete(struct media_request_object *obj)
0437 {
0438 }
0439 
0440 #endif
0441 
0442 #endif