[RESEND] firmware: stratix10-svc: Add Multi SVC clients support

Muhammad Amirul Asyraf Mohamad Jamian posted 1 patch 4 days, 4 hours ago
There is a newer version of this series
drivers/firmware/stratix10-svc.c              | 200 +++++++++++-------
.../firmware/intel/stratix10-svc-client.h     |   8 +-
2 files changed, 128 insertions(+), 80 deletions(-)
[RESEND] firmware: stratix10-svc: Add Multi SVC clients support
Posted by Muhammad Amirul Asyraf Mohamad Jamian 4 days, 4 hours ago
In the current implementation, SVC client drivers such as socfpga-hwmon,
intel_fcs, stratix10-soc, stratix10-rsu each send an SMC command that
triggers a single thread in the stratix10-svc driver. Upon receiving a
callback, the initiating client driver sends a stratix10-svc-done signal,
terminating the thread without waiting for other pending SMC commands to
complete. This leads to a timeout issue in the firmware SVC mailbox service
when multiple client drivers send SMC commands concurrently.

To resolve this issue, a dedicated thread is now created per channel. The
stratix10-svc driver will supports up to the number of channels defined by
SVC_NUM_CHANNEL. Thread synchronization is handled using a mutex to prevent
simultaneous issuance of SMC commands by multiple threads.

Additionally, a thread task is now validated before invoking kthread_stop
when the user aborts, ensuring safe termination.

Timeout values have also been adjusted to accommodate the increased load
from concurrent client driver activity.

Signed-off-by: Ang Tien Sung <tien.sung.ang@intel.com>
Signed-off-by: Fong, Yan Kei <yankei.fong@altera.com>
Signed-off-by: Khairul Anuar Romli <khairul.anuar.romli@altera.com>
Signed-off-by: Muhammad Amirul Asyraf Mohamad Jamian <muhammadamirulasyraf.mohamadjamian@altera.com>
---
 drivers/firmware/stratix10-svc.c              | 200 +++++++++++-------
 .../firmware/intel/stratix10-svc-client.h     |   8 +-
 2 files changed, 128 insertions(+), 80 deletions(-)

diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 515b948ff320..6bc0f9315a4e 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -37,9 +37,9 @@
  * service layer will return error to FPGA manager when timeout occurs,
  * timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC.
  */
-#define SVC_NUM_DATA_IN_FIFO			32
+#define SVC_NUM_DATA_IN_FIFO			8
 #define SVC_NUM_CHANNEL				4
-#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS	200
+#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS	2000
 #define FPGA_CONFIG_STATUS_TIMEOUT_SEC		30
 #define BYTE_TO_WORD_SIZE              4
 
