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
