Skip to content

Commit

Permalink
driver: virtio-camera accepts flag to output debug info
Browse files Browse the repository at this point in the history
Tracked-On: OAM-128423
Signed-off-by: Zhangwei6 <[email protected]>
  • Loading branch information
6ZhangWei committed Dec 11, 2024
1 parent dc47476 commit e1f1481
Showing 1 changed file with 69 additions and 47 deletions.
116 changes: 69 additions & 47 deletions drivers/media/platform/virtio/virtio-camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include <asm/msr.h>
#include "linux/virtio_shm.h"

/* Here borrow this bit to open debug log for virtio_camera */
#define V4L2_DEV_VCAM_DEBUG 0x80

#define VQ_NAME_LEN 24
/**
* struct virtio_camera_ctrl_req - The internal data for one virtio-camera request and response
Expand Down Expand Up @@ -80,7 +83,7 @@ struct virtio_camera_buffer {

/**
* struct virtual_camera - All internal data for one instance of virtual camera
* @vnode: video nodes
* @vnodes: video nodes
* @nr_videos: number of videos; one virtual camera may contain multiple video streams
* @v4l2_lock: ioctl serialization mutex
* @v4l2_dev: top-level v4l2 device struct
Expand Down Expand Up @@ -123,6 +126,11 @@ static inline struct virtio_camera_vq *vq_to_vcamvq(struct virtqueue *vq)
return &vcam->vqs[vq->index];
}

static inline const char *get_vnode_name(struct virtio_camera_video *vnode)
{
return video_device_node_name(&vnode->vdev);
}

static struct virtio_camera_ctrl_req *
virtio_camera_create_req(unsigned int cmd)
{
Expand All @@ -146,6 +154,7 @@ static void virtio_camera_control_ack(struct virtqueue *vq)
struct virtio_camera_vq *vcam_vq = vq_to_vcamvq(vq);
struct virtio_camera_ctrl_req *req;
struct vb2_v4l2_buffer *vbuf;
struct virtio_camera_video *vnode;
unsigned int len;

spin_lock_irq(&vcam_vq->lock);
Expand All @@ -158,8 +167,11 @@ static void virtio_camera_control_ack(struct virtqueue *vq)
vbuf->vb2_buf.timestamp = req->resp.u.buffer.timestamp;
vbuf->planes[0].bytesused = req->resp.u.format.size.sizeimage;
vb2_buffer_done(req->vb, VB2_BUF_STATE_DONE);
pr_debug("virtio-camera: mark the buffer done. UUID is %d, ptr is %pK\n",
req->resp.u.buffer.uuid[0] + req->resp.u.buffer.uuid[1], req->vb);
vnode = vb2_get_drv_priv(vbuf->vb2_buf.vb2_queue);
if(vnode->vdev.dev_debug & V4L2_DEV_VCAM_DEBUG)
pr_info("virtio-camera: %s mark the buffer done. index=%d, UUID is %d\n",
get_vnode_name(vnode), req->vb->index,
req->resp.u.buffer.uuid[0] + req->resp.u.buffer.uuid[1]);

kfree(req);
}
Expand Down Expand Up @@ -192,7 +204,7 @@ static int vcam_vq_request(struct virtio_camera_video *vnode,
spin_lock_irq(&vnode->ctr_vqx->lock);
ret = virtqueue_add_sgs(vnode->ctr_vqx->vq, sgs, num_sgs - 1, 1, req, GFP_KERNEL);
if (ret) {
pr_err("%s: fail to add req to vq, errno is %d\n", __func__, ret);
pr_err("%s: %s fail to add req to vq, errno is %d\n", __func__, get_vnode_name(vnode), ret);
spin_unlock_irq(&vnode->ctr_vqx->lock);
return ret;
}
Expand Down Expand Up @@ -238,13 +250,13 @@ int vcam_v4l2_fh_open(struct file *filp)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_FILE_OPEN);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init open-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init open, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("virtio-camera: vnode%d file handler open failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s file handler open failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand All @@ -268,13 +280,13 @@ int vcam_v4l2_fh_release(struct file *filp)
vnode = video_drvdata(filp);
vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_FILE_CLOSE);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init close-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init close, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err)
pr_err("virtio-camera: vnode%d release file failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s release file failed, err response.\n", get_vnode_name(vnode));

kfree(vcam_req);
return err;
Expand All @@ -296,7 +308,7 @@ static int vcam_querycap(struct file *file, void *priv,

strscpy(cap->bus_info, "platform:camera", sizeof(cap->bus_info));
strscpy(cap->driver, "virtio-camera", sizeof(cap->driver));
snprintf(cap->card, sizeof(cap->card), "virtio-camera%u", vnode->idx);
snprintf(cap->card, sizeof(cap->card), "virtio-camera-node%u", vnode->idx);
return 0;
}

Expand All @@ -308,15 +320,15 @@ static int vcam_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_ENUM_FORMAT);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init enum_fmt-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init enum_fmt, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

vcam_req->ctrl.header.index = f->index;

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("virtio-camera: vnode%d enum_fmt failed, err response.\n", vnode->idx);
if (err && f->index == 0) {
pr_err("virtio-camera: %s enum_fmt failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand All @@ -337,16 +349,16 @@ static int vcam_enum_framesizes(struct file *file, void *fh,

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_ENUM_SIZE);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init enum_size-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init enum_size, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

vcam_req->ctrl.header.index = fsize->index;
vcam_req->ctrl.u.format.pixelformat = fsize->pixel_format;

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("virtio-camera: vnode%d enum_size failed, err response.\n", vnode->idx);
if (err && fsize->index == 0) {
pr_err("virtio-camera: %s enum_size failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand All @@ -369,7 +381,9 @@ static int vcam_enum_framesizes(struct file *file, void *fh,
else
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
}
pr_debug("%s: fmt width is %d, height is %d\n", __func__, sz->width, sz->height);
if(vnode->vdev.dev_debug & V4L2_DEV_VCAM_DEBUG)
pr_info("%s: %s fmt width is %d, height is %d\n", __func__,
get_vnode_name(vnode), sz->width, sz->height);

err_free:
kfree(vcam_req);
Expand All @@ -386,7 +400,7 @@ static int vcam_enum_frameintervals(struct file *file, void *fh,

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_ENUM_INTV);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init enum_interval-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init enum_interval, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

Expand All @@ -397,16 +411,17 @@ static int vcam_enum_frameintervals(struct file *file, void *fh,

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
sz = &vcam_req->resp.u.format.size;
if (err) {
pr_err("virtio-camera: vnode%d enum_interval failed, err response.\n", vnode->idx);
if (err && fintv->index ==0) {
pr_err("virtio-camera: %s enum_interval failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

fintv->type = V4L2_FRMIVAL_TYPE_DISCRETE;
fintv->discrete.denominator = sz->fps;
fintv->discrete.numerator = 1;
pr_debug("%s: idx is %d, denominator is %d, numerator is %d\n", __func__,
fintv->index, fintv->discrete.denominator, fintv->discrete.numerator);
if(vnode->vdev.dev_debug & V4L2_DEV_VCAM_DEBUG)
pr_info("%s: %s idx is %d, denominator is %d, numerator is %d\n", __func__,
get_vnode_name(vnode), fintv->index, fintv->discrete.denominator, fintv->discrete.numerator);

err_free:
kfree(vcam_req);
Expand All @@ -421,13 +436,13 @@ static int vcam_g_fmt(struct file *file, void *fh, struct v4l2_format *f)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_GET_FORMAT);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init get_fmt-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init get_fmt, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("virtio-camera: vnode%d get_fmt failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s get_fmt failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand Down Expand Up @@ -459,13 +474,13 @@ static int vcam_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
int err;

if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
pr_err("virtio-camera: vnode%d only support video capture buffer.\n", vnode->idx);
pr_err("virtio-camera: %s only support video capture buffer.\n", get_vnode_name(vnode));
return -EINVAL;
}

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_SET_FORMAT);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init set_fmt-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init set_fmt, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

Expand All @@ -476,7 +491,7 @@ static int vcam_s_fmt(struct file *file, void *fh, struct v4l2_format *f)

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("virtio-camera: vnode%d set_fmt failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s set_fmt failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand Down Expand Up @@ -507,7 +522,7 @@ static int vcam_try_fmt(struct file *file, void *fh, struct v4l2_format *f)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_TRY_FORMAT);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init try_fmt-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init try_fmt, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

Expand All @@ -518,7 +533,7 @@ static int vcam_try_fmt(struct file *file, void *fh, struct v4l2_format *f)

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("virtio-camera: vnode%d try_fmt failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s try_fmt failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand Down Expand Up @@ -609,8 +624,8 @@ vcam_queue_setup(struct vb2_queue *vq,
if (*num_planes) {
ret = sizes[0] < size ? -EINVAL : 0;
if (ret != 0)
pr_err("virtio-camera: vnode%d fail to setup queue,\
size[0]=%d is invalid.\n", vnode->idx, sizes[0]);
pr_err("virtio-camera: %s fail to setup queue,\
size[0]=%d is invalid.\n", get_vnode_name(vnode), sizes[0]);
return ret;
}

Expand All @@ -633,14 +648,14 @@ static int vcam_buf_init(struct vb2_buffer *vb)

/* TODO */
if (WARN_ON(vb->num_planes != 1)) {
pr_err("virtio-camera: vnode%d fail to init buffer, only support 1 plane buffer.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init buffer, only support 1 plane buffer.\n", get_vnode_name(vnode));
return -EINVAL;
}

