linux/include/media/media-request.h
<<
>>
Prefs
   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 */
  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 * @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 */
  62struct 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 */
  86static inline int __must_check
  87media_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 */
 111static 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 */
 131static inline int __must_check
 132media_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 */
 159static 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 */
 177static 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 */
 190void 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 */
 207struct media_request *
 208media_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 */
 218int media_request_alloc(struct media_device *mdev,
 219                        int *alloc_fd);
 220
 221#else
 222
 223static inline void media_request_get(struct media_request *req)
 224{
 225}
 226
 227static inline void media_request_put(struct media_request *req)
 228{
 229}
 230
 231static inline struct media_request *
 232media_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 */
 247struct 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 */
 269struct 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 */
 287static 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 */
 300void 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 */
 317struct media_request_object *
 318media_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 */
 331void 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 */
 356int 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 */
 368void 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 */
 378void media_request_object_complete(struct media_request_object *obj);
 379
 380#else
 381
 382static inline int __must_check
 383media_request_lock_for_access(struct media_request *req)
 384{
 385        return -EINVAL;
 386}
 387
 388static inline void media_request_unlock_for_access(struct media_request *req)
 389{
 390}
 391
 392static inline int __must_check
 393media_request_lock_for_update(struct media_request *req)
 394{
 395        return -EINVAL;
 396}
 397
 398static inline void media_request_unlock_for_update(struct media_request *req)
 399{
 400}
 401
 402static inline void media_request_object_get(struct media_request_object *obj)
 403{
 404}
 405
 406static inline void media_request_object_put(struct media_request_object *obj)
 407{
 408}
 409
 410static inline struct media_request_object *
 411media_request_object_find(struct media_request *req,
 412                          const struct media_request_object_ops *ops,
 413                          void *priv)
 414{
 415        return NULL;
 416}
 417
 418static inline void media_request_object_init(struct media_request_object *obj)
 419{
 420        obj->ops = NULL;
 421        obj->req = NULL;
 422}
 423
 424static 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
 432static inline void media_request_object_unbind(struct media_request_object *obj)
 433{
 434}
 435
 436static inline void media_request_object_complete(struct media_request_object *obj)
 437{
 438}
 439
 440#endif
 441
 442#endif
 443