Branch data Line data Source code
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 87 : 0 : media_request_lock_for_access(struct media_request *req) 88 : : { 89 : : unsigned long flags; 90 : : int ret = -EBUSY; 91 : : 92 : 0 : spin_lock_irqsave(&req->lock, flags); 93 : 0 : if (req->state == MEDIA_REQUEST_STATE_COMPLETE) { 94 : 0 : req->access_count++; 95 : : ret = 0; 96 : : } 97 : : spin_unlock_irqrestore(&req->lock, flags); 98 : : 99 : 0 : 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 : : */ 111 : 0 : static inline void media_request_unlock_for_access(struct media_request *req) 112 : : { 113 : : unsigned long flags; 114 : : 115 : 0 : spin_lock_irqsave(&req->lock, flags); 116 : 0 : if (!WARN_ON(!req->access_count)) 117 : 0 : req->access_count--; 118 : : spin_unlock_irqrestore(&req->lock, flags); 119 : 0 : } 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 132 : 0 : media_request_lock_for_update(struct media_request *req) 133 : : { 134 : : unsigned long flags; 135 : : int ret = 0; 136 : : 137 : 0 : spin_lock_irqsave(&req->lock, flags); 138 : 0 : if (req->state == MEDIA_REQUEST_STATE_IDLE || 139 : : req->state == MEDIA_REQUEST_STATE_UPDATING) { 140 : 0 : req->state = MEDIA_REQUEST_STATE_UPDATING; 141 : 0 : req->updating_count++; 142 : : } else { 143 : : ret = -EBUSY; 144 : : } 145 : : spin_unlock_irqrestore(&req->lock, flags); 146 : : 147 : 0 : 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 : : */ 159 : 0 : static inline void media_request_unlock_for_update(struct media_request *req) 160 : : { 161 : : unsigned long flags; 162 : : 163 : 0 : spin_lock_irqsave(&req->lock, flags); 164 : 0 : WARN_ON(req->updating_count <= 0); 165 : 0 : if (!--req->updating_count) 166 : 0 : req->state = MEDIA_REQUEST_STATE_IDLE; 167 : : spin_unlock_irqrestore(&req->lock, flags); 168 : 0 : } 169 : : 170 : : /** 171 : : * media_request_get - Get the media request 172 : : * 173 : : * @req: The media request 174 : : * 175 : : * Get the media request. 176 : : */ 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 : : 223 : : static inline void media_request_get(struct media_request *req) 224 : : { 225 : : } 226 : : 227 : : static inline void media_request_put(struct media_request *req) 228 : : { 229 : : } 230 : : 231 : : static inline struct media_request * 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 : : */ 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 383 : : media_request_lock_for_access(struct media_request *req) 384 : : { 385 : : return -EINVAL; 386 : : } 387 : : 388 : : static inline void media_request_unlock_for_access(struct media_request *req) 389 : : { 390 : : } 391 : : 392 : : static inline int __must_check 393 : : media_request_lock_for_update(struct media_request *req) 394 : : { 395 : : return -EINVAL; 396 : : } 397 : : 398 : : static inline void media_request_unlock_for_update(struct media_request *req) 399 : : { 400 : : } 401 : : 402 : : static inline void media_request_object_get(struct media_request_object *obj) 403 : : { 404 : : } 405 : : 406 : : static inline void media_request_object_put(struct media_request_object *obj) 407 : : { 408 : : } 409 : : 410 : : static inline struct media_request_object * 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 : : 418 : : static inline void media_request_object_init(struct media_request_object *obj) 419 : : { 420 : : obj->ops = NULL; 421 : : obj->req = NULL; 422 : : } 423 : : 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 : : 432 : : static inline void media_request_object_unbind(struct media_request_object *obj) 433 : : { 434 : : } 435 : : 436 : : static inline void media_request_object_complete(struct media_request_object *obj) 437 : : { 438 : : } 439 : : 440 : : #endif 441 : : 442 : : #endif