[PATCH char-misc-next 3/4] issei: host_client: add dma allocation support

From: Alexander Usyskin

Date: Thu Oct 15 2026 - 01:31:53 EST


Add functions to allow dedicated DMA buffer allocated on current
hardware device per host client.

Signed-off-by: Alexander Usyskin <alexander.usyskin@xxxxxxxxx>
---
drivers/misc/issei/host_client.c | 66 ++++++++++++++++++++++++++++++++++++++++
drivers/misc/issei/host_client.h | 12 ++++++++
drivers/misc/issei/issei_dev.h | 3 ++
3 files changed, 81 insertions(+)

diff --git a/drivers/misc/issei/host_client.c b/drivers/misc/issei/host_client.c
index d16b5835c619..751296e3dc25 100644
--- a/drivers/misc/issei/host_client.c
+++ b/drivers/misc/issei/host_client.c
@@ -2,6 +2,7 @@
/* Copyright (C) 2023-2026 Intel Corporation */
#include <linux/cleanup.h>
#include <linux/dev_printk.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/kobject.h>
@@ -112,6 +113,17 @@ static void __issei_cl_disconnect(struct issei_device *idev, struct issei_host_c
cl_dbg(idev, cl, "Disconnected\n");
}

+static void __issei_cl_dma_unmap(struct issei_host_client *cl)
+{
+ if (!cl->dma_size)
+ return;
+
+ dma_free_coherent(cl->idev->parent, cl->dma_size, cl->dma_vaddr, cl->dma_daddr);
+ cl->dma_size = 0;
+ cl->dma_vaddr = NULL;
+ cl->dma_daddr = 0;
+}
+
static void __issei_cl_init(struct issei_host_client *cl, struct issei_device *idev,
u16 id, struct file *fp)
{
@@ -185,6 +197,8 @@ void issei_cl_remove(struct issei_host_client *cl)

__issei_cl_disconnect(idev, cl);

+ __issei_cl_dma_unmap(cl);
+
cl_dbg(idev, cl, "Removed\n");
kfree(cl);
}
@@ -521,3 +535,55 @@ void issei_cl_clean_all_wbuf(struct issei_host_client *cl)

__issei_cl_clean_all_wbuf(idev, cl);
}
+
+/**
+ * issei_cl_dma_map - allocate DMA mapping for client
+ *
+ * @cl: host client
+ * @size: memory size to allocate
+ * @daddr: pointer for buffer DMA address
+ * @vaddr: pointer for buffer virtual address
+ *
+ * Return: 0 on success, < 0 on error
+ */
+int issei_cl_dma_map(struct issei_host_client *cl, size_t size,
+ dma_addr_t *daddr, void **vaddr)
+{
+ struct issei_device *idev = cl->idev;
+
+ if (size == 0 || size > ISSEI_HOST_DMA_MAX_SIZE) {
+ cl_err(idev, cl, "The size is out of bounds.\n");
+ return -EINVAL;
+ }
+
+ guard(mutex)(&idev->client_lock);
+
+ if (cl->dma_size) {
+ cl_err(idev, cl, "DMA already allocated.\n");
+ return -EALREADY;
+ }
+
+ cl->dma_vaddr = dma_alloc_coherent(cl->idev->parent, size, &cl->dma_daddr, GFP_KERNEL);
+ if (!cl->dma_vaddr)
+ return -ENOMEM;
+
+ cl->dma_size = size;
+
+ *daddr = cl->dma_daddr;
+ *vaddr = cl->dma_vaddr;
+ return 0;
+}
+
+/**
+ * issei_cl_dma_unmap - deallocate DMA mapping for client
+ *
+ * @cl: host client
+ */
+void issei_cl_dma_unmap(struct issei_host_client *cl)
+{
+ struct issei_device *idev = cl->idev;
+
+ guard(mutex)(&idev->client_lock);
+
+ __issei_cl_dma_unmap(cl);
+}
diff --git a/drivers/misc/issei/host_client.h b/drivers/misc/issei/host_client.h
index 05e2f4ade9c3..987cee609676 100644
--- a/drivers/misc/issei/host_client.h
+++ b/drivers/misc/issei/host_client.h
@@ -38,6 +38,10 @@ enum issei_host_client_state {
* @read_wait: waitqueue for read object
* @read_data: received data pointer
* @read_data_size: received data size
+ *
+ * @dma_vaddr: allocated DMA buffer virtual address
+ * @dma_daddr: allocated DMA buffer DMA address
+ * @dma_size: allocated DMA buffer size, zero if no buffer allocated
*/
struct issei_host_client {
struct list_head list;
@@ -54,6 +58,10 @@ struct issei_host_client {
wait_queue_head_t read_wait;
u8 *read_data;
size_t read_data_size;
+
+ void *dma_vaddr;
+ dma_addr_t dma_daddr;
+ size_t dma_size;
};

struct issei_host_client *issei_cl_create(struct issei_device *idev, struct file *fp);
@@ -72,4 +80,8 @@ int issei_cl_check_read(struct issei_host_client *cl);
int issei_cl_check_write(struct issei_host_client *cl);
void issei_cl_clean_all_wbuf(struct issei_host_client *cl);

+int issei_cl_dma_map(struct issei_host_client *cl, size_t size,
+ dma_addr_t *daddr, void **vaddr);
+void issei_cl_dma_unmap(struct issei_host_client *cl);
+
#endif /* ISSEI_HOST_CLIENT_H_ */
diff --git a/drivers/misc/issei/issei_dev.h b/drivers/misc/issei/issei_dev.h
index b47c4a7c2da4..244dc62ad85f 100644
--- a/drivers/misc/issei/issei_dev.h
+++ b/drivers/misc/issei/issei_dev.h
@@ -6,6 +6,7 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/sched.h>
+#include <linux/sizes.h>
#include <linux/time64.h>
#include <linux/types.h>
#include <linux/wait.h>
@@ -31,6 +32,8 @@ extern struct class *issei_class;
#define ISSEI_STOP_TIMEOUT_MSEC 500
#define ISSEI_WRITE_TIMEOUT_MSEC (MSEC_PER_SEC)

+#define ISSEI_HOST_DMA_MAX_SIZE SZ_64M
+
/**
* struct issei_write_buf - write buffer object
* @list: linked list pointer

--
2.53.0