cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

media-request.h (12245B)


      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