* [PATCH char-misc-next v2 1/4] issei: save power_down flag while processing event
2026-10-18 9:30 [PATCH char-misc-next v2 0/4] issei: runtime power management, dma and in-kernel interface Alexander Usyskin
@ 2026-10-18 9:30 ` Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 2/4] issei: add runtime pm Alexander Usyskin
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Alexander Usyskin @ 2026-10-18 9:30 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman
Cc: linux-kernel, Menachem Adin, Andrzej Kacprowski, Karol Wachowski,
Alexander Usyskin
Change in power_down flag may confuse event thread.
Save flag status at the first available moment and
work according to saved value.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
drivers/misc/issei/main.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/misc/issei/main.c b/drivers/misc/issei/main.c
index 5987fb340250..8aaf2d47392b 100644
--- a/drivers/misc/issei/main.c
+++ b/drivers/misc/issei/main.c
@@ -24,7 +24,7 @@ static void issei_rst_state_set(struct issei_device *idev, enum issei_rst_state
wake_up(&idev->wait_rst_state);
}
-static int issei_reset(struct issei_device *idev)
+static int issei_reset(struct issei_device *idev, bool power_down)
{
int ret;
@@ -34,14 +34,14 @@ static int issei_reset(struct issei_device *idev)
issei_fw_cl_remove_all(idev);
/* No need to check for overflow here, the counter is used only for info */
idev->all_reset_count++;
- ret = idev->ops->hw_reset(idev, !idev->power_down);
+ ret = idev->ops->hw_reset(idev, !power_down);
issei_dmam_setup(idev);
if (ret) {
dev_err(&idev->dev, "hw_reset failed ret = %d\n", ret);
return ret;
}
- if (idev->power_down) {
+ if (power_down) {
dev_dbg(&idev->dev, "powering down: end of reset\n");
issei_rst_state_set(idev, ISSEI_RST_STATE_DISABLED);
return -ENODEV;
@@ -87,24 +87,26 @@ static int issei_process_thread(void *_dev)
{
long timeout, old_timeout = MAX_SCHEDULE_TIMEOUT;
struct issei_device *idev = _dev;
+ bool power_down;
int ret;
while (!kthread_should_stop()) {
dev_dbg(&idev->dev, "process_work in %d\n", idev->rst_state);
+ WRITE_ONCE(idev->has_data, false);
+ power_down = idev->power_down; /* to save state */
if (!idev->ops->hw_is_ready(idev) && idev->rst_state > ISSEI_RST_STATE_HW_READY) {
- if (!idev->power_down)
+ if (!power_down)
dev_dbg(&idev->dev, "HW not ready, resetting\n");
idev->rst_state = ISSEI_RST_STATE_INIT;
}
- if (idev->power_down)
+ if (power_down)
idev->rst_state = ISSEI_RST_STATE_INIT;
- WRITE_ONCE(idev->has_data, false);
dev_dbg(&idev->dev, "reset_step in %d\n", idev->rst_state);
timeout = MAX_SCHEDULE_TIMEOUT;
ret = 0;
switch (idev->rst_state) {
case ISSEI_RST_STATE_DISABLED:
- if (idev->power_down) {
+ if (power_down) {
dev_dbg(&idev->dev, "Interrupt in power down?\n");
break;
}
@@ -115,7 +117,7 @@ static int issei_process_thread(void *_dev)
idev->ops->irq_clear(idev);
idev->ops->irq_sync(idev);
- if (!idev->power_down) {
+ if (!power_down) {
idev->reset_count++;
if (idev->reset_count > ISSEI_MAX_CONSEC_RESET) {
dev_err(&idev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
@@ -124,8 +126,8 @@ static int issei_process_thread(void *_dev)
}
}
- ret = issei_reset(idev);
- if (idev->power_down) {
+ ret = issei_reset(idev, power_down);
+ if (power_down) {
dev_dbg(&idev->dev, "Powering down\n");
return 0;
}
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH char-misc-next v2 2/4] issei: add runtime pm
2026-10-18 9:30 [PATCH char-misc-next v2 0/4] issei: runtime power management, dma and in-kernel interface Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 1/4] issei: save power_down flag while processing event Alexander Usyskin
@ 2026-10-18 9:30 ` Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 3/4] issei: host_client: add dma allocation support Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 4/4] issei: add driver to driver interface Alexander Usyskin
3 siblings, 0 replies; 7+ messages in thread
From: Alexander Usyskin @ 2026-10-18 9:30 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman
Cc: linux-kernel, Menachem Adin, Andrzej Kacprowski, Karol Wachowski,
Alexander Usyskin
Add support for runtime power management.
ISSE communication is based on send-receive transaction.
Allow autosuspend with 60 seconds grace as firmware required
to answer inside this timeframe.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
drivers/misc/issei/host_client.c | 4 +
drivers/misc/issei/hw_heci.c | 21 +++-
drivers/misc/issei/main.c | 229 +++++++++++++++++++++------------------
drivers/misc/issei/pci_heci.c | 21 ++++
4 files changed, 168 insertions(+), 107 deletions(-)
diff --git a/drivers/misc/issei/host_client.c b/drivers/misc/issei/host_client.c
index 8f36d1c319ec..d16b5835c619 100644
--- a/drivers/misc/issei/host_client.c
+++ b/drivers/misc/issei/host_client.c
@@ -7,6 +7,7 @@
#include <linux/kobject.h>
#include <linux/list.h>
#include <linux/overflow.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/wait.h>
@@ -73,6 +74,7 @@ static void __issei_cl_clean_all_wbuf(struct issei_device *idev, struct issei_ho
}
}
cl->write_in_progress = false;
+ pm_runtime_put_autosuspend(idev->parent);
/* synchronized under host client mutex */
if (waitqueue_active(&cl->write_wait))
wake_up_interruptible(&cl->write_wait);
@@ -309,6 +311,7 @@ ssize_t issei_cl_write(struct issei_host_client *cl, const u8 *buf, size_t buf_s
list_add_tail(&wbuf->list, &idev->write_queue);
cl->write_in_progress = true;
cl_dbg(idev, cl, "Write queued %zu bytes\n", buf_size);
+ pm_runtime_get(idev->parent);
issei_poke_process_thread(idev);
@@ -353,6 +356,7 @@ int issei_cl_write_from_queue(struct issei_device *idev)
if (ret >= 0)
idev->ops->irq_write_generate(idev);
cl->write_in_progress = false;
+ pm_runtime_put_autosuspend(idev->parent);
/* synchronized under host client mutex */
if (waitqueue_active(&cl->write_wait))
wake_up_interruptible(&cl->write_wait);
diff --git a/drivers/misc/issei/hw_heci.c b/drivers/misc/issei/hw_heci.c
index 501774aa95ff..1e39b285d4db 100644
--- a/drivers/misc/issei/hw_heci.c
+++ b/drivers/misc/issei/hw_heci.c
@@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/pci.h>
+#include <linux/pm_runtime.h>
#include <linux/sizes.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -501,12 +502,20 @@ irqreturn_t issei_heci_irq_quick_handler(int irq, void *dev_id)
{
struct issei_device *idev = dev_id;
struct issei_heci_hw *hw = to_heci_hw(idev);
+ irqreturn_t ret;
+ int active;
u32 reg;
- reg = heci_hcsr_read(idev);
- if (!heci_irq_src(reg))
+ active = pm_runtime_get_if_active(idev->parent);
+ if (!active)
return IRQ_NONE;
+ reg = heci_hcsr_read(idev);
+ if (!heci_irq_src(reg)) {
+ ret = IRQ_NONE;
+ goto out;
+ }
+
scoped_guard(spinlock_irqsave, &hw->access_lock) {
reg = heci_hcsr_read(idev);
heci_irq_clear(idev, reg);
@@ -519,7 +528,13 @@ irqreturn_t issei_heci_irq_quick_handler(int irq, void *dev_id)
issei_poke_process_thread(idev);
- return IRQ_HANDLED;
+ ret = IRQ_HANDLED;
+
+out:
+ if (active > 0)
+ pm_runtime_put_autosuspend(idev->parent);
+
+ return ret;
}
static const struct hw_heci_cfg hw_heci_pch_cfg = {
diff --git a/drivers/misc/issei/main.c b/drivers/misc/issei/main.c
index 8aaf2d47392b..c0b8606b17b3 100644
--- a/drivers/misc/issei/main.c
+++ b/drivers/misc/issei/main.c
@@ -7,6 +7,7 @@
#include <linux/export.h>
#include <linux/jiffies.h>
#include <linux/kthread.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/wait.h>
@@ -83,132 +84,152 @@ static int issei_process_write_msg(struct issei_device *idev)
return issei_cl_write_from_queue(idev);
}
-static int issei_process_thread(void *_dev)
+static bool issei_process_thread_worker(struct issei_device *idev, bool power_down,
+ long *timeout, long *old_timeout)
{
- long timeout, old_timeout = MAX_SCHEDULE_TIMEOUT;
- struct issei_device *idev = _dev;
- bool power_down;
int ret;
- while (!kthread_should_stop()) {
- dev_dbg(&idev->dev, "process_work in %d\n", idev->rst_state);
- WRITE_ONCE(idev->has_data, false);
- power_down = idev->power_down; /* to save state */
- if (!idev->ops->hw_is_ready(idev) && idev->rst_state > ISSEI_RST_STATE_HW_READY) {
- if (!power_down)
- dev_dbg(&idev->dev, "HW not ready, resetting\n");
- idev->rst_state = ISSEI_RST_STATE_INIT;
+ PM_RUNTIME_ACQUIRE_AUTOSUSPEND(idev->parent, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret) {
+ dev_err(&idev->dev, "Failed to acquire pm %d\n", ret);
+ idev->rst_state = ISSEI_RST_STATE_INIT;
+ return false;
+ }
+
+ if (!idev->ops->hw_is_ready(idev) && idev->rst_state > ISSEI_RST_STATE_HW_READY) {
+ if (!power_down)
+ dev_dbg(&idev->dev, "HW not ready, resetting\n");
+ idev->rst_state = ISSEI_RST_STATE_INIT;
+ }
+ if (power_down)
+ idev->rst_state = ISSEI_RST_STATE_INIT;
+ dev_dbg(&idev->dev, "reset_step in %d\n", idev->rst_state);
+ *timeout = MAX_SCHEDULE_TIMEOUT;
+ ret = 0;
+ switch (idev->rst_state) {
+ case ISSEI_RST_STATE_DISABLED:
+ if (power_down) {
+ dev_dbg(&idev->dev, "Interrupt in power down?\n");
+ break;
}
- if (power_down)
- idev->rst_state = ISSEI_RST_STATE_INIT;
- dev_dbg(&idev->dev, "reset_step in %d\n", idev->rst_state);
- timeout = MAX_SCHEDULE_TIMEOUT;
- ret = 0;
- switch (idev->rst_state) {
- case ISSEI_RST_STATE_DISABLED:
- if (power_down) {
- dev_dbg(&idev->dev, "Interrupt in power down?\n");
+ idev->rst_state = ISSEI_RST_STATE_INIT;
+ idev->reset_count = 0;
+ fallthrough;
+
+ case ISSEI_RST_STATE_INIT:
+ idev->ops->irq_clear(idev);
+ idev->ops->irq_sync(idev);
+
+ if (!power_down) {
+ if (!idev->reset_count)
+ pm_runtime_get_noresume(idev->parent);
+ idev->reset_count++;
+ if (idev->reset_count > ISSEI_MAX_CONSEC_RESET) {
+ dev_err(&idev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
+ issei_rst_state_set(idev, ISSEI_RST_STATE_DISABLED);
+ pm_runtime_put_noidle(idev->parent);
break;
}
- idev->rst_state = ISSEI_RST_STATE_INIT;
- fallthrough;
-
- case ISSEI_RST_STATE_INIT:
- idev->ops->irq_clear(idev);
- idev->ops->irq_sync(idev);
-
- if (!power_down) {
- idev->reset_count++;
- if (idev->reset_count > ISSEI_MAX_CONSEC_RESET) {
- dev_err(&idev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
- issei_rst_state_set(idev, ISSEI_RST_STATE_DISABLED);
- break;
- }
- }
-
- ret = issei_reset(idev, power_down);
- if (power_down) {
- dev_dbg(&idev->dev, "Powering down\n");
- return 0;
- }
- if (ret)
- break;
+ }
- idev->rst_state = ISSEI_RST_STATE_HW_READY;
- timeout = msecs_to_jiffies(ISSEI_RST_HW_READY_TIMEOUT_MSEC);
+ ret = issei_reset(idev, power_down);
+ if (power_down) {
+ dev_dbg(&idev->dev, "Powering down\n");
+ return true;
+ }
+ if (ret)
break;
- case ISSEI_RST_STATE_HW_READY:
- if (!idev->ops->hw_is_ready(idev)) {
- dev_dbg(&idev->dev, "HW is not ready?\n");
- timeout = old_timeout;
- break;
- }
-
- dev_dbg(&idev->dev, "HW is ready\n");
- idev->ops->hw_reset_release(idev);
- idev->ops->host_set_ready(idev);
- ret = idev->ops->setup_message_send(idev);
- if (ret)
- break;
+ idev->rst_state = ISSEI_RST_STATE_HW_READY;
+ *timeout = msecs_to_jiffies(ISSEI_RST_HW_READY_TIMEOUT_MSEC);
+ break;
- idev->rst_state = ISSEI_RST_STATE_SETUP;
- timeout = msecs_to_jiffies(ISSEI_RST_STEP_TIMEOUT_MSEC);
+ case ISSEI_RST_STATE_HW_READY:
+ if (!idev->ops->hw_is_ready(idev)) {
+ dev_dbg(&idev->dev, "HW is not ready?\n");
+ *timeout = *old_timeout;
break;
+ }
- case ISSEI_RST_STATE_SETUP:
- ret = idev->ops->setup_message_recv(idev);
- if (ret) {
- if (ret == -ENODATA) {
- ret = 0;
- timeout = old_timeout;
- }
- } else {
- timeout = msecs_to_jiffies(ISSEI_RST_STEP_TIMEOUT_MSEC);
- ret = issei_ham_send_start_req(idev);
- idev->rst_state = ISSEI_RST_STATE_START;
- }
+ dev_dbg(&idev->dev, "HW is ready\n");
+ idev->ops->hw_reset_release(idev);
+ idev->ops->host_set_ready(idev);
+ ret = idev->ops->setup_message_send(idev);
+ if (ret)
break;
- case ISSEI_RST_STATE_START:
- ret = issei_process_read_msg(idev);
- if (!ret) {
- timeout = msecs_to_jiffies(ISSEI_RST_STEP_TIMEOUT_MSEC);
- idev->rst_state = ISSEI_RST_STATE_CLIENT_ENUM;
- } else if (ret == -ENODATA) {
+ idev->rst_state = ISSEI_RST_STATE_SETUP;
+ *timeout = msecs_to_jiffies(ISSEI_RST_STEP_TIMEOUT_MSEC);
+ break;
+
+ case ISSEI_RST_STATE_SETUP:
+ ret = idev->ops->setup_message_recv(idev);
+ if (ret) {
+ if (ret == -ENODATA) {
ret = 0;
- timeout = old_timeout;
+ *timeout = *old_timeout;
}
- break;
+ } else {
+ *timeout = msecs_to_jiffies(ISSEI_RST_STEP_TIMEOUT_MSEC);
+ ret = issei_ham_send_start_req(idev);
+ idev->rst_state = ISSEI_RST_STATE_START;
+ }
+ break;
+
+ case ISSEI_RST_STATE_START:
+ ret = issei_process_read_msg(idev);
+ if (!ret) {
+ *timeout = msecs_to_jiffies(ISSEI_RST_STEP_TIMEOUT_MSEC);
+ idev->rst_state = ISSEI_RST_STATE_CLIENT_ENUM;
+ } else if (ret == -ENODATA) {
+ ret = 0;
+ *timeout = *old_timeout;
+ }
+ break;
- case ISSEI_RST_STATE_CLIENT_ENUM:
- ret = issei_process_read_msg(idev);
- if (ret) {
- if (ret == -ENODATA) {
- ret = 0;
- timeout = old_timeout;
- }
- } else {
- idev->reset_count = 0;
- idev->rst_state = ISSEI_RST_STATE_DONE;
- dev_dbg(&idev->dev, "Reset finished successfully\n");
+ case ISSEI_RST_STATE_CLIENT_ENUM:
+ ret = issei_process_read_msg(idev);
+ if (ret) {
+ if (ret == -ENODATA) {
+ ret = 0;
+ *timeout = *old_timeout;
}
+ } else {
+ idev->reset_count = 0;
+ issei_rst_state_set(idev, ISSEI_RST_STATE_DONE);
+ pm_runtime_put_autosuspend(idev->parent);
+ dev_dbg(&idev->dev, "Reset finished successfully\n");
+ }
+ break;
+
+ case ISSEI_RST_STATE_DONE:
+ ret = issei_process_read_msg(idev);
+ if (ret != 0 && ret != -ENODATA)
break;
- case ISSEI_RST_STATE_DONE:
- ret = issei_process_read_msg(idev);
- if (ret != 0 && ret != -ENODATA)
- break;
+ ret = issei_process_write_msg(idev);
+ break;
+ }
- ret = issei_process_write_msg(idev);
- break;
- }
+ if (ret) {
+ dev_warn(&idev->dev, "Process failed ret = %d\n", ret);
+ idev->rst_state = ISSEI_RST_STATE_INIT;
+ }
+ return false;
+}
- if (ret) {
- dev_warn(&idev->dev, "Process failed ret = %d\n", ret);
- idev->rst_state = ISSEI_RST_STATE_INIT;
- continue;
- }
+static int issei_process_thread(void *_dev)
+{
+ long timeout, old_timeout = MAX_SCHEDULE_TIMEOUT;
+ struct issei_device *idev = _dev;
+
+ while (!kthread_should_stop()) {
+ dev_dbg(&idev->dev, "process_work in %d\n", idev->rst_state);
+ WRITE_ONCE(idev->has_data, false);
+
+ if (issei_process_thread_worker(idev, idev->power_down, &timeout, &old_timeout))
+ return 0;
/*
* Every thread that has data to process sets the 'has_data' flag and
diff --git a/drivers/misc/issei/pci_heci.c b/drivers/misc/issei/pci_heci.c
index 86c567a4bf0f..c58b51b3aad3 100644
--- a/drivers/misc/issei/pci_heci.c
+++ b/drivers/misc/issei/pci_heci.c
@@ -8,11 +8,15 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/time.h>
#include "cdev.h"
#include "hw_heci.h"
#include "hw_heci_regs.h"
+#define HW_HECI_RPM_TIMEOUT_MSEC (60 * MSEC_PER_SEC)
+
static int issei_heci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
@@ -70,6 +74,18 @@ static int issei_heci_probe(struct pci_dev *pdev, const struct pci_device_id *en
goto free_irq;
}
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, HW_HECI_RPM_TIMEOUT_MSEC);
+
+ /*
+ * ISSEI requires to resume from runtime suspend mode
+ * in order to perform link reset flow upon system suspend.
+ */
+ dev_pm_set_driver_flags(dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+
+ pm_runtime_put_noidle(dev);
+ pm_runtime_allow(dev);
+
return 0;
free_irq:
@@ -86,6 +102,11 @@ static void issei_heci_shutdown(struct pci_dev *pdev)
{
struct issei_device *idev = pci_get_drvdata(pdev);
struct issei_heci_hw *hw = to_heci_hw(idev);
+ struct device *dev = &pdev->dev;
+
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_forbid(dev);
+ pm_runtime_get_noresume(dev);
issei_stop(idev);
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH char-misc-next v2 3/4] issei: host_client: add dma allocation support
2026-10-18 9:30 [PATCH char-misc-next v2 0/4] issei: runtime power management, dma and in-kernel interface Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 1/4] issei: save power_down flag while processing event Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 2/4] issei: add runtime pm Alexander Usyskin
@ 2026-10-18 9:30 ` Alexander Usyskin
2026-10-18 9:30 ` [PATCH char-misc-next v2 4/4] issei: add driver to driver interface Alexander Usyskin
3 siblings, 0 replies; 7+ messages in thread
From: Alexander Usyskin @ 2026-10-18 9:30 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman
Cc: linux-kernel, Menachem Adin, Andrzej Kacprowski, Karol Wachowski,
Alexander Usyskin
Add functions to allow dedicated DMA buffer allocated on current
hardware device per host client.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
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
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH char-misc-next v2 4/4] issei: add driver to driver interface
2026-10-18 9:30 [PATCH char-misc-next v2 0/4] issei: runtime power management, dma and in-kernel interface Alexander Usyskin
` (2 preceding siblings ...)
2026-10-18 9:30 ` [PATCH char-misc-next v2 3/4] issei: host_client: add dma allocation support Alexander Usyskin
@ 2026-10-18 9:30 ` Alexander Usyskin
2026-10-19 4:17 ` kernel test robot
2026-10-19 6:19 ` kernel test robot
3 siblings, 2 replies; 7+ messages in thread
From: Alexander Usyskin @ 2026-10-18 9:30 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman
Cc: linux-kernel, Menachem Adin, Andrzej Kacprowski, Karol Wachowski,
Alexander Usyskin, Reuven Abliyev
Add new interface that enables communication with ISSEI device
from the kernel modules.
First intended consumer is an NPU driver.
Co-developed-by: Reuven Abliyev <reuvenab@gmail.com>
Signed-off-by: Reuven Abliyev <reuvenab@gmail.com>
Co-developed-by: Andrzej Kacprowski <andrzej.kacprowski@linux.intel.com>
Signed-off-by: Andrzej Kacprowski <andrzej.kacprowski@linux.intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
MAINTAINERS | 1 +
drivers/misc/issei/Makefile | 1 +
drivers/misc/issei/cdev.c | 12 +-
drivers/misc/issei/issei_device.c | 269 ++++++++++++++++++++++++++++++++++++++
include/linux/issei_device.h | 31 +++++
5 files changed, 308 insertions(+), 6 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index c548092c6a78..e16f6a0bc186 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13506,6 +13506,7 @@ S: Supported
F: Documentation/ABI/testing/sysfs-class-issei
F: Documentation/driver-api/issei/issei.rst
F: drivers/misc/issei/
+F: include/linux/issei_device.h
F: include/uapi/linux/issei.h
INTEL SGX
diff --git a/drivers/misc/issei/Makefile b/drivers/misc/issei/Makefile
index 8fac360c3342..b689784357f4 100644
--- a/drivers/misc/issei/Makefile
+++ b/drivers/misc/issei/Makefile
@@ -8,6 +8,7 @@ issei-objs += dma.o
issei-objs += fw_client.o
issei-objs += host_client.o
issei-objs += ham.o
+issei-objs += issei_device.o
issei-objs += main.o
obj-$(CONFIG_INTEL_SSEI_HW_HECI) += issei-heci.o
diff --git a/drivers/misc/issei/cdev.c b/drivers/misc/issei/cdev.c
index b7d65e2d0813..f5a3ebbf8740 100644
--- a/drivers/misc/issei/cdev.c
+++ b/drivers/misc/issei/cdev.c
@@ -272,14 +272,14 @@ static const struct file_operations issei_fops = {
.poll = issei_poll,
};
-static void issei_device_release(struct device *dev)
+static void issei_dev_release(struct device *dev)
{
kfree(dev_get_drvdata(dev));
}
-static void issei_device_init(struct issei_device *idev, struct device *parent,
- const struct issei_dma_length *dma_length,
- const struct issei_hw_ops *ops)
+static void issei_dev_init(struct issei_device *idev, struct device *parent,
+ const struct issei_dma_length *dma_length,
+ const struct issei_hw_ops *ops)
{
idev->parent = parent;
idev->power_down = false;
@@ -322,7 +322,7 @@ struct issei_device *issei_register(size_t hw_size, struct device *parent,
if (!idev)
return ERR_PTR(-ENOMEM);
- issei_device_init(idev, parent, dma_length, ops);
+ issei_dev_init(idev, parent, dma_length, ops);
ret = xa_alloc(&issei_minor_xa, &minor, idev, XA_LIMIT(0, ISSEI_MAX_DEVS), GFP_KERNEL);
if (ret < 0) {
@@ -339,7 +339,7 @@ struct issei_device *issei_register(size_t hw_size, struct device *parent,
idev->dev.class = issei_class;
idev->dev.parent = parent;
idev->dev.groups = issei_groups;
- idev->dev.release = issei_device_release;
+ idev->dev.release = issei_dev_release;
dev_set_drvdata(&idev->dev, idev);
idev->cdev = cdev_alloc();
diff --git a/drivers/misc/issei/issei_device.c b/drivers/misc/issei/issei_device.c
new file mode 100644
index 000000000000..a399ffc39455
--- /dev/null
+++ b/drivers/misc/issei/issei_device.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2025-2026 Intel Corporation */
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+#include <linux/wait.h>
+
+#include <linux/issei.h>
+#include <linux/issei_device.h>
+
+#include "issei_dev.h"
+#include "host_client.h"
+
+#define ISSEI_DEVICE_CNT_TO_MS 200
+
+/**
+ * issei_device_open - open issei device context.
+ * @match: pointer to callback that should return non-zero when matching device is found
+ * @data: user data to pass to match callback
+ *
+ * Return: pointer to opaque context on success, ERR_PTR on error
+ */
+void *issei_device_open(int (*match)(struct device *, const void *), const void *data)
+{
+ struct issei_host_client *cl;
+ struct issei_device *idev;
+ struct device *dev;
+
+ dev = class_find_device(issei_class, NULL, data, match);
+ if (!dev)
+ return ERR_PTR(-ENODEV);
+
+ idev = dev_get_drvdata(dev);
+
+ cl = issei_cl_create(idev, NULL);
+ if (IS_ERR(cl))
+ put_device(dev);
+
+ return cl;
+}
+EXPORT_SYMBOL_GPL(issei_device_open);
+
+/**
+ * issei_device_release - release issei device context.
+ * @ctx: opaque context
+ */
+void issei_device_release(void *ctx)
+{
+ struct issei_host_client *cl = ctx;
+ struct issei_device *idev = cl->idev;
+
+ issei_cl_remove(cl);
+ put_device(&idev->dev);
+}
+EXPORT_SYMBOL_GPL(issei_device_release);
+
+/**
+ * issei_device_connect - connect to the firmware client.
+ * @ctx: opaque context
+ * @client_uuid: UUID of firmware client to connect
+ * @conn: pointer for client data to fill on successful connection
+ *
+ * Return: 0 on success, <0 on error
+ */
+int issei_device_connect(void *ctx, const uuid_t *client_uuid, struct issei_client *conn)
+{
+ struct issei_host_client *cl = ctx;
+ struct issei_device *idev = cl->idev;
+ long ret;
+
+ if (idev->rst_state != ISSEI_RST_STATE_DONE) {
+ ret = wait_event_interruptible_timeout(idev->wait_rst_state,
+ idev->rst_state == ISSEI_RST_STATE_DONE,
+ msecs_to_jiffies(ISSEI_DEVICE_CNT_TO_MS));
+ if (ret == 0) /* timeout */
+ ret = -ETIMEDOUT;
+ if (ret < 0) {
+ dev_dbg(&idev->dev, "Device is in transition ret = %ld\n", ret);
+ return ret;
+ }
+ }
+ return issei_cl_connect(cl, client_uuid, &conn->max_msg_length,
+ &conn->protocol_version, &conn->flags);
+}
+EXPORT_SYMBOL_GPL(issei_device_connect);
+
+/**
+ * issei_device_disconnect - disconnect from the firmware client.
+ * @ctx: opaque context
+ *
+ * Return: 0 on success, <0 on error
+ */
+int issei_device_disconnect(void *ctx)
+{
+ struct issei_host_client *cl = ctx;
+ struct issei_device *idev = cl->idev;
+
+ if (idev->rst_state != ISSEI_RST_STATE_DONE) {
+ dev_dbg(&idev->dev, "Device is in transition\n");
+ return -ENODEV;
+ }
+
+ return issei_cl_disconnect(cl);
+}
+EXPORT_SYMBOL_GPL(issei_device_disconnect);
+
+/**
+ * issei_device_write - send data to the firmware client.
+ * @ctx: opaque context
+ * @ubuf: data to send
+ * @length: data length
+ * @timeout: operation timeout in milliseconds
+ *
+ * Return: >=0 data length on success, <0 on error
+ */
+ssize_t issei_device_write(void *ctx, const u8 *ubuf, size_t length, unsigned long timeout)
+{
+ struct issei_host_client *cl = ctx;
+ struct issei_device *idev = cl->idev;
+ ssize_t ret;
+ long wret;
+
+ if (idev->rst_state != ISSEI_RST_STATE_DONE) {
+ dev_dbg(&idev->dev, "Device is in transition\n");
+ return -EBUSY;
+ }
+
+ if (!length)
+ return 0;
+
+ /* sanity check */
+ if (length > idev->dma.length.h2f) {
+ dev_dbg(&idev->dev, "Write is too big %zu > %zu\n", length,
+ idev->dma.length.h2f);
+ return -EFBIG;
+ }
+
+ u8 *buf __free(kfree) = kmemdup(ubuf, length, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ do {
+ ret = issei_cl_write(cl, buf, length);
+ if (ret < 0 && ret != -EAGAIN)
+ return ret;
+ /* buf is consumed by issei_cl_write on success */
+ if (ret >= 0)
+ retain_and_null_ptr(buf);
+ wret = wait_event_interruptible_timeout(cl->write_wait,
+ issei_cl_check_write(cl) != 1,
+ msecs_to_jiffies(timeout));
+ if (wret == 0) /* timeout */
+ wret = -ETIMEDOUT;
+ if (wret < 0) {
+ issei_cl_clean_all_wbuf(cl);
+ dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
+ return wret;
+ }
+ } while (ret == -EAGAIN);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(issei_device_write);
+
+/**
+ * issei_device_read - receive data from the firmware client.
+ * @ctx: opaque context
+ * @ubuf: buffer for data
+ * @length: buffer length
+ * @timeout: operation timeout in milliseconds
+ *
+ * Return: >=0 data length on success, <0 on error
+ */
+ssize_t issei_device_read(void *ctx, u8 *ubuf, size_t length, unsigned long timeout)
+{
+ struct issei_host_client *cl = ctx;
+ struct issei_device *idev = cl->idev;
+ u8 *data = NULL;
+ ssize_t ret;
+
+ if (idev->rst_state != ISSEI_RST_STATE_DONE) {
+ dev_dbg(&idev->dev, "Device is in transition\n");
+ return -EBUSY;
+ }
+
+ if (!length)
+ return 0;
+
+ /* sanity check */
+ if (length > idev->dma.length.f2h) {
+ dev_dbg(&idev->dev, "Read is too big %zu > %zu\n", length,
+ idev->dma.length.f2h);
+ return -EFBIG;
+ }
+
+ ret = issei_cl_read(cl, &data, length);
+ if (ret < 0) {
+ if (ret != -ENOENT)
+ return ret;
+
+ ret = wait_event_interruptible_timeout(cl->read_wait,
+ issei_cl_check_read(cl) != 0,
+ timeout);
+ if (ret == 0) /* timeout */
+ ret = -ETIMEDOUT;
+ if (ret < 0) {
+ dev_dbg(&idev->dev, "Failed reading data ret = %zd\n", ret);
+ return ret;
+ }
+ ret = issei_cl_read(cl, &data, length);
+ if (ret < 0)
+ return ret;
+ }
+
+ memcpy(ubuf, data, ret);
+ kfree(data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(issei_device_read);
+
+/**
+ * issei_device_dma_map - allocate DMA buffer on parent device.
+ * @ctx: opaque context
+ * @size: buffer size
+ * @daddr: pointer for buffer DMA address
+ * @vaddr: pointer for buffer virtual address
+ *
+ * Return: 0 on success, <0 on error
+ */
+int issei_device_dma_map(void *ctx, size_t size, dma_addr_t *daddr, void **vaddr)
+{
+ struct issei_host_client *cl = ctx;
+
+ return issei_cl_dma_map(cl, size, daddr, vaddr);
+}
+EXPORT_SYMBOL_GPL(issei_device_dma_map);
+
+/**
+ * issei_device_dma_unmap - deallocate DMA buffer.
+ * @ctx: opaque context
+ */
+void issei_device_dma_unmap(void *ctx)
+{
+ struct issei_host_client *cl = ctx;
+
+ issei_cl_dma_unmap(cl);
+}
+EXPORT_SYMBOL_GPL(issei_device_dma_unmap);
+
+/**
+ * issei_device_register_interface - register class interface for issei class.
+ * @intf: interface structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+int issei_device_register_interface(struct class_interface *intf)
+{
+ intf->class = issei_class;
+
+ return class_interface_register(intf);
+}
+EXPORT_SYMBOL_GPL(issei_device_register_interface);
diff --git a/include/linux/issei_device.h b/include/linux/issei_device.h
new file mode 100644
index 000000000000..2775aa1c1ed8
--- /dev/null
+++ b/include/linux/issei_device.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2025-2026 Intel Corporation */
+#ifndef _ISSEI_DEVICE_H_
+#define _ISSEI_DEVICE_H_
+
+#include <linux/issei.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+/* add MODULE_IMPORT_NS("INTEL_SSEI") to use these APIs */
+
+struct class_interface;
+struct device;
+
+void *issei_device_open(int (*match)(struct device *, const void *), const void *data);
+void issei_device_release(void *ctx);
+
+int issei_device_connect(void *ctx, const uuid_t *client_uuid, struct issei_client *conn);
+int issei_device_disconnect(void *ctx);
+
+ssize_t issei_device_write(void *ctx, const u8 *ubuf, size_t length, unsigned long timeout);
+ssize_t issei_device_read(void *ctx, u8 *ubuf, size_t length, unsigned long timeout);
+
+int issei_device_dma_map(void *ctx, size_t size, dma_addr_t *daddr, void **vaddr);
+void issei_device_dma_unmap(void *ctx);
+
+int issei_device_register_interface(struct class_interface *intf);
+#define issei_device_unregister_interface(intf) \
+ class_interface_unregister(intf)
+
+#endif /* _ISSEI_DEVICE_H_ */
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH char-misc-next v2 4/4] issei: add driver to driver interface
2026-10-18 9:30 ` [PATCH char-misc-next v2 4/4] issei: add driver to driver interface Alexander Usyskin
@ 2026-10-19 4:17 ` kernel test robot
2026-10-19 6:19 ` kernel test robot
1 sibling, 0 replies; 7+ messages in thread
From: kernel test robot @ 2026-10-19 4:17 UTC (permalink / raw)
To: Alexander Usyskin, Arnd Bergmann, Greg Kroah-Hartman
Cc: oe-kbuild-all, linux-kernel, Menachem Adin, Andrzej Kacprowski,
Karol Wachowski, Alexander Usyskin, Reuven Abliyev
Hi Alexander,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 79e5797d243a466138f641932f81dc69f796060c]
url: https://github.com/intel-lab-lkp/linux/commits/Alexander-Usyskin/issei-save-power_down-flag-while-processing-event/20261018-123052
base: 79e5797d243a466138f641932f81dc69f796060c
patch link: https://lore.kernel.org/r/20261018-issei_pm_and_itf-v2-4-7a07452e3606%40intel.com
patch subject: [PATCH char-misc-next v2 4/4] issei: add driver to driver interface
config: i386-randconfig-1002-20261019 (https://download.01.org/0day-ci/archive/20261019/202610191253.F5L34Ggm-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261019/202610191253.F5L34Ggm-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202610191253.F5L34Ggm-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from include/linux/device.h:15,
from drivers/misc/issei/issei_device.c:4:
drivers/misc/issei/issei_device.c: In function 'issei_device_write':
>> drivers/misc/issei/issei_device.c:163:45: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'ssize_t' {aka 'int'} [-Wformat=]
163 | dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/dev_printk.h:139:49: note: in definition of macro 'dev_no_printk'
139 | _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
| ^~~
include/linux/dev_printk.h:171:40: note: in expansion of macro 'dev_fmt'
171 | dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~
drivers/misc/issei/issei_device.c:163:25: note: in expansion of macro 'dev_dbg'
163 | dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
| ^~~~~~~
drivers/misc/issei/issei_device.c:163:74: note: format string is defined here
163 | dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
| ~~^
| |
| long int
| %d
vim +163 drivers/misc/issei/issei_device.c
113
114 /**
115 * issei_device_write - send data to the firmware client.
116 * @ctx: opaque context
117 * @ubuf: data to send
118 * @length: data length
119 * @timeout: operation timeout in milliseconds
120 *
121 * Return: >=0 data length on success, <0 on error
122 */
123 ssize_t issei_device_write(void *ctx, const u8 *ubuf, size_t length, unsigned long timeout)
124 {
125 struct issei_host_client *cl = ctx;
126 struct issei_device *idev = cl->idev;
127 ssize_t ret;
128 long wret;
129
130 if (idev->rst_state != ISSEI_RST_STATE_DONE) {
131 dev_dbg(&idev->dev, "Device is in transition\n");
132 return -EBUSY;
133 }
134
135 if (!length)
136 return 0;
137
138 /* sanity check */
139 if (length > idev->dma.length.h2f) {
140 dev_dbg(&idev->dev, "Write is too big %zu > %zu\n", length,
141 idev->dma.length.h2f);
142 return -EFBIG;
143 }
144
145 u8 *buf __free(kfree) = kmemdup(ubuf, length, GFP_KERNEL);
146 if (!buf)
147 return -ENOMEM;
148
149 do {
150 ret = issei_cl_write(cl, buf, length);
151 if (ret < 0 && ret != -EAGAIN)
152 return ret;
153 /* buf is consumed by issei_cl_write on success */
154 if (ret >= 0)
155 retain_and_null_ptr(buf);
156 wret = wait_event_interruptible_timeout(cl->write_wait,
157 issei_cl_check_write(cl) != 1,
158 msecs_to_jiffies(timeout));
159 if (wret == 0) /* timeout */
160 wret = -ETIMEDOUT;
161 if (wret < 0) {
162 issei_cl_clean_all_wbuf(cl);
> 163 dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
164 return wret;
165 }
166 } while (ret == -EAGAIN);
167
168 return ret;
169 }
170 EXPORT_SYMBOL_GPL(issei_device_write);
171
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH char-misc-next v2 4/4] issei: add driver to driver interface
2026-10-18 9:30 ` [PATCH char-misc-next v2 4/4] issei: add driver to driver interface Alexander Usyskin
2026-10-19 4:17 ` kernel test robot
@ 2026-10-19 6:19 ` kernel test robot
1 sibling, 0 replies; 7+ messages in thread
From: kernel test robot @ 2026-10-19 6:19 UTC (permalink / raw)
To: Alexander Usyskin, Arnd Bergmann, Greg Kroah-Hartman
Cc: llvm, oe-kbuild-all, linux-kernel, Menachem Adin,
Andrzej Kacprowski, Karol Wachowski, Alexander Usyskin,
Reuven Abliyev
Hi Alexander,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 79e5797d243a466138f641932f81dc69f796060c]
url: https://github.com/intel-lab-lkp/linux/commits/Alexander-Usyskin/issei-save-power_down-flag-while-processing-event/20261018-123052
base: 79e5797d243a466138f641932f81dc69f796060c
patch link: https://lore.kernel.org/r/20261018-issei_pm_and_itf-v2-4-7a07452e3606%40intel.com
patch subject: [PATCH char-misc-next v2 4/4] issei: add driver to driver interface
config: i386-randconfig-1001-20261019 (https://download.01.org/0day-ci/archive/20261019/202610191455.cc2xaeEs-lkp@intel.com/config)
compiler: clang version 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261019/202610191455.cc2xaeEs-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202610191455.cc2xaeEs-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/misc/issei/issei_device.c:163:59: warning: format specifies type 'long' but the argument has type 'ssize_t' (aka 'int') [-Wformat]
163 | dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
| ~~~ ^~~
| %zd
include/linux/dev_printk.h:171:49: note: expanded from macro 'dev_dbg'
171 | dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/dev_printk.h:139:35: note: expanded from macro 'dev_no_printk'
139 | _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
| ~~~ ^~~~~~~~~~~
1 warning generated.
vim +163 drivers/misc/issei/issei_device.c
113
114 /**
115 * issei_device_write - send data to the firmware client.
116 * @ctx: opaque context
117 * @ubuf: data to send
118 * @length: data length
119 * @timeout: operation timeout in milliseconds
120 *
121 * Return: >=0 data length on success, <0 on error
122 */
123 ssize_t issei_device_write(void *ctx, const u8 *ubuf, size_t length, unsigned long timeout)
124 {
125 struct issei_host_client *cl = ctx;
126 struct issei_device *idev = cl->idev;
127 ssize_t ret;
128 long wret;
129
130 if (idev->rst_state != ISSEI_RST_STATE_DONE) {
131 dev_dbg(&idev->dev, "Device is in transition\n");
132 return -EBUSY;
133 }
134
135 if (!length)
136 return 0;
137
138 /* sanity check */
139 if (length > idev->dma.length.h2f) {
140 dev_dbg(&idev->dev, "Write is too big %zu > %zu\n", length,
141 idev->dma.length.h2f);
142 return -EFBIG;
143 }
144
145 u8 *buf __free(kfree) = kmemdup(ubuf, length, GFP_KERNEL);
146 if (!buf)
147 return -ENOMEM;
148
149 do {
150 ret = issei_cl_write(cl, buf, length);
151 if (ret < 0 && ret != -EAGAIN)
152 return ret;
153 /* buf is consumed by issei_cl_write on success */
154 if (ret >= 0)
155 retain_and_null_ptr(buf);
156 wret = wait_event_interruptible_timeout(cl->write_wait,
157 issei_cl_check_write(cl) != 1,
158 msecs_to_jiffies(timeout));
159 if (wret == 0) /* timeout */
160 wret = -ETIMEDOUT;
161 if (wret < 0) {
162 issei_cl_clean_all_wbuf(cl);
> 163 dev_dbg(&idev->dev, "Failed writing data ret = %ld\n", ret);
164 return wret;
165 }
166 } while (ret == -EAGAIN);
167
168 return ret;
169 }
170 EXPORT_SYMBOL_GPL(issei_device_write);
171
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 7+ messages in thread