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@xxxxxxxxxxxxxxx> --- drivers/media/media-device.c | 55 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 7781c49..247587b 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -189,6 +189,47 @@ 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), bool queue) +{ + char *str = queue ? "queue" : "apply"; + 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; + dev_dbg(mdev->dev, + "request: unable to %s %u, request in state %s\n", + str, req->id, request_state(req->state)); + } 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); + dev_dbg(mdev->dev, + "request: can't %s %u\n", str, req->id); + } else { + dev_dbg(mdev->dev, + "request: %s %u\n", str, req->id); + } + + return rval; +} + static long media_device_request_cmd(struct media_device *mdev, struct file *filp, struct media_request_cmd *cmd) @@ -216,17 +257,15 @@ 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, + false); 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, + true); break; default: -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html