summaryrefslogtreecommitdiff
path: root/drivers/media/mc/mc-request.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/mc/mc-request.c')
-rw-r--r--drivers/media/mc/mc-request.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c
index 3cca9a0c7c97..8ad10c72f9db 100644
--- a/drivers/media/mc/mc-request.c
+++ b/drivers/media/mc/mc-request.c
@@ -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);
}
@@ -74,6 +75,7 @@ static void media_request_release(struct kref *kref)
mdev->ops->req_free(req);
else
kfree(req);
+ atomic_dec(&mdev->num_requests);
}
void media_request_put(struct media_request *req)
@@ -298,6 +300,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);
@@ -317,6 +320,7 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
snprintf(req->debug_str, sizeof(req->debug_str), "%u:%d",
atomic_inc_return(&mdev->request_id), fd_prepare_fd(fdf));
+ atomic_inc(&mdev->num_requests);
dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);
*alloc_fd = fd_publish(fdf);
@@ -337,10 +341,12 @@ static void media_request_object_release(struct kref *kref)
struct media_request_object *obj =
container_of(kref, struct media_request_object, kref);
struct media_request *req = obj->req;
+ struct media_device *mdev = obj->mdev;
if (WARN_ON(req))
media_request_object_unbind(obj);
obj->ops->release(obj);
+ atomic_dec(&mdev->num_request_objects);
}
struct media_request_object *
@@ -405,6 +411,7 @@ int media_request_object_bind(struct media_request *req,
obj->req = req;
obj->ops = ops;
obj->priv = priv;
+ obj->mdev = req->mdev;
if (is_buffer)
list_add_tail(&obj->list, &req->objects);
@@ -412,6 +419,7 @@ int media_request_object_bind(struct media_request *req,
list_add(&obj->list, &req->objects);
req->num_incomplete_objects++;
ret = 0;
+ atomic_inc(&obj->mdev->num_request_objects);
unlock:
spin_unlock_irqrestore(&req->lock, flags);
@@ -449,7 +457,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 +486,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 +497,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);