@@ -252,11 +252,10 @@ struct stratix10_async_ctrl {
  * @node: list management
  * @genpool: memory pool pointing to the memory region
  * @task: pointer to the thread task which handles SMC or HVC call
- * @svc_fifo: a queue for storing service message data
  * @complete_status: state for completion
- * @svc_fifo_lock: protect access to service message data queue
  * @invoke_fn: function to issue secure monitor call or hypervisor call
  * @svc: manages the list of client svc drivers
+ * @sdm_lock: only allows a single command single response to SDM
  * @actrl: async control structure
  *
  * This struct is used to create communication channels for service clients, to
@@ -269,12 +268,10 @@ struct stratix10_svc_controller {
 	int num_active_client;
 	struct list_head node;
 	struct gen_pool *genpool;
-	struct task_struct *task;
-	struct kfifo svc_fifo;
 	struct completion complete_status;
-	spinlock_t svc_fifo_lock;
 	svc_invoke_fn *invoke_fn;
 	struct stratix10_svc *svc;
+	struct mutex *sdm_lock; /* Protect SDM transaction until response */
 	struct stratix10_async_ctrl actrl;
 };
 
@@ -283,6 +280,9 @@ struct stratix10_svc_controller {
  * @ctrl: pointer to service controller which is the provider of this channel
  * @scl: pointer to service client which owns the channel
  * @name: service client name associated with the channel
+ * @task: pointer to the thread task which handles SMC or HVC call
+ * @svc_fifo: a queue for storing service message data
+ * @svc_fifo_lock: protect access to service message data queue
  * @lock: protect access to the channel
  * @async_chan: reference to asynchronous channel object for this channel
  *
@@ -293,6 +293,10 @@ struct stratix10_svc_chan {
 	struct stratix10_svc_controller *ctrl;
 	struct stratix10_svc_client *scl;
 	char *name;
+	struct task_struct *task;
+	/* Separate fifo for every channel */
+	struct kfifo svc_fifo;
+	spinlock_t svc_fifo_lock; /* locking pending fifo */
 	spinlock_t lock;
 	struct stratix10_async_chan *async_chan;
 };
@@ -527,13 +531,14 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
  */
 static int svc_normal_to_secure_thread(void *data)
 {
-	struct stratix10_svc_controller
-			*ctrl = (struct stratix10_svc_controller *)data;
-	struct stratix10_svc_data *pdata;
-	struct stratix10_svc_cb_data *cbdata;
+	struct stratix10_svc_chan *chan =  (struct stratix10_svc_chan *)data;
+	struct stratix10_svc_controller	*ctrl = chan->ctrl;
+	struct stratix10_svc_data *pdata = NULL;
+	struct stratix10_svc_cb_data *cbdata = NULL;
 	struct arm_smccc_res res;
 	unsigned long a0, a1, a2, a3, a4, a5, a6, a7;
 	int ret_fifo = 0;
+	bool sdm_lock_owned = false;
 
 	pdata =  kmalloc(sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -555,12 +560,12 @@ static int svc_normal_to_secure_thread(void *data)
 	a6 = 0;
 	a7 = 0;
 
-	pr_debug("smc_hvc_shm_thread is running\n");
+	pr_debug("%s: %s: Thread is running!\n", __func__, chan->name);
 
 	while (!kthread_should_stop()) {
-		ret_fifo = kfifo_out_spinlocked(&ctrl->svc_fifo,
+		ret_fifo = kfifo_out_spinlocked(&chan->svc_fifo,
 						pdata, sizeof(*pdata),
-						&ctrl->svc_fifo_lock);
+						&chan->svc_fifo_lock);
 
 		if (!ret_fifo)
 			continue;
@@ -569,6 +574,16 @@ static int svc_normal_to_secure_thread(void *data)
 			 (unsigned int)pdata->paddr, pdata->command,
 			 (unsigned int)pdata->size);
 
+		/* SDM can only processs one command at a time */
+		if (!sdm_lock_owned) {
+			/* Must not do mutex re-lock */
+			pr_debug("%s: %s: Thread is waiting for mutex!\n",
+				 __func__, chan->name);
+			guard(mutex)(ctrl->sdm_lock);
+		}
+
+		sdm_lock_owned = true;
+
 		switch (pdata->command) {
 		case COMMAND_RECONFIG_DATA_CLAIM:
 			svc_thread_cmd_data_claim(ctrl, pdata, cbdata);
@@ -702,8 +717,8 @@ static int svc_normal_to_secure_thread(void *data)
 			pr_warn("it shouldn't happen\n");
 			break;
 		}
-		pr_debug("%s: before SMC call -- a0=0x%016x a1=0x%016x",
-			 __func__,
+		pr_debug("%s: %s: before SMC call -- a0=0x%016x a1=0x%016x",
+			 __func__, chan->name,
 			 (unsigned int)a0,
 			 (unsigned int)a1);
 		pr_debug(" a2=0x%016x\n", (unsigned int)a2);
@@ -712,8 +727,8 @@ static int svc_normal_to_secure_thread(void *data)
 		pr_debug(" a5=0x%016x\n", (unsigned int)a5);
 		ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
 
-		pr_debug("%s: after SMC call -- res.a0=0x%016x",
-			 __func__, (unsigned int)res.a0);
+		pr_debug("%s: %s: after SMC call -- res.a0=0x%016x",
+			 __func__, chan->name, (unsigned int)res.a0);
 		pr_debug(" res.a1=0x%016x, res.a2=0x%016x",
 			 (unsigned int)res.a1, (unsigned int)res.a2);
 		pr_debug(" res.a3=0x%016x\n", (unsigned int)res.a3);
@@ -728,6 +743,7 @@ static int svc_normal_to_secure_thread(void *data)
 			cbdata->kaddr2 = NULL;
 			cbdata->kaddr3 = NULL;
 			pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata);
+			sdm_lock_owned = false;
 			continue;
 		}
 
@@ -1697,21 +1713,21 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
 		return -ENOMEM;
 
 	/* first client will create kernel thread */
-	if (!chan->ctrl->task) {
-		chan->ctrl->task =
+	if (!chan->task) {
+		chan->task =
 			kthread_run_on_cpu(svc_normal_to_secure_thread,
-					   (void *)chan->ctrl,
+					   (void *)chan,
 					   cpu, "svc_smc_hvc_thread");
-			if (IS_ERR(chan->ctrl->task)) {
-				dev_err(chan->ctrl->dev,
-					"failed to create svc_smc_hvc_thread\n");
-				kfree(p_data);
-				return -EINVAL;
-			}
+		if (IS_ERR(chan->task)) {
+			dev_err(chan->ctrl->dev,
+				"failed to create svc_smc_hvc_thread\n");
+			kfree(p_data);
+			return -EINVAL;
+		}
 	}
 
-	pr_debug("%s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,
-		 p_msg->payload, p_msg->command,
+	pr_debug("%s: %s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,
+		 chan->name, p_msg->payload, p_msg->command,
 		 (unsigned int)p_msg->payload_length);
 
 	if (list_empty(&svc_data_mem)) {
@@ -1747,12 +1763,16 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
 	p_data->arg[2] = p_msg->arg[2];
 	p_data->size = p_msg->payload_length;
 	p_data->chan = chan;
-	pr_debug("%s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n", __func__,
-	       (unsigned int)p_data->paddr, p_data->command,
-	       (unsigned int)p_data->size);
-	ret = kfifo_in_spinlocked(&chan->ctrl->svc_fifo, p_data,
+	pr_debug("%s: %s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n",
+		 __func__,
+		 chan->name,
+		 (unsigned int)p_data->paddr,
+		 p_data->command,
+		 (unsigned int)p_data->size);
+
+	ret = kfifo_in_spinlocked(&chan->svc_fifo, p_data,
 				  sizeof(*p_data),
-				  &chan->ctrl->svc_fifo_lock);
+				  &chan->svc_fifo_lock);
 
 	kfree(p_data);
 
@@ -1773,12 +1793,21 @@ EXPORT_SYMBOL_GPL(stratix10_svc_send);
  */
 void stratix10_svc_done(struct stratix10_svc_chan *chan)
 {
-	/* stop thread when thread is running AND only one active client */
-	if (chan->ctrl->task && chan->ctrl->num_active_client <= 1) {
-		pr_debug("svc_smc_hvc_shm_thread is stopped\n");
-		kthread_stop(chan->ctrl->task);
-		chan->ctrl->task = NULL;
+	/* stop thread when thread is running */
+	if (chan->task) {
+		if (!IS_ERR(chan->task)) {
+			struct task_struct *task_to_stop = chan->task;
+
+			chan->task = NULL;
+			pr_debug("%s: %s: svc_smc_hvc_shm_thread is stopping\n",
+				 __func__, chan->name);
+			kthread_stop(task_to_stop);
+		}
+
+		chan->task = NULL;
 	}
+	pr_debug("%s: %s: svc_smc_hvc_shm_thread has stopped\n",
+		 __func__, chan->name);
 }
 EXPORT_SYMBOL_GPL(stratix10_svc_done);
 
@@ -1817,8 +1846,8 @@ void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
 	pmem->paddr = pa;
 	pmem->size = s;
 	list_add_tail(&pmem->node, &svc_data_mem);
-	pr_debug("%s: va=%p, pa=0x%016x\n", __func__,
-		 pmem->vaddr, (unsigned int)pmem->paddr);
+	pr_debug("%s: %s: va=%p, pa=0x%016x\n", __func__,
+		 chan->name, pmem->vaddr, (unsigned int)pmem->paddr);
 
 	return (void *)va;
 }
@@ -1855,6 +1884,11 @@ static const struct of_device_id stratix10_svc_drv_match[] = {
 	{},
 };
 
+/**
+ * mailbox_lock protects access to the to SDM if thread is busy
+ */
+static DEFINE_MUTEX(mailbox_lock);
+
 static int stratix10_svc_drv_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1905,7 +1939,6 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
 	controller->num_active_client = 0;
 	controller->chans = chans;
 	controller->genpool = genpool;
-	controller->task = NULL;
 	controller->invoke_fn = invoke_fn;
 	init_completion(&controller->complete_status);
 
@@ -1917,32 +1950,63 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
 	}
 
 	fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
-	ret = kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL);
+	ret = kfifo_alloc(&chans->svc_fifo, fifo_size, GFP_KERNEL);
 	if (ret) {
 		dev_err(dev, "failed to allocate FIFO\n");
 		goto err_async_exit;
 	}
-	spin_lock_init(&controller->svc_fifo_lock);
+	spin_lock_init(&chans->svc_fifo_lock);
+	/*
+	 * This mutex is used to block threads from utilizing
+	 * SDM to prevent out of order command tx
+	 */
+	controller->sdm_lock = &mailbox_lock;
+
+	fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
 
 	chans[0].scl = NULL;
 	chans[0].ctrl = controller;
 	chans[0].name = SVC_CLIENT_FPGA;
 	spin_lock_init(&chans[0].lock);
+	ret = kfifo_alloc(&chans[0].svc_fifo, fifo_size, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev, "failed to allocate FIFO 0\n");
+		return ret;
+	}
+	spin_lock_init(&chans[0].svc_fifo_lock);
 
 	chans[1].scl = NULL;
 	chans[1].ctrl = controller;
 	chans[1].name = SVC_CLIENT_RSU;
 	spin_lock_init(&chans[1].lock);
+	ret = kfifo_alloc(&chans[1].svc_fifo, fifo_size, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev, "failed to allocate FIFO 1\n");
+		return ret;
+	}
+	spin_lock_init(&chans[1].svc_fifo_lock);
 
 	chans[2].scl = NULL;
 	chans[2].ctrl = controller;
 	chans[2].name = SVC_CLIENT_FCS;
 	spin_lock_init(&chans[2].lock);
+	ret = kfifo_alloc(&chans[2].svc_fifo, fifo_size, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev, "failed to allocate FIFO 2\n");
+		return ret;
+	}
+	spin_lock_init(&chans[2].svc_fifo_lock);
 
 	chans[3].scl = NULL;
 	chans[3].ctrl = controller;
 	chans[3].name = SVC_CLIENT_HWMON;
 	spin_lock_init(&chans[3].lock);
+	ret = kfifo_alloc(&chans[3].svc_fifo, fifo_size, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev, "failed to allocate FIFO 3\n");
+		return ret;
+	}
+	spin_lock_init(&chans[3].svc_fifo_lock);
 
 	list_add_tail(&controller->node, &svc_ctrl);
 	platform_set_drvdata(pdev, controller);
