mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:04:51 +01:00
media: mc: add manual request completion
By default when the last request object is completed, the whole request completes as well. But sometimes you want to delay this completion to an arbitrary point in time so add a manual complete mode for this. In req_queue the driver marks the request for manual completion by calling media_request_mark_manual_completion, and when the driver wants to manually complete the request it calls media_request_manual_complete(). Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
This commit is contained in:
parent
a519e21e32
commit
c789a7f402
2 changed files with 76 additions and 3 deletions
|
|
@ -54,6 +54,7 @@ static void media_request_clean(struct media_request *req)
|
|||
req->access_count = 0;
|
||||
WARN_ON(req->num_incomplete_objects);
|
||||
req->num_incomplete_objects = 0;
|
||||
req->manual_completion = false;
|
||||
wake_up_interruptible_all(&req->poll_wait);
|
||||
}
|
||||
|
||||
|
|
@ -298,6 +299,7 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
|
|||
req->mdev = mdev;
|
||||
req->state = MEDIA_REQUEST_STATE_IDLE;
|
||||
req->num_incomplete_objects = 0;
|
||||
req->manual_completion = false;
|
||||
kref_init(&req->kref);
|
||||
INIT_LIST_HEAD(&req->objects);
|
||||
spin_lock_init(&req->lock);
|
||||
|
|
@ -449,7 +451,7 @@ void media_request_object_unbind(struct media_request_object *obj)
|
|||
|
||||
req->num_incomplete_objects--;
|
||||
if (req->state == MEDIA_REQUEST_STATE_QUEUED &&
|
||||
!req->num_incomplete_objects) {
|
||||
!req->num_incomplete_objects && !req->manual_completion) {
|
||||
req->state = MEDIA_REQUEST_STATE_COMPLETE;
|
||||
completed = true;
|
||||
wake_up_interruptible_all(&req->poll_wait);
|
||||
|
|
@ -478,7 +480,7 @@ void media_request_object_complete(struct media_request_object *obj)
|
|||
WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
|
||||
goto unlock;
|
||||
|
||||
if (!--req->num_incomplete_objects) {
|
||||
if (!--req->num_incomplete_objects && !req->manual_completion) {
|
||||
req->state = MEDIA_REQUEST_STATE_COMPLETE;
|
||||
wake_up_interruptible_all(&req->poll_wait);
|
||||
completed = true;
|
||||
|
|
@ -489,3 +491,38 @@ unlock:
|
|||
media_request_put(req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(media_request_object_complete);
|
||||
|
||||
void media_request_manual_complete(struct media_request *req)
|
||||
{
|
||||
bool completed = false;
|
||||
unsigned long flags;
|
||||
|
||||
if (WARN_ON_ONCE(!req))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&req->lock, flags);
|
||||
|
||||
if (WARN_ON_ONCE(!req->manual_completion))
|
||||
goto unlock;
|
||||
|
||||
if (WARN_ON_ONCE(req->state != MEDIA_REQUEST_STATE_QUEUED))
|
||||
goto unlock;
|
||||
|
||||
req->manual_completion = false;
|
||||
/*
|
||||
* It is expected that all other objects in this request are
|
||||
* completed when this function is called. WARN if that is
|
||||
* not the case.
|
||||
*/
|
||||
if (!WARN_ON(req->num_incomplete_objects)) {
|
||||
req->state = MEDIA_REQUEST_STATE_COMPLETE;
|
||||
wake_up_interruptible_all(&req->poll_wait);
|
||||
completed = true;
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&req->lock, flags);
|
||||
if (completed)
|
||||
media_request_put(req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(media_request_manual_complete);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ struct media_request_object;
|
|||
* @access_count: count the number of request accesses that are in progress
|
||||
* @objects: List of @struct media_request_object request objects
|
||||
* @num_incomplete_objects: The number of incomplete objects in the request
|
||||
* @manual_completion: if true, then the request won't be marked as completed
|
||||
* when @num_incomplete_objects reaches 0. Call media_request_manual_complete()
|
||||
* to complete the request after @num_incomplete_objects == 0.
|
||||
* @poll_wait: Wait queue for poll
|
||||
* @lock: Serializes access to this struct
|
||||
*/
|
||||
|
|
@ -68,6 +71,7 @@ struct media_request {
|
|||
unsigned int access_count;
|
||||
struct list_head objects;
|
||||
unsigned int num_incomplete_objects;
|
||||
bool manual_completion;
|
||||
wait_queue_head_t poll_wait;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
|
@ -218,6 +222,38 @@ media_request_get_by_fd(struct media_device *mdev, int request_fd);
|
|||
int media_request_alloc(struct media_device *mdev,
|
||||
int *alloc_fd);
|
||||
|
||||
/**
|
||||
* media_request_mark_manual_completion - Enable manual completion
|
||||
*
|
||||
* @req: The request
|
||||
*
|
||||
* Mark that the request has to be manually completed by calling
|
||||
* media_request_manual_complete().
|
||||
*
|
||||
* This function shall be called in the req_queue callback.
|
||||
*/
|
||||
static inline void
|
||||
media_request_mark_manual_completion(struct media_request *req)
|
||||
{
|
||||
req->manual_completion = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* media_request_manual_complete - Mark the request as completed
|
||||
*
|
||||
* @req: The request
|
||||
*
|
||||
* This function completes a request that was marked for manual completion by an
|
||||
* earlier call to media_request_mark_manual_completion(). The request's
|
||||
* @manual_completion field is reset to false.
|
||||
*
|
||||
* All objects contained in the request must have been completed previously. It
|
||||
* is an error to call this function otherwise. If such an error occurred, the
|
||||
* function will WARN and the object completion will be delayed until
|
||||
* @num_incomplete_objects is 0.
|
||||
*/
|
||||
void media_request_manual_complete(struct media_request *req);
|
||||
|
||||
#else
|
||||
|
||||
static inline void media_request_get(struct media_request *req)
|
||||
|
|
@ -336,7 +372,7 @@ void media_request_object_init(struct media_request_object *obj);
|
|||
* @req: The media request
|
||||
* @ops: The object ops for this object
|
||||
* @priv: A driver-specific priv pointer associated with this object
|
||||
* @is_buffer: Set to true if the object a buffer object.
|
||||
* @is_buffer: Set to true if the object is a buffer object.
|
||||
* @obj: The object
|
||||
*
|
||||
* Bind this object to the request and set the ops and priv values of
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue