From: Ekansh Gupta <[email protected]>

A buffer mapped for the DSP stays mapped until it is explicitly
unmapped, so user space needs a way to take a mapping down once it is
no longer needed.

Add an ioctl that removes a mapping, naming it by the address that map
returned. As with map there are two flavours, selected by the request:
one matching the plain mapping and one matching the attribute-based
mapping, which also carries the DSP-side buffer identifier.

The buffer itself is kept alive by the handle it was created or
imported under, so unmapping does not touch it; the mapping and the
buffer have independent lifetimes and user space is expected to keep
the handle open for as long as the DSP uses the mapping.

Signed-off-by: Ekansh Gupta <[email protected]>
---
 drivers/accel/qda/qda_drv.c     |  1 +
 drivers/accel/qda/qda_fastrpc.c | 73 +++++++++++++++++++++++++++++++++++++++++
 drivers/accel/qda/qda_fastrpc.h | 32 ++++++++++++++++++
 drivers/accel/qda/qda_ioctl.c   | 24 ++++++++++++++
 drivers/accel/qda/qda_ioctl.h   |  1 +
 include/uapi/drm/qda_accel.h    | 30 +++++++++++++++++
 6 files changed, 161 insertions(+)

diff --git a/drivers/accel/qda/qda_drv.c b/drivers/accel/qda/qda_drv.c
index 7f19380701d9..c5b41b869692 100644
--- a/drivers/accel/qda/qda_drv.c
+++ b/drivers/accel/qda/qda_drv.c
@@ -126,6 +126,7 @@ static const struct drm_ioctl_desc qda_ioctls[] = {
        DRM_IOCTL_DEF_DRV(QDA_REMOTE_INVOKE, qda_ioctl_invoke, 0),
        DRM_IOCTL_DEF_DRV(QDA_REMOTE_SESSION_CREATE, qda_ioctl_init_create, 0),
        DRM_IOCTL_DEF_DRV(QDA_REMOTE_MMAP, qda_ioctl_mmap, 0),
+       DRM_IOCTL_DEF_DRV(QDA_REMOTE_MUNMAP, qda_ioctl_munmap, 0),
 };
 
 static const struct drm_driver qda_drm_driver = {
diff --git a/drivers/accel/qda/qda_fastrpc.c b/drivers/accel/qda/qda_fastrpc.c
index 744d7317cbe1..dbd14cd07cb2 100644
--- a/drivers/accel/qda/qda_fastrpc.c
+++ b/drivers/accel/qda/qda_fastrpc.c
@@ -1072,6 +1072,73 @@ static int qda_fastrpc_prepare_args_mem_map(struct 
qda_fastrpc_invoke_ctx *ctx,
        return err;
 }
 
+/*
+ * INIT_MUNMAP packed layout:
+ *   [0] req   sizeof(qda_fastrpc_munmap_req_msg)      IN
+ */
+static int qda_fastrpc_prepare_args_munmap(struct qda_fastrpc_invoke_ctx *ctx, 
void *argp)
+{
+       struct drm_qda_mem_unmap *uargs = argp;
+       struct qda_fastrpc_munmap_req_msg *req;
+       struct qda_gem_obj *kernel_gem;
+       int err;
+
+       ctx->sc = QDA_FASTRPC_SCALARS(QDA_FASTRPC_RMID_INIT_MUNMAP, 1, 0);
+       ctx->handle = QDA_FASTRPC_INIT_HANDLE;
+
+       err = alloc_kernel_args(ctx, 1);
+       if (err)
+               return err;
+
+       kernel_gem = alloc_kernel_gem(ctx, sizeof(*req));
+       if (IS_ERR(kernel_gem))
+               return PTR_ERR(kernel_gem);
+
+       req = kernel_gem->virt;
+       req->remote_session_id = ctx->session->remote_session_id;
+       req->vaddr = uargs->vaddrout;
+       req->size = uargs->size;
+
+       assign_kernel_gem_arg(ctx, 0, kernel_gem, req, sizeof(*req));
+       drm_gem_object_put(&kernel_gem->base);
+
+       return 0;
+}
+
+/*
+ * INIT_MEM_UNMAP packed layout:
+ *   [0] req   sizeof(qda_fastrpc_mem_unmap_req_msg)   IN
+ */
+static int qda_fastrpc_prepare_args_mem_unmap(struct qda_fastrpc_invoke_ctx 
*ctx, void *argp)
+{
+       struct drm_qda_mem_unmap *uargs = argp;
+       struct qda_fastrpc_mem_unmap_req_msg *req;
+       struct qda_gem_obj *kernel_gem;
+       int err;
+
+       ctx->sc = QDA_FASTRPC_SCALARS(QDA_FASTRPC_RMID_INIT_MEM_UNMAP, 1, 0);
+       ctx->handle = QDA_FASTRPC_INIT_HANDLE;
+
+       err = alloc_kernel_args(ctx, 1);
+       if (err)
+               return err;
+
+       kernel_gem = alloc_kernel_gem(ctx, sizeof(*req));
+       if (IS_ERR(kernel_gem))
+               return PTR_ERR(kernel_gem);
+
+       req = kernel_gem->virt;
+       req->remote_session_id = ctx->session->remote_session_id;
+       req->handle = uargs->dsp_handle;
+       req->vaddrin = uargs->vaddr;
+       req->len = uargs->size;
+
+       assign_kernel_gem_arg(ctx, 0, kernel_gem, req, sizeof(*req));
+       drm_gem_object_put(&kernel_gem->base);
+
+       return 0;
+}
+
 /*
  * INVOKE_DYNAMIC: the argument descriptors are supplied by user space, which
  * is also responsible for having imported every buffer to a GEM handle.
@@ -1141,6 +1208,12 @@ int qda_fastrpc_prepare_args(struct 
qda_fastrpc_invoke_ctx *ctx,
        case QDA_FASTRPC_RMID_INIT_MEM_MAP:
                err = qda_fastrpc_prepare_args_mem_map(ctx, argp);
                break;
+       case QDA_FASTRPC_RMID_INIT_MUNMAP:
+               err = qda_fastrpc_prepare_args_munmap(ctx, argp);
+               break;
+       case QDA_FASTRPC_RMID_INIT_MEM_UNMAP:
+               err = qda_fastrpc_prepare_args_mem_unmap(ctx, argp);
+               break;
        case QDA_FASTRPC_RMID_INVOKE_DYNAMIC:
                err = qda_fastrpc_prepare_args_invoke(ctx, argp);
                break;
diff --git a/drivers/accel/qda/qda_fastrpc.h b/drivers/accel/qda/qda_fastrpc.h
index 1bd696baa95c..889b41dc20b0 100644
--- a/drivers/accel/qda/qda_fastrpc.h
+++ b/drivers/accel/qda/qda_fastrpc.h
@@ -46,9 +46,11 @@ struct qda_session;
 /* Methods of the initialisation handle */
 #define QDA_FASTRPC_RMID_INIT_RELEASE          1
 #define QDA_FASTRPC_RMID_INIT_MMAP             4
+#define QDA_FASTRPC_RMID_INIT_MUNMAP           5
 #define QDA_FASTRPC_RMID_INIT_CREATE           6
 #define QDA_FASTRPC_RMID_INIT_CREATE_ATTR      7
 #define QDA_FASTRPC_RMID_INIT_MEM_MAP          10
+#define QDA_FASTRPC_RMID_INIT_MEM_UNMAP                11
 #define QDA_FASTRPC_RMID_INVOKE_DYNAMIC                0xFFFFFFFFU
 
 /* Handle the initialisation methods are addressed to */
@@ -197,6 +199,36 @@ struct qda_fastrpc_map_rsp_msg {
        u64 vaddrout;
 };
 
+/**
+ * struct qda_fastrpc_munmap_req_msg - Request to remove a plain mapping
+ *
+ * Layout the DSP expects; do not reorder.
+ */
+struct qda_fastrpc_munmap_req_msg {
+       /** @remote_session_id: Session the mapping belongs to */
+       s32 remote_session_id;
+       /** @vaddr: Address the mapping was made at */
+       u64 vaddr;
+       /** @size: Length of the mapping in bytes */
+       u64 size;
+};
+
+/**
+ * struct qda_fastrpc_mem_unmap_req_msg - Request to remove an attribute-based 
mapping
+ *
+ * Layout the DSP expects; do not reorder.
+ */
+struct qda_fastrpc_mem_unmap_req_msg {
+       /** @remote_session_id: Session the mapping belongs to */
+       s32 remote_session_id;
+       /** @handle: Identifier the DSP tracks the buffer by */
+       s32 handle;
+       /** @vaddrin: Address the mapping was made at */
+       u64 vaddrin;
+       /** @len: Length of the mapping in bytes */
+       u64 len;
+};
+
 /**
  * struct qda_fastrpc_msg - FastRPC wire message for remote invocations
  *
diff --git a/drivers/accel/qda/qda_ioctl.c b/drivers/accel/qda/qda_ioctl.c
index cd3cea72f50e..17d1b488b4a9 100644
--- a/drivers/accel/qda/qda_ioctl.c
+++ b/drivers/accel/qda/qda_ioctl.c
@@ -197,6 +197,30 @@ int qda_ioctl_mmap(struct drm_device *dev, void *data, 
struct drm_file *file_pri
        }
 }
 
+/**
+ * qda_ioctl_munmap() - Remove a buffer's mapping from the DSP's address space
+ * @dev: DRM device structure
+ * @data: User-space data (struct drm_qda_mem_unmap)
+ * @file_priv: DRM file private data
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int qda_ioctl_munmap(struct drm_device *dev, void *data, struct drm_file 
*file_priv)
+{
+       struct drm_qda_mem_unmap *unmap_req = data;
+
+       switch (unmap_req->request) {
+       case QDA_REQUEST_MUNMAP:
+               return qda_fastrpc_invoke(QDA_FASTRPC_RMID_INIT_MUNMAP, data,
+                                         file_priv->driver_priv);
+       case QDA_REQUEST_MEM_UNMAP:
+               return qda_fastrpc_invoke(QDA_FASTRPC_RMID_INIT_MEM_UNMAP, data,
+                                         file_priv->driver_priv);
+       default:
+               return -EINVAL;
+       }
+}
+
 /**
  * qda_ioctl_invoke() - Run a method on the DSP
  * @dev: DRM device structure
diff --git a/drivers/accel/qda/qda_ioctl.h b/drivers/accel/qda/qda_ioctl.h
index afb3ed0e132e..9c053349c3fa 100644
--- a/drivers/accel/qda/qda_ioctl.h
+++ b/drivers/accel/qda/qda_ioctl.h
@@ -16,6 +16,7 @@ int qda_ioctl_gem_mmap_offset(struct drm_device *dev, void 
*data, struct drm_fil
 int qda_ioctl_invoke(struct drm_device *dev, void *data, struct drm_file 
*file_priv);
 int qda_ioctl_init_create(struct drm_device *dev, void *data, struct drm_file 
*file_priv);
 int qda_ioctl_mmap(struct drm_device *dev, void *data, struct drm_file 
*file_priv);
+int qda_ioctl_munmap(struct drm_device *dev, void *data, struct drm_file 
*file_priv);
 int qda_session_init_create(struct qda_session *session, struct 
qda_init_create_args *create);
 
 #endif /* __QDA_IOCTL_H__ */
diff --git a/include/uapi/drm/qda_accel.h b/include/uapi/drm/qda_accel.h
index bd2d0f4308b1..43598ddef461 100644
--- a/include/uapi/drm/qda_accel.h
+++ b/include/uapi/drm/qda_accel.h
@@ -18,6 +18,7 @@ extern "C" {
 #define DRM_QDA_REMOTE_INVOKE          0x03
 #define DRM_QDA_REMOTE_SESSION_CREATE  0x04
 #define DRM_QDA_REMOTE_MMAP            0x05
+#define DRM_QDA_REMOTE_MUNMAP          0x06
 
 #define DRM_IOCTL_QDA_QUERY            DRM_IOWR(DRM_COMMAND_BASE + 
DRM_QDA_QUERY, \
                                         struct drm_qda_query)
@@ -32,11 +33,17 @@ extern "C" {
                 struct drm_qda_init_create)
 #define DRM_IOCTL_QDA_REMOTE_MMAP      DRM_IOWR(DRM_COMMAND_BASE + 
DRM_QDA_REMOTE_MMAP, \
                                         struct drm_qda_mem_map)
+#define DRM_IOCTL_QDA_REMOTE_MUNMAP    DRM_IOWR(DRM_COMMAND_BASE + 
DRM_QDA_REMOTE_MUNMAP, \
+                                        struct drm_qda_mem_unmap)
 
 /* Request types for drm_qda_mem_map.request */
 #define QDA_REQUEST_MMAP       1       /* Map a whole buffer */
 #define QDA_REQUEST_MEM_MAP    2       /* Map a region of a buffer, with 
attributes */
 
+/* Request types for drm_qda_mem_unmap.request */
+#define QDA_REQUEST_MUNMAP     1
+#define QDA_REQUEST_MEM_UNMAP  2
+
 /* Query type definitions for drm_qda_query */
 #define QDA_QUERY_DSP_NAME             1
 
@@ -173,6 +180,29 @@ struct drm_qda_mem_map {
        __u64 vaddrout;
 };
 
+/**
+ * struct drm_qda_mem_unmap - Parameters for removing a DSP mapping
+ * @request: QDA_REQUEST_MUNMAP or QDA_REQUEST_MEM_UNMAP
+ * @dsp_handle: Identifier the DSP tracks the buffer by (QDA_REQUEST_MEM_UNMAP)
+ * @vaddr: Address the mapping was made at (QDA_REQUEST_MEM_UNMAP)
+ * @vaddrout: Address the mapping was made at (QDA_REQUEST_MUNMAP)
+ * @size: Length of the mapping in bytes
+ *
+ * Removes a mapping made with DRM_IOCTL_QDA_REMOTE_MMAP, named by the address
+ * that call returned in drm_qda_mem_map.vaddrout. The request must match the
+ * one the mapping was made with: QDA_REQUEST_MUNMAP uses @vaddrout and @size,
+ * QDA_REQUEST_MEM_UNMAP uses @dsp_handle, @vaddr and @size. The buffer is not
+ * affected, so its handle must stay open for as long as the DSP uses the
+ * mapping.
+ */
+struct drm_qda_mem_unmap {
+       __u32 request;
+       __s32 dsp_handle;
+       __u64 vaddr;
+       __u64 vaddrout;
+       __u64 size;
+};
+
 #if defined(__cplusplus)
 }
 #endif

-- 
2.34.1

Reply via email to