@@ -1950,60 +2014,41 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
 	/* add svc client device(s) */
 	svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
 	if (!svc) {
-		ret = -ENOMEM;
-		goto err_free_kfifo;
+		return -ENOMEM;
 	}
 	controller->svc = svc;
 
 	svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0);
 	if (!svc->stratix10_svc_rsu) {
 		dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU);
-		ret = -ENOMEM;
-		goto err_free_kfifo;
+		return -ENOMEM;
 	}
 
 	ret = platform_device_add(svc->stratix10_svc_rsu);
-	if (ret) {
-		platform_device_put(svc->stratix10_svc_rsu);
-		goto err_free_kfifo;
-	}
-
-	svc->intel_svc_fcs = platform_device_alloc(INTEL_FCS, 1);
-	if (!svc->intel_svc_fcs) {
-		dev_err(dev, "failed to allocate %s device\n", INTEL_FCS);
-		ret = -ENOMEM;
-		goto err_unregister_rsu_dev;
-	}
-
-	ret = platform_device_add(svc->intel_svc_fcs);
-	if (ret) {
-		platform_device_put(svc->intel_svc_fcs);
-		goto err_unregister_rsu_dev;
-	}
+	if (ret)
+		goto err_put_device;
 
 	ret = of_platform_default_populate(dev_of_node(dev), NULL, dev);
 	if (ret)
