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 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 */ 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 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 */ 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 */ 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 443
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.