From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Ong Hock Yu Date: Tue, 27 Nov 2018 22:48:32 +0000 Subject: [PATCH] media: intel-ipu4: [VIRT] Fix PSYS 2 PG operation issue. The psys file node is open multiple times per operation with multiple instances of file handler was returned. Previous implementation only keep one instance of psys node file handler. This patch address the issue by supporting multiple instances of file handler. Signed-off-by: Ong Hock Yu Tracked-On: OAM-64123 Tracked-On: OAM-64294 Tracked-On: OAM-64937 Tracked-On: OLINUX-2973 Tracked-On: OLINUX-3042 Change-Id: I7e528681ff2a8fcc8328c036d356984bfb2fb399 --- drivers/media/pci/intel/ipu-psys-virt.c | 39 ++++++++++++++++++- drivers/media/pci/intel/ipu-psys-virt.h | 1 + .../intel/virtio/intel-ipu4-para-virt-psys.c | 21 +++++++++- .../intel/virtio/intel-ipu4-para-virt-psys.h | 1 + .../intel/virtio/intel-ipu4-virtio-be-psys.c | 32 ++++++++------- .../intel/virtio/intel-ipu4-virtio-common.h | 1 + 6 files changed, 79 insertions(+), 16 deletions(-) diff --git a/drivers/media/pci/intel/ipu-psys-virt.c b/drivers/media/pci/intel/ipu-psys-virt.c index 877f57e0d781..76b616b9383a 100644 --- a/drivers/media/pci/intel/ipu-psys-virt.c +++ b/drivers/media/pci/intel/ipu-psys-virt.c @@ -499,7 +499,11 @@ int virt_ipu_psys_dqevent(struct ipu_psys_fh *fh, unsigned int f_flags) { struct ipu_psys_event *event; - int status = 0; + struct ipu_psys_kcmd *kcmd = NULL; + int status = 0, time_remain = -1; + DEFINE_WAIT_FUNC(wait, woken_wake_function); + + pr_debug("%s: IOC_DQEVENT", __func__); event = map_guest_phys(req_info->domid, req_info->request->payload, @@ -509,8 +513,39 @@ int virt_ipu_psys_dqevent(struct ipu_psys_fh *fh, return -EFAULT; } - status = ipu_ioctl_dqevent(event, fh, f_flags); + add_wait_queue(&fh->wait, &wait); + while (1) { + if (ipu_get_completed_kcmd(fh) || + time_remain == 0) + break; + time_remain = + wait_woken(&wait, TASK_INTERRUPTIBLE, POLL_WAIT); + } + remove_wait_queue(&fh->wait, &wait); + + if ((time_remain == 0) || (time_remain == -ERESTARTSYS)) { + pr_err("%s: poll timeout or unexpected wake up %d", + __func__, time_remain); + req_info->request->func_ret = 0; + goto error_exit; + } + + mutex_lock(&fh->mutex); + if (!kcmd) { + kcmd = __ipu_get_completed_kcmd(fh); + if (!kcmd) { + mutex_unlock(&fh->mutex); + return -ENODATA; + } + } + + *event = kcmd->ev; + ipu_psys_kcmd_free(kcmd); + mutex_unlock(&fh->mutex); + + req_info->request->func_ret = POLLIN; +error_exit: unmap_guest_phys(req_info->domid, req_info->request->payload); diff --git a/drivers/media/pci/intel/ipu-psys-virt.h b/drivers/media/pci/intel/ipu-psys-virt.h index 91a7bd32d035..6289207dd4bd 100644 --- a/drivers/media/pci/intel/ipu-psys-virt.h +++ b/drivers/media/pci/intel/ipu-psys-virt.h @@ -31,6 +31,7 @@ struct psys_fops_virt { long ipu_psys_unmapbuf(int fd, struct ipu_psys_fh *fh); //Function define in ipu4-psys.c void ipu_psys_kcmd_free(struct ipu_psys_kcmd *kcmd); +struct ipu_psys_kcmd *__ipu_get_completed_kcmd(struct ipu_psys_fh *fh); extern struct psys_fops_virt psys_vfops; diff --git a/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c b/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c index f85f22c0584d..d3a2801dde0f 100644 --- a/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c +++ b/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.c @@ -86,6 +86,8 @@ int ipu_get_manifest(struct ipu_psys_manifest *m, intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_GET_MANIFEST, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { @@ -133,6 +135,8 @@ int ipu_query_caps(struct ipu_psys_capability *caps, intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_QUERYCAP, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { @@ -209,6 +213,8 @@ int ipu_psys_kcmd_new(struct ipu_psys_command *cmd, intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_QCMD, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); @@ -417,6 +423,8 @@ int ipu_psys_getbuf(struct ipu_psys_buffer *buf, intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_GETBUF, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { @@ -466,6 +474,8 @@ int ipu_psys_unmapbuf(int fd, struct virt_ipu_psys_fh *fh) intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_UNMAPBUF, &op[0]); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { @@ -510,6 +520,8 @@ unsigned int virt_psys_poll(struct file *file, intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_POLL, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { @@ -545,6 +557,8 @@ long ipu_ioctl_dqevent(struct ipu_psys_event *event, intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_DQEVENT, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { @@ -670,7 +684,6 @@ static int virt_psys_open(struct inode *inode, struct file *file) hash_init(FD_BUF_HASH); fh->psys = psys; - file->private_data = fh; req = ipu4_virtio_fe_req_queue_get(); if (!req) { @@ -689,6 +702,10 @@ static int virt_psys_open(struct inode *inode, struct file *file) ipu4_virtio_fe_req_queue_put(req); return rval; } + + fh->be_fh = req->be_fh; + file->private_data = fh; + ipu4_virtio_fe_req_queue_put(req); return rval; @@ -713,6 +730,8 @@ static int virt_psys_release(struct inode *inode, struct file *file) intel_ipu4_virtio_create_req(req, IPU4_CMD_PSYS_CLOSE, NULL); + req->be_fh = fh->be_fh; + rval = fe_ctx->bknd_ops->send_req(fe_ctx->domid, req, true, IPU_VIRTIO_QUEUE_1); if (rval) { diff --git a/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.h b/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.h index 8de72c15b01c..8df029ad3730 100644 --- a/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.h +++ b/drivers/media/pci/intel/virtio/intel-ipu4-para-virt-psys.h @@ -29,6 +29,7 @@ struct virt_ipu_psys_fh { wait_queue_head_t wait; struct mutex bs_mutex; /* Protects buf_set field */ struct list_head buf_sets; + struct file *be_fh; }; int virt_psys_init(struct ipu4_virtio_ctx *fe_ctx); void virt_psys_exit(void); diff --git a/drivers/media/pci/intel/virtio/intel-ipu4-virtio-be-psys.c b/drivers/media/pci/intel/virtio/intel-ipu4-virtio-be-psys.c index c69e48c76397..957d51b2198b 100644 --- a/drivers/media/pci/intel/virtio/intel-ipu4-virtio-be-psys.c +++ b/drivers/media/pci/intel/virtio/intel-ipu4-virtio-be-psys.c @@ -12,8 +12,6 @@ #include "intel-ipu4-virtio-be-request-queue.h" #include "intel-ipu4-virtio-be.h" -struct file *psys_file; - int process_psys_mapbuf(struct ipu4_virtio_req_info *req_info) { return IPU4_REQ_ERROR; @@ -21,9 +19,14 @@ int process_psys_mapbuf(struct ipu4_virtio_req_info *req_info) int process_psys_unmapbuf(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; int status = 0; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; + if(!fh) { + pr_err("%s NULL file handler", __func__); + return IPU4_REQ_ERROR; + } + status = fh->vfops->unmap_buf(fh, req_info); /*Only doing this in mediated mode because @@ -40,7 +43,7 @@ int process_psys_unmapbuf(struct ipu4_virtio_req_info *req_info) int process_psys_querycap(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; int status = 0; struct ipu_psys_capability *psys_caps; @@ -73,7 +76,7 @@ int process_psys_putbuf(struct ipu4_virtio_req_info *req_info) int process_psys_qcmd(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; int status = 0; status = fh->vfops->qcmd(fh, req_info); @@ -88,10 +91,10 @@ int process_psys_qcmd(struct ipu4_virtio_req_info *req_info) int process_psys_dqevent(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; int status = 0; - status = fh->vfops->dqevent(fh, req_info, psys_file->f_flags); + status = fh->vfops->dqevent(fh, req_info, req_info->request->be_fh->f_flags); req_info->request->func_ret = status; @@ -103,7 +106,7 @@ int process_psys_dqevent(struct ipu4_virtio_req_info *req_info) int process_psys_getbuf(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; int status = 0; status = fh->vfops->get_buf(fh, req_info); @@ -118,7 +121,7 @@ int process_psys_getbuf(struct ipu4_virtio_req_info *req_info) int process_psys_get_manifest(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; int status = 0; status = fh->vfops->get_manifest(fh, req_info); @@ -133,16 +136,19 @@ int process_psys_get_manifest(struct ipu4_virtio_req_info *req_info) int process_psys_open(struct ipu4_virtio_req_info *req_info) { + struct file *fh; pr_info("%s: /dev/ipu-psys0", __func__); - psys_file = filp_open("/dev/ipu-psys0", req_info->request->op[0], 0); + fh = filp_open("/dev/ipu-psys0", req_info->request->op[0], 0); - if (psys_file == NULL) { + if (fh == NULL) { pr_err("%s: Native IPU psys device not found", __func__); return IPU4_REQ_ERROR; } + req_info->request->be_fh = fh; + return IPU4_REQ_PROCESSED; } @@ -150,14 +156,14 @@ int process_psys_close(struct ipu4_virtio_req_info *req_info) { pr_info("%s: /dev/ipu-psys0", __func__); - filp_close(psys_file, 0); + filp_close(req_info->request->be_fh, 0); return IPU4_REQ_PROCESSED; } int process_psys_poll(struct ipu4_virtio_req_info *req_info) { - struct ipu_psys_fh *fh = psys_file->private_data; + struct ipu_psys_fh *fh = req_info->request->be_fh->private_data; int status = 0; status = fh->vfops->poll(fh, req_info); diff --git a/drivers/media/pci/intel/virtio/intel-ipu4-virtio-common.h b/drivers/media/pci/intel/virtio/intel-ipu4-virtio-common.h index 1909e026ff1e..3edab4270da0 100644 --- a/drivers/media/pci/intel/virtio/intel-ipu4-virtio-common.h +++ b/drivers/media/pci/intel/virtio/intel-ipu4-virtio-common.h @@ -37,6 +37,7 @@ struct ipu4_virtio_req { wait_queue_head_t *wait; bool completed; u64 payload; + struct file *be_fh; }; struct test_payload { unsigned int data1; -- https://clearlinux.org