[PATCH 15/15] accel/qda: Add remote memory unmap from DSP address space
From: Ekansh Gupta via B4 Relay
Date: Tue May 19 2026 - 02:28:56 EST
From: Ekansh Gupta <ekansh.gupta@xxxxxxxxxxxxxxxx>
Implement DRM_IOCTL_QDA_REMOTE_MUNMAP (command 0x06), which unmaps
a previously mapped memory region from the DSP's virtual address space.
Two unmap modes mirror the two map modes:
QDA_MUNMAP_REQUEST_LEGACY (FASTRPC_RMID_INIT_MUNMAP)
Legacy single-argument unmap: sends a fastrpc_munmap_req_msg
containing the session ID, the DSP virtual address (vaddrout from
the original map response), and the region size.
QDA_MUNMAP_REQUEST_ATTR (FASTRPC_RMID_INIT_MEM_UNMAP)
Attribute-based unmap: sends a fastrpc_mem_unmap_req_msg which
additionally carries the original DMA-BUF fd and virtual address,
matching the fd-based MEM_MAP path.
DRM_QDA_REMOTE_MUNMAP is assigned command number 0x06, filling the
slot that was previously reserved for this purpose.
Assisted-by: Claude:claude-4-6-sonnet
Signed-off-by: Ekansh Gupta <ekansh.gupta@xxxxxxxxxxxxxxxx>
---
drivers/accel/qda/qda_drv.c | 1 +
drivers/accel/qda/qda_fastrpc.c | 84 +++++++++++++++++++++++++++++++++++++++++
drivers/accel/qda/qda_fastrpc.h | 34 +++++++++++++++++
drivers/accel/qda/qda_ioctl.c | 28 ++++++++++++++
drivers/accel/qda/qda_ioctl.h | 1 +
include/uapi/drm/qda_accel.h | 36 +++++++++++++++++-
6 files changed, 183 insertions(+), 1 deletion(-)
diff --git a/drivers/accel/qda/qda_drv.c b/drivers/accel/qda/qda_drv.c
index 3640e4a41605..41cc207447b4 100644
--- a/drivers/accel/qda/qda_drv.c
+++ b/drivers/accel/qda/qda_drv.c
@@ -68,6 +68,7 @@ static const struct drm_ioctl_desc qda_ioctls[] = {
DRM_IOCTL_DEF_DRV(QDA_GEM_MMAP_OFFSET, qda_ioctl_gem_mmap_offset, 0),
DRM_IOCTL_DEF_DRV(QDA_REMOTE_SESSION_CREATE, qda_ioctl_init_create, 0),
DRM_IOCTL_DEF_DRV(QDA_REMOTE_MAP, qda_ioctl_mmap, 0),
+ DRM_IOCTL_DEF_DRV(QDA_REMOTE_MUNMAP, qda_ioctl_munmap, 0),
DRM_IOCTL_DEF_DRV(QDA_REMOTE_INVOKE, qda_ioctl_invoke, 0),
};
diff --git a/drivers/accel/qda/qda_fastrpc.c b/drivers/accel/qda/qda_fastrpc.c
index cab3a560ceb5..0513beede428 100644
--- a/drivers/accel/qda/qda_fastrpc.c
+++ b/drivers/accel/qda/qda_fastrpc.c
@@ -887,6 +887,84 @@ static int fastrpc_prepare_args_mem_map_attr(struct fastrpc_invoke_context *ctx,
return err;
}
+static int fastrpc_prepare_args_munmap(struct fastrpc_invoke_context *ctx, char __user *argp)
+{
+ struct drm_qda_fastrpc_invoke_args *args;
+ struct fastrpc_munmap_req_msg *req_msg;
+ struct drm_qda_mem_unmap uargs;
+ void *req;
+ int err;
+
+ memcpy(&uargs, argp, sizeof(uargs));
+
+ args = kzalloc_obj(*args);
+ if (!args)
+ return -ENOMEM;
+
+ req = kzalloc_obj(*req_msg);
+ if (!req) {
+ err = -ENOMEM;
+ goto err_free_args;
+ }
+ req_msg = (struct fastrpc_munmap_req_msg *)req;
+
+ req_msg->remote_session_id = ctx->remote_session_id;
+ req_msg->size = uargs.size;
+ req_msg->vaddr = uargs.vaddrout;
+
+ setup_single_arg(args, req_msg, sizeof(*req_msg));
+ ctx->sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MUNMAP, 1, 0);
+ ctx->args = args;
+ ctx->req = req;
+ ctx->handle = FASTRPC_INIT_HANDLE;
+
+ return 0;
+
+err_free_args:
+ kfree(args);
+ return err;
+}
+
+static int fastrpc_prepare_args_mem_unmap_attr(struct fastrpc_invoke_context *ctx,
+ char __user *argp)
+{
+ struct drm_qda_fastrpc_invoke_args *args;
+ struct fastrpc_mem_unmap_req_msg *req_msg;
+ struct drm_qda_mem_unmap uargs;
+ void *req;
+ int err;
+
+ memcpy(&uargs, argp, sizeof(uargs));
+
+ args = kzalloc_obj(*args);
+ if (!args)
+ return -ENOMEM;
+
+ req = kzalloc_obj(*req_msg);
+ if (!req) {
+ err = -ENOMEM;
+ goto err_free_args;
+ }
+ req_msg = (struct fastrpc_mem_unmap_req_msg *)req;
+
+ req_msg->remote_session_id = ctx->remote_session_id;
+ req_msg->fd = uargs.fd; /* DMA-BUF fd forwarded to DSP */
+ req_msg->vaddrin = uargs.vaddr;
+ req_msg->len = uargs.size;
+
+ setup_single_arg(args, req_msg, sizeof(*req_msg));
+ ctx->sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_UNMAP, 1, 0);
+ ctx->args = args;
+ ctx->req = req;
+ ctx->handle = FASTRPC_INIT_HANDLE;
+
+ return 0;
+
+err_free_args:
+ kfree(args);
+ return err;
+}
+
static int fastrpc_prepare_args_invoke(struct fastrpc_invoke_context *ctx, char __user *argp)
{
struct drm_qda_invoke_args invoke_args;
@@ -945,6 +1023,12 @@ int qda_fastrpc_prepare_args(struct fastrpc_invoke_context *ctx, char __user *ar
case FASTRPC_RMID_INIT_MEM_MAP:
err = fastrpc_prepare_args_mem_map_attr(ctx, argp);
break;
+ case FASTRPC_RMID_INIT_MUNMAP:
+ err = fastrpc_prepare_args_munmap(ctx, argp);
+ break;
+ case FASTRPC_RMID_INIT_MEM_UNMAP:
+ err = fastrpc_prepare_args_mem_unmap_attr(ctx, argp);
+ break;
case FASTRPC_RMID_INVOKE_DYNAMIC:
err = fastrpc_prepare_args_invoke(ctx, argp);
break;
diff --git a/drivers/accel/qda/qda_fastrpc.h b/drivers/accel/qda/qda_fastrpc.h
index 71812eaf9a54..030e9b954f7a 100644
--- a/drivers/accel/qda/qda_fastrpc.h
+++ b/drivers/accel/qda/qda_fastrpc.h
@@ -275,9 +275,11 @@ struct fastrpc_invoke_context {
/* Remote Method ID table - identifies initialization and control operations */
#define FASTRPC_RMID_INIT_RELEASE 1 /* Release DSP process */
#define FASTRPC_RMID_INIT_MMAP 4 /* Map memory region to DSP */
+#define FASTRPC_RMID_INIT_MUNMAP 5 /* Unmap DSP memory region */
#define FASTRPC_RMID_INIT_CREATE 6 /* Create DSP process */
#define FASTRPC_RMID_INIT_CREATE_ATTR 7 /* Create DSP process with attributes */
#define FASTRPC_RMID_INIT_MEM_MAP 10 /* Map DMA buffer with attributes to DSP */
+#define FASTRPC_RMID_INIT_MEM_UNMAP 11 /* Unmap DMA buffer from DSP */
#define FASTRPC_RMID_INVOKE_DYNAMIC 0xFFFFFFFF /* Dynamic method invocation */
/* Common handle for initialization operations */
@@ -345,6 +347,38 @@ struct fastrpc_map_rsp_msg {
u64 vaddrout;
};
+/**
+ * struct fastrpc_mem_unmap_req_msg - Memory unmap request message with attributes
+ *
+ * This message structure is sent to the DSP to request unmapping
+ * of a previously mapped memory region (ATTR request).
+ */
+struct fastrpc_mem_unmap_req_msg {
+ /** @remote_session_id: Client identifier for the session */
+ s32 remote_session_id;
+ /** @fd: DMA-BUF file descriptor of the buffer to unmap */
+ s32 fd;
+ /** @vaddrin: DSP virtual address of the mapped region to unmap */
+ u64 vaddrin;
+ /** @len: Size of the region to unmap in bytes */
+ u64 len;
+};
+
+/**
+ * struct fastrpc_munmap_req_msg - Legacy memory unmap request message
+ *
+ * This message structure is sent to the DSP to request unmapping
+ * of a previously mapped memory region.
+ */
+struct fastrpc_munmap_req_msg {
+ /** @remote_session_id: Client identifier for the session */
+ s32 remote_session_id;
+ /** @vaddr: DSP virtual address of the mapped region to unmap */
+ u64 vaddr;
+ /** @size: Size of the region to unmap in bytes */
+ u64 size;
+};
+
void qda_fastrpc_context_free(struct kref *ref);
struct fastrpc_invoke_context *qda_fastrpc_context_alloc(void);
int qda_fastrpc_prepare_args(struct fastrpc_invoke_context *ctx, char __user *argp);
diff --git a/drivers/accel/qda/qda_ioctl.c b/drivers/accel/qda/qda_ioctl.c
index 283eb7535c45..aeba6190182e 100644
--- a/drivers/accel/qda/qda_ioctl.c
+++ b/drivers/accel/qda/qda_ioctl.c
@@ -254,6 +254,34 @@ int qda_ioctl_mmap(struct drm_device *dev, void *data, struct drm_file *file_pri
}
}
+/**
+ * qda_ioctl_munmap() - Unmap memory from DSP 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;
+
+ if (!data)
+ return -EINVAL;
+
+ unmap_req = (struct drm_qda_mem_unmap *)data;
+
+ switch (unmap_req->request) {
+ case QDA_MUNMAP_REQUEST_LEGACY:
+ return fastrpc_invoke(FASTRPC_RMID_INIT_MUNMAP, dev, data, file_priv);
+ case QDA_MUNMAP_REQUEST_ATTR:
+ return fastrpc_invoke(FASTRPC_RMID_INIT_MEM_UNMAP, dev, data, file_priv);
+ default:
+ drm_err(dev, "Invalid munmap request type: %u\n", unmap_req->request);
+ return -EINVAL;
+ }
+}
+
/**
* qda_ioctl_invoke() - Perform a dynamic FastRPC method invocation
* @dev: DRM device structure
diff --git a/drivers/accel/qda/qda_ioctl.h b/drivers/accel/qda/qda_ioctl.h
index 457ceccede08..e14a39050d09 100644
--- a/drivers/accel/qda/qda_ioctl.h
+++ b/drivers/accel/qda/qda_ioctl.h
@@ -14,5 +14,6 @@ int qda_ioctl_gem_create(struct drm_device *dev, void *data, struct drm_file *fi
int qda_ioctl_gem_mmap_offset(struct drm_device *dev, void *data, struct drm_file *file_priv);
int qda_ioctl_invoke(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);
#endif /* __QDA_IOCTL_H__ */
diff --git a/include/uapi/drm/qda_accel.h b/include/uapi/drm/qda_accel.h
index 173f59abd361..e3b5c9a963bf 100644
--- a/include/uapi/drm/qda_accel.h
+++ b/include/uapi/drm/qda_accel.h
@@ -21,9 +21,10 @@ extern "C" {
#define DRM_QDA_QUERY 0x00
#define DRM_QDA_GEM_CREATE 0x01
#define DRM_QDA_GEM_MMAP_OFFSET 0x02
-/* Command number 0x03 reserved for INIT_ATTACH; 0x06 reserved for MUNMAP */
+/* Command number 0x03 reserved for INIT_ATTACH */
#define DRM_QDA_REMOTE_SESSION_CREATE 0x04
#define DRM_QDA_REMOTE_MAP 0x05
+#define DRM_QDA_REMOTE_MUNMAP 0x06
#define DRM_QDA_REMOTE_INVOKE 0x07
/*
@@ -44,6 +45,8 @@ extern "C" {
struct drm_qda_init_create)
#define DRM_IOCTL_QDA_REMOTE_MAP DRM_IOWR(DRM_COMMAND_BASE + DRM_QDA_REMOTE_MAP, \
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)
#define DRM_IOCTL_QDA_REMOTE_INVOKE DRM_IOWR(DRM_COMMAND_BASE + DRM_QDA_REMOTE_INVOKE, \
struct drm_qda_invoke_args)
@@ -51,6 +54,10 @@ extern "C" {
#define QDA_MAP_REQUEST_LEGACY 1 /* Legacy MMAP operation */
#define QDA_MAP_REQUEST_ATTR 2 /* Handle-based MEM_MAP operation with attributes */
+/* Request type definitions for qda_mem_unmap */
+#define QDA_MUNMAP_REQUEST_LEGACY 1 /* Legacy MUNMAP operation */
+#define QDA_MUNMAP_REQUEST_ATTR 2 /* Handle-based MEM_UNMAP operation */
+
/**
* struct drm_qda_query - Device information query structure
* @dsp_name: Name of DSP (e.g., "adsp", "cdsp", "cdsp1", "gdsp0", "gdsp1")
@@ -188,6 +195,33 @@ struct drm_qda_mem_map {
__u64 vaddrout;
};
+/**
+ * struct drm_qda_mem_unmap - Memory unmapping request structure
+ * @request: Request type (QDA_MUNMAP_REQUEST_LEGACY or QDA_MUNMAP_REQUEST_ATTR)
+ * @fd: DMA-BUF file descriptor (used for ATTR request)
+ * @vaddr: Virtual address (used for ATTR request)
+ * @vaddrout: DSP virtual address (used for LEGACY request)
+ * @size: Size of the memory region to unmap in bytes
+ *
+ * This structure is used to request unmapping of a previously mapped
+ * memory region from the DSP's virtual address space.
+ *
+ * For QDA_MUNMAP_REQUEST_LEGACY (value 1):
+ * - Uses fields: vaddrout, size
+ * - Legacy MUNMAP operation for backward compatibility
+ *
+ * For QDA_MUNMAP_REQUEST_ATTR (value 2):
+ * - Uses fields: fd, vaddr, size
+ * - Handle-based MEM_UNMAP operation
+ */
+struct drm_qda_mem_unmap {
+ __u32 request;
+ __s32 fd;
+ __u64 vaddr;
+ __u64 vaddrout;
+ __u64 size;
+};
+
#if defined(__cplusplus)
}
#endif
--
2.34.1