@@ -158,6 +158,37 @@ static void media_device_request_delete(struct media_device *mdev,
media_device_request_put(req);
}
+static int media_device_request_queue_apply(
+ struct media_device *mdev, struct media_device_request *req,
+ int (*fn)(struct media_device *mdev,
+ struct media_device_request *req))
+{
+ unsigned long flags;
+ int rval = 0;
+
+ if (!fn)
+ return -ENOSYS;
+
+ spin_lock_irqsave(&mdev->req_lock, flags);
+ if (req->state != MEDIA_DEVICE_REQUEST_STATE_IDLE)
+ rval = -EINVAL;
+ else
+ req->state = MEDIA_DEVICE_REQUEST_STATE_QUEUED;
+ spin_unlock_irqrestore(&mdev->req_lock, flags);
+
+ if (rval)
+ return rval;
+
+ rval = fn(mdev, req);
+ if (rval) {
+ spin_lock_irqsave(&mdev->req_lock, flags);
+ req->state = MEDIA_DEVICE_REQUEST_STATE_IDLE;
+ spin_unlock_irqrestore(&mdev->req_lock, flags);
+ }
+
+ return rval;
+}
+
static long media_device_request_cmd(struct media_device *mdev,
struct file *filp,
struct media_request_cmd *cmd)
@@ -186,17 +217,13 @@ static long media_device_request_cmd(struct media_device *mdev,
break;
case MEDIA_REQ_CMD_APPLY:
- if (!mdev->ops->req_apply)
- return -ENOSYS;
-
- ret = mdev->ops->req_apply(mdev, req);
+ ret = media_device_request_queue_apply(mdev, req,
+ mdev->ops->req_apply);
break;
case MEDIA_REQ_CMD_QUEUE:
- if (!mdev->ops->req_queue)
- return -ENOSYS;
-
- ret = mdev->ops->req_queue(mdev, req);
+ ret = media_device_request_queue_apply(mdev, req,
+ mdev->ops->req_queue);
break;
default:
Verify that the request state is IDLE before queueing it. Also mark requests queued when they're queued, and return the request to IDLE if queueing it failed. Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> --- drivers/media/media-device.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-)