sgt = vb2_dma_sg_plane_desc(vb, 0);
ents = kmalloc_array(sgt->nents, sizeof(*ents), GFP_KERNEL);
if (!ents) {
pr_err("virtio-camera: vnode%d fail to init buffer, no mem", vnode->idx);
pr_err("virtio-camera: %s fail to init buffer, no mem", get_vnode_name(vnode));
return -ENOMEM;
}

Expand All @@ -660,7 +675,7 @@ static int vcam_buf_init(struct vb2_buffer *vb)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_CREATE_BUFFER);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init create_buffer-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init create_buffer, no mem.\n", get_vnode_name(vnode));
err = -ENOMEM;
goto fail_alloc_req;
}
Expand All @@ -669,7 +684,7 @@ static int vcam_buf_init(struct vb2_buffer *vb)

err = vcam_vq_request(vnode, vcam_req, ents, sgt->nents, false);
if (err) {
pr_err("virtio-camera: vnode%d create_buffer failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s create_buffer failed, err response.\n", get_vnode_name(vnode));
goto err_free;
}

Expand All @@ -693,15 +708,15 @@ static void vcam_buf_cleanup(struct vb2_buffer *vb)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_DESTROY_BUFFER);
if (unlikely(vcam_req == NULL)) {
pr_err("%s: Failed to clean vcam buffer\n", __func__);
pr_err("%s: %s Failed to clean vcam buffer\n", __func__, get_vnode_name(vnode));
return;
}

memcpy(vcam_req->ctrl.u.buffer.uuid, vbuf->uuid, sizeof(vbuf->uuid));
err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err) {
pr_err("%s: Failed to deinit virtio-camera buffers, buffers may still be retained by backend\n",
__func__);
pr_err("%s: %s Failed to deinit virtio-camera buffers, buffers may still be retained by backend\n",
__func__, get_vnode_name(vnode));
}
kfree(vcam_req);
}
Expand All @@ -724,7 +739,7 @@ static void vcam_buf_queue(struct vb2_buffer *vb)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_ENQUEUE_BUFFER);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init enqueue_buffer-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init enqueue_buffer, no mem.\n", get_vnode_name(vnode));
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
return;
}
Expand All @@ -733,14 +748,15 @@ static void vcam_buf_queue(struct vb2_buffer *vb)
vcam_req->vb = vb;
err = vcam_vq_request(vnode, vcam_req, NULL, 0, true);
if (err) {
pr_err("virtio-camera: vnode%d enqueue_buffer failed, err response, errno %d\n", vnode->idx, err);
pr_err("virtio-camera: %s enqueue_buffer failed, err response, errno %d\n", get_vnode_name(vnode), err);
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
goto err_free;
}

pr_debug("%s: video%d queue a buffer, success. UUID is %d, ptr is %pK\n",
__func__, vnode->idx, vcam_req->resp.u.buffer.uuid[0] + vcam_req->resp.u.buffer.uuid[1],
vcam_req->vb);
if(vnode->vdev.dev_debug & V4L2_DEV_VCAM_DEBUG)
pr_info("virtio-camera: %s queue a buffer, success. index=%d, UUID is %d\n",
get_vnode_name(vnode), vb->index,
vcam_req->resp.u.buffer.uuid[0] + vcam_req->resp.u.buffer.uuid[1]);

return;

Expand All @@ -757,13 +773,13 @@ static int vcam_start_streaming(struct vb2_queue *q, unsigned int count)
vnode->sequence = 0;
vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_STREAM_ON);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init stream_on-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init stream_on, no mem.\n", get_vnode_name(vnode));
return -ENOMEM;
}

err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err)
pr_err("virtio-camera: vnode%d stream_on failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s stream_on failed, err response.\n", get_vnode_name(vnode));

kfree(vcam_req);
return err;
Expand All @@ -777,14 +793,14 @@ static void vcam_stop_streaming(struct vb2_queue *q)

vcam_req = virtio_camera_create_req(VIRTIO_CAMERA_CMD_STREAM_OFF);
if (unlikely(vcam_req == NULL)) {
pr_err("virtio-camera: vnode%d fail to init stream_off-req, no mem.\n", vnode->idx);
pr_err("virtio-camera: %s fail to init stream_off, no mem.\n", get_vnode_name(vnode));
return;
}

/*TODO, mark all vcam buffers invalid when err occur*/
err = vcam_vq_request(vnode, vcam_req, NULL, 0, false);
if (err)
pr_err("virtio-camera: vnode%d stream_off failed, err response.\n", vnode->idx);
pr_err("virtio-camera: %s stream_off failed, err response.\n", get_vnode_name(vnode));

vb2_wait_for_all_buffers(q);
kfree(vcam_req);
Expand Down Expand Up @@ -985,10 +1001,11 @@ static int virtio_camera_setup_vnode(struct virtio_device *vdev,
virtio_camera_unregister_devs(vcam, i, j-1);
return dev_err_probe(&vdev->dev, err, "failed to register video");
}
pr_info("virtio_camera registered video device %s\n",
get_vnode_name(vnode));
}
}

pr_info("%s: success register video devices\n", __func__);
return 0;
}

Expand All @@ -1007,6 +1024,11 @@ static int virtio_camera_probe(struct virtio_device *vdev)

virtio_cread_bytes(vdev, 0, &vcam->config, sizeof(vcam->config));

if (vcam->config.num_virtual_cameras == 0) {
pr_err("%s: get 0 cameras, invalid config.\n", __func__);
return -EINVAL;
}

if (vcam->config.num_virtual_cameras > ARRAY_SIZE(vcam->config.nr_per_virtual_camera)) {
pr_err("%s: nr cameras too large %d", __func__, vcam->config.num_virtual_cameras);
return -EINVAL;
Expand Down

0 comments on commit e1f1481

Please sign in to comment.