-		goto err_unregister_fcs_dev;
+		goto err_put_device;
 
 	pr_info("Intel Service Layer Driver Initialized\n");
 
 	return 0;
 
-err_unregister_fcs_dev:
-	platform_device_unregister(svc->intel_svc_fcs);
-err_unregister_rsu_dev:
-	platform_device_unregister(svc->stratix10_svc_rsu);
-err_free_kfifo:
-	kfifo_free(&controller->svc_fifo);
 err_async_exit:
 	stratix10_svc_async_exit(controller);
+err_put_device:
+	platform_device_put(svc->stratix10_svc_rsu);
 err_destroy_pool:
 	gen_pool_destroy(genpool);
+
 	return ret;
 }
 
 static void stratix10_svc_drv_remove(struct platform_device *pdev)
 {
+	int i;
 	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
 	struct stratix10_svc *svc = ctrl->svc;
 
@@ -2014,11 +2059,14 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
 	platform_device_unregister(svc->intel_svc_fcs);
 	platform_device_unregister(svc->stratix10_svc_rsu);
 
-	kfifo_free(&ctrl->svc_fifo);
-	if (ctrl->task) {
-		kthread_stop(ctrl->task);
-		ctrl->task = NULL;
+	for (i = 0; i < SVC_NUM_CHANNEL; i++) {
+		if (ctrl->chans[i].task) {
+			kthread_stop(ctrl->chans[i].task);
+			ctrl->chans[i].task = NULL;
+		}
+		kfifo_free(&ctrl->chans[i].svc_fifo);
 	}
+
 	if (ctrl->genpool)
 		gen_pool_destroy(ctrl->genpool);
 	list_del(&ctrl->node);
diff --git a/include/linux/firmware/intel/stratix10-svc-client.h b/include/linux/firmware/intel/stratix10-svc-client.h
index d290060f4c73..91013161e9db 100644
--- a/include/linux/firmware/intel/stratix10-svc-client.h
+++ b/include/linux/firmware/intel/stratix10-svc-client.h
@@ -68,12 +68,12 @@
  * timeout value used in Stratix10 FPGA manager driver.
  * timeout value used in RSU driver
  */
-#define SVC_RECONFIG_REQUEST_TIMEOUT_MS         300
-#define SVC_RECONFIG_BUFFER_TIMEOUT_MS          720
-#define SVC_RSU_REQUEST_TIMEOUT_MS              300
+#define SVC_RECONFIG_REQUEST_TIMEOUT_MS         5000
+#define SVC_RECONFIG_BUFFER_TIMEOUT_MS          5000
+#define SVC_RSU_REQUEST_TIMEOUT_MS              2000
 #define SVC_FCS_REQUEST_TIMEOUT_MS		2000
 #define SVC_COMPLETED_TIMEOUT_MS		30000
-#define SVC_HWMON_REQUEST_TIMEOUT_MS		300
+#define SVC_HWMON_REQUEST_TIMEOUT_MS		2000
 
 struct stratix10_svc_chan;
 
-- 
2.43.7
Re: [RESEND] firmware: stratix10-svc: Add Multi SVC clients support
Posted by kernel test robot 3 days, 15 hours ago
Hi Muhammad,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.19-rc8 next-20260202]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Muhammad-Amirul-Asyraf-Mohamad-Jamian/firmware-stratix10-svc-Add-Multi-SVC-clients-support/20260203-110120
base:   linus/master
patch link:    https://lore.kernel.org/r/20260203025815.4526-1-muhammadamirulasyraf.mohamadjamian%40altera.com
patch subject: [RESEND] firmware: stratix10-svc: Add Multi SVC clients support
config: arm64-randconfig-003-20260203 (https://download.01.org/0day-ci/archive/20260203/202602032325.MuglZ156-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9b8addffa70cee5b2acc5454712d9cf78ce45710)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260203/202602032325.MuglZ156-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/202602032325.MuglZ156-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/firmware/stratix10-svc.c:1954:6: warning: variable 'svc' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    1954 |         if (ret) {
         |             ^~~
   drivers/firmware/stratix10-svc.c:2042:22: note: uninitialized use occurs here
    2042 |         platform_device_put(svc->stratix10_svc_rsu);
         |                             ^~~
   drivers/firmware/stratix10-svc.c:1954:2: note: remove the 'if' if its condition is always false
    1954 |         if (ret) {
         |         ^~~~~~~~~~
    1955 |                 dev_err(dev, "failed to allocate FIFO\n");
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1956 |                 goto err_async_exit;
         |                 ~~~~~~~~~~~~~~~~~~~~
    1957 |         }
         |         ~
   drivers/firmware/stratix10-svc.c:1899:27: note: initialize the variable 'svc' to silence this warning
    1899 |         struct stratix10_svc *svc;
         |                                  ^
         |                                   = NULL
   1 warning generated.


vim +1954 drivers/firmware/stratix10-svc.c

1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1891  
7ca5ce896524f5 Richard Gong                          2018-11-13  1892  static int stratix10_svc_drv_probe(struct platform_device *pdev)
7ca5ce896524f5 Richard Gong                          2018-11-13  1893  {
7ca5ce896524f5 Richard Gong                          2018-11-13  1894  	struct device *dev = &pdev->dev;
7ca5ce896524f5 Richard Gong                          2018-11-13  1895  	struct stratix10_svc_controller *controller;
7ca5ce896524f5 Richard Gong                          2018-11-13  1896  	struct stratix10_svc_chan *chans;
7ca5ce896524f5 Richard Gong                          2018-11-13  1897  	struct gen_pool *genpool;
7ca5ce896524f5 Richard Gong                          2018-11-13  1898  	struct stratix10_svc_sh_memory *sh_memory;
b5dc75c915cdae Richard Gong                          2019-09-03  1899  	struct stratix10_svc *svc;
b5dc75c915cdae Richard Gong                          2019-09-03  1900  
7ca5ce896524f5 Richard Gong                          2018-11-13  1901  	svc_invoke_fn *invoke_fn;
7ca5ce896524f5 Richard Gong                          2018-11-13  1902  	size_t fifo_size;
7ca5ce896524f5 Richard Gong                          2018-11-13  1903  	int ret;
7ca5ce896524f5 Richard Gong                          2018-11-13  1904  
7ca5ce896524f5 Richard Gong                          2018-11-13  1905  	/* get SMC or HVC function */
7ca5ce896524f5 Richard Gong                          2018-11-13  1906  	invoke_fn = get_invoke_func(dev);
7ca5ce896524f5 Richard Gong                          2018-11-13  1907  	if (IS_ERR(invoke_fn))
7ca5ce896524f5 Richard Gong                          2018-11-13  1908  		return -EINVAL;
7ca5ce896524f5 Richard Gong                          2018-11-13  1909  
7ca5ce896524f5 Richard Gong                          2018-11-13  1910  	sh_memory = devm_kzalloc(dev, sizeof(*sh_memory), GFP_KERNEL);
7ca5ce896524f5 Richard Gong                          2018-11-13  1911  	if (!sh_memory)
7ca5ce896524f5 Richard Gong                          2018-11-13  1912  		return -ENOMEM;
7ca5ce896524f5 Richard Gong                          2018-11-13  1913  
7ca5ce896524f5 Richard Gong                          2018-11-13  1914  	sh_memory->invoke_fn = invoke_fn;
7ca5ce896524f5 Richard Gong                          2018-11-13  1915  	ret = svc_get_sh_memory(pdev, sh_memory);
7ca5ce896524f5 Richard Gong                          2018-11-13  1916  	if (ret)
7ca5ce896524f5 Richard Gong                          2018-11-13  1917  		return ret;
7ca5ce896524f5 Richard Gong                          2018-11-13  1918  
7ca5ce896524f5 Richard Gong                          2018-11-13  1919  	genpool = svc_create_memory_pool(pdev, sh_memory);
e1d6ca042e62c2 Dan Carpenter                         2023-04-19  1920  	if (IS_ERR(genpool))
e1d6ca042e62c2 Dan Carpenter                         2023-04-19  1921  		return PTR_ERR(genpool);
7ca5ce896524f5 Richard Gong                          2018-11-13  1922  
7ca5ce896524f5 Richard Gong                          2018-11-13  1923  	/* allocate service controller and supporting channel */
7ca5ce896524f5 Richard Gong                          2018-11-13  1924  	controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
9175ee1a99d57e Yang Yingliang                        2022-11-29  1925  	if (!controller) {
9175ee1a99d57e Yang Yingliang                        2022-11-29  1926  		ret = -ENOMEM;
9175ee1a99d57e Yang Yingliang                        2022-11-29  1927  		goto err_destroy_pool;
9175ee1a99d57e Yang Yingliang                        2022-11-29  1928  	}
7ca5ce896524f5 Richard Gong                          2018-11-13  1929  
7ca5ce896524f5 Richard Gong                          2018-11-13  1930  	chans = devm_kmalloc_array(dev, SVC_NUM_CHANNEL,
7ca5ce896524f5 Richard Gong                          2018-11-13  1931  				   sizeof(*chans), GFP_KERNEL | __GFP_ZERO);
9175ee1a99d57e Yang Yingliang                        2022-11-29  1932  	if (!chans) {
9175ee1a99d57e Yang Yingliang                        2022-11-29  1933  		ret = -ENOMEM;
9175ee1a99d57e Yang Yingliang                        2022-11-29  1934  		goto err_destroy_pool;
9175ee1a99d57e Yang Yingliang                        2022-11-29  1935  	}
7ca5ce896524f5 Richard Gong                          2018-11-13  1936  
7ca5ce896524f5 Richard Gong                          2018-11-13  1937  	controller->dev = dev;
7ca5ce896524f5 Richard Gong                          2018-11-13  1938  	controller->num_chans = SVC_NUM_CHANNEL;
7ca5ce896524f5 Richard Gong                          2018-11-13  1939  	controller->num_active_client = 0;
7ca5ce896524f5 Richard Gong                          2018-11-13  1940  	controller->chans = chans;
7ca5ce896524f5 Richard Gong                          2018-11-13  1941  	controller->genpool = genpool;
7ca5ce896524f5 Richard Gong                          2018-11-13  1942  	controller->invoke_fn = invoke_fn;
7ca5ce896524f5 Richard Gong                          2018-11-13  1943  	init_completion(&controller->complete_status);
7ca5ce896524f5 Richard Gong                          2018-11-13  1944  
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1945  	ret = stratix10_svc_async_init(controller);
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1946  	if (ret) {
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1947  		dev_dbg(dev, "Intel Service Layer Driver: Error on stratix10_svc_async_init %d\n",
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1948  			ret);
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1949  		goto err_destroy_pool;
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1950  	}
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1951  
7ca5ce896524f5 Richard Gong                          2018-11-13  1952  	fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1953  	ret = kfifo_alloc(&chans->svc_fifo, fifo_size, GFP_KERNEL);
7ca5ce896524f5 Richard Gong                          2018-11-13 @1954  	if (ret) {
b5dc75c915cdae Richard Gong                          2019-09-03  1955  		dev_err(dev, "failed to allocate FIFO\n");
bcb9f4f0706147 Mahesh Rao                            2025-10-27  1956  		goto err_async_exit;
7ca5ce896524f5 Richard Gong                          2018-11-13  1957  	}
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1958  	spin_lock_init(&chans->svc_fifo_lock);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1959  	/*
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1960  	 * This mutex is used to block threads from utilizing
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1961  	 * SDM to prevent out of order command tx
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1962  	 */
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1963  	controller->sdm_lock = &mailbox_lock;
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1964  
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1965  	fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
7ca5ce896524f5 Richard Gong                          2018-11-13  1966  
7ca5ce896524f5 Richard Gong                          2018-11-13  1967  	chans[0].scl = NULL;
7ca5ce896524f5 Richard Gong                          2018-11-13  1968  	chans[0].ctrl = controller;
7ca5ce896524f5 Richard Gong                          2018-11-13  1969  	chans[0].name = SVC_CLIENT_FPGA;
7ca5ce896524f5 Richard Gong                          2018-11-13  1970  	spin_lock_init(&chans[0].lock);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1971  	ret = kfifo_alloc(&chans[0].svc_fifo, fifo_size, GFP_KERNEL);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1972  	if (ret) {
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1973  		dev_err(dev, "failed to allocate FIFO 0\n");
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1974  		return ret;
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1975  	}
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1976  	spin_lock_init(&chans[0].svc_fifo_lock);
7ca5ce896524f5 Richard Gong                          2018-11-13  1977  
6b50d882d38d5a Richard Gong                          2018-11-13  1978  	chans[1].scl = NULL;
6b50d882d38d5a Richard Gong                          2018-11-13  1979  	chans[1].ctrl = controller;
6b50d882d38d5a Richard Gong                          2018-11-13  1980  	chans[1].name = SVC_CLIENT_RSU;
6b50d882d38d5a Richard Gong                          2018-11-13  1981  	spin_lock_init(&chans[1].lock);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1982  	ret = kfifo_alloc(&chans[1].svc_fifo, fifo_size, GFP_KERNEL);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1983  	if (ret) {
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1984  		dev_err(dev, "failed to allocate FIFO 1\n");
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1985  		return ret;
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1986  	}
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1987  	spin_lock_init(&chans[1].svc_fifo_lock);
6b50d882d38d5a Richard Gong                          2018-11-13  1988  
e6281c26674e03 Ang Tien Sung                         2022-07-11  1989  	chans[2].scl = NULL;
e6281c26674e03 Ang Tien Sung                         2022-07-11  1990  	chans[2].ctrl = controller;
e6281c26674e03 Ang Tien Sung                         2022-07-11  1991  	chans[2].name = SVC_CLIENT_FCS;
e6281c26674e03 Ang Tien Sung                         2022-07-11  1992  	spin_lock_init(&chans[2].lock);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1993  	ret = kfifo_alloc(&chans[2].svc_fifo, fifo_size, GFP_KERNEL);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1994  	if (ret) {
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1995  		dev_err(dev, "failed to allocate FIFO 2\n");
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1996  		return ret;
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1997  	}
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  1998  	spin_lock_init(&chans[2].svc_fifo_lock);
e6281c26674e03 Ang Tien Sung                         2022-07-11  1999  
4f49088c162579 Khairul Anuar Romli                   2025-10-08  2000  	chans[3].scl = NULL;
4f49088c162579 Khairul Anuar Romli                   2025-10-08  2001  	chans[3].ctrl = controller;
4f49088c162579 Khairul Anuar Romli                   2025-10-08  2002  	chans[3].name = SVC_CLIENT_HWMON;
4f49088c162579 Khairul Anuar Romli                   2025-10-08  2003  	spin_lock_init(&chans[3].lock);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2004  	ret = kfifo_alloc(&chans[3].svc_fifo, fifo_size, GFP_KERNEL);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2005  	if (ret) {
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2006  		dev_err(dev, "failed to allocate FIFO 3\n");
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2007  		return ret;
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2008  	}
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2009  	spin_lock_init(&chans[3].svc_fifo_lock);
4f49088c162579 Khairul Anuar Romli                   2025-10-08  2010  
7ca5ce896524f5 Richard Gong                          2018-11-13  2011  	list_add_tail(&controller->node, &svc_ctrl);
7ca5ce896524f5 Richard Gong                          2018-11-13  2012  	platform_set_drvdata(pdev, controller);
7ca5ce896524f5 Richard Gong                          2018-11-13  2013  
b5dc75c915cdae Richard Gong                          2019-09-03  2014  	/* add svc client device(s) */
b5dc75c915cdae Richard Gong                          2019-09-03  2015  	svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
d99247f9b54253 Christophe JAILLET                    2021-05-21  2016  	if (!svc) {
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2017  		return -ENOMEM;
d99247f9b54253 Christophe JAILLET                    2021-05-21  2018  	}
d0fcf70c680e4d Khairul Anuar Romli                   2025-11-03  2019  	controller->svc = svc;
b5dc75c915cdae Richard Gong                          2019-09-03  2020  
b5dc75c915cdae Richard Gong                          2019-09-03  2021  	svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0);
b5dc75c915cdae Richard Gong                          2019-09-03  2022  	if (!svc->stratix10_svc_rsu) {
b5dc75c915cdae Richard Gong                          2019-09-03  2023  		dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2024  		return -ENOMEM;
b5dc75c915cdae Richard Gong                          2019-09-03  2025  	}
b5dc75c915cdae Richard Gong                          2019-09-03  2026  
b5dc75c915cdae Richard Gong                          2019-09-03  2027  	ret = platform_device_add(svc->stratix10_svc_rsu);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2028  	if (ret)
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2029  		goto err_put_device;
d99247f9b54253 Christophe JAILLET                    2021-05-21  2030  
4d239f447f96bd Mahesh Rao                            2025-03-26  2031  	ret = of_platform_default_populate(dev_of_node(dev), NULL, dev);
4d239f447f96bd Mahesh Rao                            2025-03-26  2032  	if (ret)
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2033  		goto err_put_device;
4d239f447f96bd Mahesh Rao                            2025-03-26  2034  
7ca5ce896524f5 Richard Gong                          2018-11-13  2035  	pr_info("Intel Service Layer Driver Initialized\n");
7ca5ce896524f5 Richard Gong                          2018-11-13  2036  
d99247f9b54253 Christophe JAILLET                    2021-05-21  2037  	return 0;
d99247f9b54253 Christophe JAILLET                    2021-05-21  2038  
bcb9f4f0706147 Mahesh Rao                            2025-10-27  2039  err_async_exit:
bcb9f4f0706147 Mahesh Rao                            2025-10-27  2040  	stratix10_svc_async_exit(controller);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2041  err_put_device:
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2042  	platform_device_put(svc->stratix10_svc_rsu);
9175ee1a99d57e Yang Yingliang                        2022-11-29  2043  err_destroy_pool:
9175ee1a99d57e Yang Yingliang                        2022-11-29  2044  	gen_pool_destroy(genpool);
1b2cdbfded37a9 Muhammad Amirul Asyraf Mohamad Jamian 2026-02-02  2045  
7ca5ce896524f5 Richard Gong                          2018-11-13  2046  	return ret;
7ca5ce896524f5 Richard Gong                          2018-11-13  2047  }
7ca5ce896524f5 Richard Gong                          2018-11-13  2048  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki