From nobody Thu Apr 2 00:08:12 2026 Received: from DM5PR21CU001.outbound.protection.outlook.com (mail-centralusazon11011020.outbound.protection.outlook.com [52.101.62.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A98A377EBC for ; Thu, 5 Mar 2026 09:31:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.62.20 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772703121; cv=fail; b=KV/ZOdz4CI9z1KMnUII95aRUqxXT4zCmglHoZdSR6nMGcDfU1xpk1uuUupDF2/hSQ0z2WZ0koCMFzuq+GXv05DoYILgCBCNBuA6IravzW0brkSmhQXmtTHf5JBZ0qfGdq5csmaeGTKE2NWNNL2p9HpLEBEVxoJ/8cWidtbXk6do= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772703121; c=relaxed/simple; bh=1wFLXlistwAjAbQQma73GTQsE9/fJzeuBlrJeUjSrHI=; h=From:To:Cc:Subject:Date:Message-Id:Content-Type:MIME-Version; b=T/q1+SEvcvNDFBKCsfSwyrW6hrwSL4n+CpmzDj/rZWUZAxQVwlB6fSZEhYvIo/7LsWhUS++Dut8ASGLBNKpuecgaO/hr/pc/+ss+FBYbTgPJWqUeY+gk/Ho4Xf5wxETC/8va0kSEtsaME8Bt3/Bb8Od0uYXpkKa8GWzzmaj3baI= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=altera.com; spf=pass smtp.mailfrom=altera.com; dkim=pass (2048-bit key) header.d=altera.com header.i=@altera.com header.b=pSfn8d63; arc=fail smtp.client-ip=52.101.62.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=altera.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=altera.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=altera.com header.i=@altera.com header.b="pSfn8d63" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Oh+vsgziaFm1Cguir/GW6c/pO8bzamq4TrAT5vZPVAPTf7//4nEScg9tHK7WUEPoTXLlWYbhIsFYqDij7+PZT98BIRXvcGHcqSMRCeSCQHwzHe7SJh9EIz6Jfh7TzdonTA4idYjW/eiMUwLh3kDcOAsHqRrnkeFBK8z8Jta9UyEBH4Tgi9Ikw2sfnbMA3fyb4HCEBo0F+DdfDJsaHpT4iWM0jru3pX8NQiO0bvWRp7/TKcI0kdsvJdNi6fTvwxSBvQkmLxIVZt0z7joK105miLf0Kv2K15dqzxy3CSy9mKwmdBIgMdin0G47C1mqhmNqZe+Hueevg7Vv2Q0tQLqvjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=IK/VIq7G73Rf9nw+UYwYKk1HL88PJkBhs2/7z9BdK1A=; b=bD2unn4vIQ7w1Na2TGhfV4yC3m0SWHAMYznaUmINCyCZkCFUgycTnbGD/PI4QUTYKkEFmFFGj6tRAKMrp5nvYSLD3aiVB8XiIGzKXVjg1cxsB9nAGyCFCLWsdjfEza38k+HkVmnr8fr8EJxhyzKTQpLYnY3ee6l8Et+gHrKuq0usGfWFqrT/AtmhmHDd23gvByIgEPreBytM+976VVTv01kMbK8rri+81nzPmNOwiVL5tat9y7qhYx7J5g1lJwn24s99RdyG7Gt7yGbvEqvdzu2QC1Bxv2BRTbLo4VvAZ51eDOS5Irr9+1LB5pGPkRW+SLLJR8aKszNLZmuyx5GdYw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=altera.com; dmarc=pass action=none header.from=altera.com; dkim=pass header.d=altera.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=altera.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IK/VIq7G73Rf9nw+UYwYKk1HL88PJkBhs2/7z9BdK1A=; b=pSfn8d63BUEmHXfhotoMR+2wNlUBs6UW2YqXQp8kPrOdHrUfYnC92Rtj16BKD/EtHRfeLpmIIqpXEZk8D7XO2XPAa8usR+UzP5fi3Cy9dTq+BnM39tm92LJQv8/ioEpWSguu2u5/1DuYRiL5U4wLolCORhjvQ6rS7ZR3TntY5nE+1rwk1eh22rvZukK89gg19eko3AxtQTnfAid5WgNu/Tfu6Pub0rHcBfnK1Vtc3A3CWr7h6fMZAstGT013A7bXqIo3vIlMI5v9etbC5fWtG2XEFr9mejVA7cgHsfwCBMzVwJhJidN0L16oLpCn6HREoXhM00DPKQ6zPfNrjl1QeQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=altera.com; Received: from BLAPR03MB5458.namprd03.prod.outlook.com (2603:10b6:208:29d::17) by DSWPR03MB989165.namprd03.prod.outlook.com (2603:10b6:8:362::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9678.18; Thu, 5 Mar 2026 09:31:54 +0000 Received: from BLAPR03MB5458.namprd03.prod.outlook.com ([fe80::7eda:fa34:15f9:e656]) by BLAPR03MB5458.namprd03.prod.outlook.com ([fe80::7eda:fa34:15f9:e656%5]) with mapi id 15.20.9678.017; Thu, 5 Mar 2026 09:31:54 +0000 From: Muhammad Amirul Asyraf Mohamad Jamian To: Dinh Nguyen , linux-kernel@vger.kernel.org, Ang Tien Sung Cc: Markus Elfring Subject: [PATCH v6] firmware: stratix10-svc: Add Multi SVC clients support Date: Thu, 5 Mar 2026 01:31:51 -0800 Message-Id: <20260305093151.2678-1-muhammad.amirul.asyraf.mohamad.jamian@altera.com> X-Mailer: git-send-email 2.26.2 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SJ0PR05CA0166.namprd05.prod.outlook.com (2603:10b6:a03:339::21) To BLAPR03MB5458.namprd03.prod.outlook.com (2603:10b6:208:29d::17) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BLAPR03MB5458:EE_|DSWPR03MB989165:EE_ X-MS-Office365-Filtering-Correlation-Id: 565aac47-ae99-4ec1-0f2b-08de7a9a0997 X-MS-Exchange-AtpMessageProperties: SA X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014; X-Microsoft-Antispam-Message-Info: vAoGCt2bLGeYGn953VHP0RgQfNk+n0/n9ZgA6pDG1Msmp6VBd0EWa6qUBJQ9OjrqgATetWgLpixlB2cmL4us6R3R5c/Eox9obZWAS1cdAIi6M6rQb7qnqAK/fEuyVjzuLD4It3wGkbtwThNed71tAh1umw7XG73mIBFWqiTjRLjVKSq5Mo10Ipv+RCcwswBWVgZIDd+WETD0uUpGFJjujXcurviP/t4h4k1+f7YSArT5zV/D0eknMCWdayropRwIR7/Zx6SwLO9+Ot4DD2N139XxypHccPcxwRx5M6Q5IppgqiUg0GEzD/mGAoypN2aSJNPr4lXfFasj2kr0hfSDb0hcuMyF9q6O9OTWoguhspKkpcglQlZ57sdytRlZCGgLG196pzUhCH0uxBCYvQjch3TfxbmnJB9SgX2I8NxOK0q25AyKTGjA9vPY2FRdz0Rp95tK7XcMvC7y4RSbgPLxaO0oBcRxP3BIaAqp1YBJk06Evg7H9zg9dYtIjmQ/RtmMY7Yt153Q/wYpwatoZxEYqI7mA4hjgWRWd6Dh8H91eqn0qdyYJi5xMez3R8sUcFc3nhgKeeKoWyDRFvcKs7fgE/kdH4RFJJhA8Fv4OjD6Jx02e0KPzoNsuOg33XwoYKAikps2jHj1TA/bhJOmfLu9NGbZLJaoNujAha/LzgbVo+vDrytxnv97TFAKdaNQA5jOQwerCG0+40lpQn87d4e87Q3f7KiDvgYaf+CgdgwCh4c= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BLAPR03MB5458.namprd03.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?W5tOOy6g3lk8Fab2xnH2febmW1+ACgpHMAI4ZN6G7fPN7wl3K1SSMRWfjNiG?= =?us-ascii?Q?CtxUw3fdb4x8NRnnk6IBCK+iLhP8gdBLWSZ9IPxl86yfHz2yU59fiEOBls0K?= =?us-ascii?Q?wyxBFUHfa5GrrAPOfPB1GJVmk5QgPgEXrNyA858WSkgl3y5tK2MHCPkjXUmp?= =?us-ascii?Q?xwuZ9/OFcnLnAYiZZ1PKfHR72a4EvVdKi7fdWTzjt/R4v6x7RAe1wvhZVQ3d?= =?us-ascii?Q?9h+e/L5CjAzgYR87LGTCpo3o0m0Q2rS8Hp9NiQt7w9wnktEyV2eGm7V/hQ9M?= =?us-ascii?Q?zzSKqdC2FhrvYTCwTN5rLb5J5COrz0PWA3KUuJwm50VD3g6Mz+sXE2cryjcX?= =?us-ascii?Q?aRvP+24FyObvZbjMLhFMmgr2bQ0lF5Vc42ep07YyGPodY74RoMFvNfO37qEO?= =?us-ascii?Q?FOaEwgGsr3maxuFve/mhJTXUHiQ8lpIVIn+jMjQnkCBbLDyGrfOl0WAebfpV?= =?us-ascii?Q?CVRbp93QKwDLTzcmDLat2oywjw15zzK2zYzsMAsA3NFeNNg/1o4rz0r1DnHh?= =?us-ascii?Q?5HUqBtnSKKzgavPetriiYOwn4Yr2myBwgU7NnK1zB7klbJBm9VwJH6ox7dix?= =?us-ascii?Q?mj0uKklHYsNXrsZWqI1XxQVULxQfWU65v75jgKaHTqaQz9EF14GUFKlFQRrH?= =?us-ascii?Q?riK3apeOPQY8LhaCuqixCFqYhkPTHXWO3NjPi25ba/tfC/Rh9wvRIQgFpguG?= =?us-ascii?Q?OaNpLYIp6E3ALPgBPkaX8sC7bfW4+IC9tOf1JyeGGRmmSYToFb5/tv7/UOYu?= =?us-ascii?Q?mtY4f8VbwIbLfHadLOT8eTHoa09/iAMopOZlaQeQcD6UovEwpkB1LWEdaUj5?= =?us-ascii?Q?7ju16neohlEuT2KoI1obu/NvIv18EZxEYkhquBtN/tAqzFXwVjwFI95v0dhH?= =?us-ascii?Q?ul/p6OU1lQh4C8ABB1rwP1SbHQs9uGi1DWfvBZaOH01CWvD479DtAybVyLxM?= =?us-ascii?Q?I5sE7vr9I9r8FkA4RdqVfU4eQFXn3uZK35iX1N1MZaTk6A3GScm2ZS02/Aif?= =?us-ascii?Q?6Wav49xiR7LuZpqWrfhFYdr8fe5AObR72/vXmiAPZUP74auC/nAdeYhw769y?= =?us-ascii?Q?lqnPrWSbmN63Meu915abmmjGfhibBheSFawy/Td/qDDL9Re5uS6oe8E6qB5+?= =?us-ascii?Q?VbNFbmLyC/rSMMFKPMtPgOI8pQadcbeozSLzEqPs2i3VJfFgLd+LFI647N+a?= =?us-ascii?Q?1FT876VRVxAeEEGD24b7l3hVASeMAY1V6MUg4BH6KaV7+Nh+Wx5YcNtMTXHh?= =?us-ascii?Q?xWEusWYFtC52eiM+E6ERKuKUdkG0fwI9DRt6mVzJC6i0DC71VTdgLD/7XI3G?= =?us-ascii?Q?EczXbIItEjS8/DNUXVoQOuC171JE0krrJokE5CUnsYVjk7DgtJ2cDOCqkcbO?= =?us-ascii?Q?+g/jxH2IGtIAjiv7HLIz2b9yrdWjYcKnMsrZYp5qntPb1osIUDq3UC6tCyT5?= =?us-ascii?Q?5F15U1lu57WsY55CeDVgOUm+LTRR9RBFvzsuM5ksGdQMKBf49e39hH2RZCXj?= =?us-ascii?Q?/dM3C1dpTKhuVQXbPGhwoYnjjoqIBdVAneqiLNGzOli1LgrAuzSZXxLnF4/y?= =?us-ascii?Q?rBjBHNTdYTN6PRFvIbnwimD4AhiiZ+L/N9KVp2WLfQ2px2Hi2Ct/QnF5LvcJ?= =?us-ascii?Q?Og9owZgXWi7snF0cc/E335LNHx3w+4Vwrhn6C+V3Wps7EW93X6ykuMQC86Zo?= =?us-ascii?Q?RjF5MXosFIvNtnvfL7P/ujzccTg5Dt3p9mUFTK/hzQ2aJZJMWoC7XQAdUH2o?= =?us-ascii?Q?mFklliZZKbckvBipkVAEFAPkjFfj+y0wZGI3j9x/uRSjjvb/nLFB+P9/SiMG?= X-MS-Exchange-AntiSpam-MessageData-1: 2q6onHsA1oisVA== X-OriginatorOrg: altera.com X-MS-Exchange-CrossTenant-Network-Message-Id: 565aac47-ae99-4ec1-0f2b-08de7a9a0997 X-MS-Exchange-CrossTenant-AuthSource: BLAPR03MB5458.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Mar 2026 09:31:54.1554 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: fbd72e03-d4a5-4110-adce-614d51f2077a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 5yNW43xQEwzw+FtVleEHH8HG56MGO6xkLLlGwvI0h5H3uCm8a/LS/OH6yY/hDmvCSLlAidaxS14lDapykmJlPm3SCiZ/4KZqSkyxJq23adPTG4EGbEDBgqd2zU5WlxbVtaCygPs6tF45+H/YWaHLxNjdvktcztV4TcmOWdxkEZ4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DSWPR03MB989165 Content-Type: text/plain; charset="utf-8" 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 support 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. SVC_NUM_DATA_IN_FIFO is reduced from 32 to 8, since each channel now has its own dedicated FIFO and the SDM processes commands one at a time. 8 entries per channel is sufficient while keeping the total aggregate capacity the same (4 channels x 8 =3D 32 entries). 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. Fixes: 7ca5ce896524 ("firmware: add Intel Stratix10 service layer driver") Cc: stable@vger.kernel.org Signed-off-by: Ang Tien Sung Signed-off-by: Fong, Yan Kei Signed-off-by: Muhammad Amirul Asyraf Mohamad Jamian Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202602032325.MuglZ156-lkp@int= el.com/ --- Changes in v6: - Fix sdm_lock: embed struct mutex directly in stratix10_svc_controller instead of using a pointer to a global mutex - Fix probe error path: adding back err_unregister_rsu_dev: label that calls platform_device_unregister() when of_platform_default_populate() fails after platform_device_add() succeeded - Fix scheduling while atomic: move kthread_run_on_cpu() outside spin_lock(&chan->lock); kthread creation sleeps internally via wait_for_completion_killable() which is illegal while holding a spinlock. Thread is created first, then assigned under lock with lost-race discard to preserve TOCTOU protection. - Add commit message explanation for SVC_NUM_DATA_IN_FIFO 32->8 reduction Changes in v5: - Fix mutex locking: replace guard(mutex) with explicit lock/unlock, use mutex_lock_interruptible() so kthread_stop() can unblock the thread when the SDM lock is contended, fix lock/unlock imbalances, and on interrupted lock notify client with SVC_STATUS_ERROR so it does not block on a response that never arrives - Fix TOCTOU race in stratix10_svc_send(): protect chan->task creation with chan->lock spinlock to prevent concurrent callers on the same channel from spawning duplicate threads - Fix probe error path: initialize controller->node with INIT_LIST_HEAD and guard list_del() so it is only called when list_add_tail() was reached, preventing NULL deref on early FIFO allocation failure - Remove stray platform_device_unregister(svc->intel_svc_fcs) call in remove function, as FCS device is not manually registered in probe; also remove the now-unused INTEL_FCS macro, stale intel_svc_fcs field from struct stratix10_svc, and stale @task kdoc from struct stratix10_svc_controller - Remove unnecessary NULL check on svc pointer in err_put_device - Clean up: convert FIFO allocations to for loop, simplify stratix10_svc_done() to a single debug message, fix whitespace, typos and log messages Changes in v4: - Signed-off-by chain clean up - Remove duplicate inline comment on sdm_lock field - Move structure field comments to structure header - Remove unnecessary checks in stratix10_svc_done() - Fix error handling to properly free FIFOs on probe failure - Reorder error labels for proper cleanup cascade - Remove redundant fifo_size initialization Changes in v3: - Fix grammar: "will supports" -> "will support" - Add Fixes tag and Cc stable as suggested by reviewer Changes in v2: - Initialize 'svc' to NULL and add NULL check in error path to fix uninitia= lized variable warning --- drivers/firmware/stratix10-svc.c | 228 ++++++++++-------- .../firmware/intel/stratix10-svc-client.h | 8 +- 2 files changed, 130 insertions(+), 106 deletions(-) diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-= svc.c index 6f5c298582ab..e9e35d67ef96 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -37,15 +37,14 @@ * 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 =20 /* stratix10 service layer clients */ #define STRATIX10_RSU "stratix10-rsu" -#define INTEL_FCS "intel-fcs" =20 /* Maximum number of SDM client IDs. */ #define MAX_SDM_CLIENT_IDS 16 @@ -105,11 +104,9 @@ struct stratix10_svc_chan; /** * struct stratix10_svc - svc private data * @stratix10_svc_rsu: pointer to stratix10 RSU device - * @intel_svc_fcs: pointer to the FCS device */ struct stratix10_svc { struct platform_device *stratix10_svc_rsu; - struct platform_device *intel_svc_fcs; }; =20 /** @@ -251,12 +248,10 @@ struct stratix10_async_ctrl { * @num_active_client: number of active service client * @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 client= s, to @@ -269,12 +264,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; struct stratix10_async_ctrl actrl; }; =20 @@ -283,6 +276,9 @@ struct stratix10_svc_controller { * @ctrl: pointer to service controller which is the provider of this chan= nel * @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 (separate fifo for = every channel) + * @svc_fifo_lock: protect access to service message data queue (locking p= ending fifo) * @lock: protect access to the channel * @async_chan: reference to asynchronous channel object for this channel * @@ -293,6 +289,9 @@ struct stratix10_svc_chan { struct stratix10_svc_controller *ctrl; struct stratix10_svc_client *scl; char *name; + struct task_struct *task; + struct kfifo svc_fifo; + spinlock_t svc_fifo_lock; spinlock_t lock; struct stratix10_async_chan *async_chan; }; @@ -527,10 +526,10 @@ static void svc_thread_recv_status_ok(struct stratix1= 0_svc_data *p_data, */ static int svc_normal_to_secure_thread(void *data) { - struct stratix10_svc_controller - *ctrl =3D (struct stratix10_svc_controller *)data; - struct stratix10_svc_data *pdata; - struct stratix10_svc_cb_data *cbdata; + struct stratix10_svc_chan *chan =3D (struct stratix10_svc_chan *)data; + struct stratix10_svc_controller *ctrl =3D chan->ctrl; + struct stratix10_svc_data *pdata =3D NULL; + struct stratix10_svc_cb_data *cbdata =3D NULL; struct arm_smccc_res res; unsigned long a0, a1, a2, a3, a4, a5, a6, a7; int ret_fifo =3D 0; @@ -555,12 +554,12 @@ static int svc_normal_to_secure_thread(void *data) a6 =3D 0; a7 =3D 0; =20 - pr_debug("smc_hvc_shm_thread is running\n"); + pr_debug("%s: %s: Thread is running!\n", __func__, chan->name); =20 while (!kthread_should_stop()) { - ret_fifo =3D kfifo_out_spinlocked(&ctrl->svc_fifo, + ret_fifo =3D kfifo_out_spinlocked(&chan->svc_fifo, pdata, sizeof(*pdata), - &ctrl->svc_fifo_lock); + &chan->svc_fifo_lock); =20 if (!ret_fifo) continue; @@ -569,9 +568,25 @@ static int svc_normal_to_secure_thread(void *data) (unsigned int)pdata->paddr, pdata->command, (unsigned int)pdata->size); =20 + /* SDM can only process one command at a time */ + pr_debug("%s: %s: Thread is waiting for mutex!\n", + __func__, chan->name); + if (mutex_lock_interruptible(&ctrl->sdm_lock)) { + /* item already dequeued; notify client to unblock it */ + cbdata->status =3D BIT(SVC_STATUS_ERROR); + cbdata->kaddr1 =3D NULL; + cbdata->kaddr2 =3D NULL; + cbdata->kaddr3 =3D NULL; + if (pdata->chan->scl) + pdata->chan->scl->receive_cb(pdata->chan->scl, + cbdata); + break; + } + switch (pdata->command) { case COMMAND_RECONFIG_DATA_CLAIM: svc_thread_cmd_data_claim(ctrl, pdata, cbdata); + mutex_unlock(&ctrl->sdm_lock); continue; case COMMAND_RECONFIG: a0 =3D INTEL_SIP_SMC_FPGA_CONFIG_START; @@ -700,10 +715,11 @@ static int svc_normal_to_secure_thread(void *data) break; default: pr_warn("it shouldn't happen\n"); - break; + mutex_unlock(&ctrl->sdm_lock); + continue; } - pr_debug("%s: before SMC call -- a0=3D0x%016x a1=3D0x%016x", - __func__, + pr_debug("%s: %s: before SMC call -- a0=3D0x%016x a1=3D0x%016x", + __func__, chan->name, (unsigned int)a0, (unsigned int)a1); pr_debug(" a2=3D0x%016x\n", (unsigned int)a2); @@ -712,8 +728,8 @@ static int svc_normal_to_secure_thread(void *data) pr_debug(" a5=3D0x%016x\n", (unsigned int)a5); ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); =20 - pr_debug("%s: after SMC call -- res.a0=3D0x%016x", - __func__, (unsigned int)res.a0); + pr_debug("%s: %s: after SMC call -- res.a0=3D0x%016x", + __func__, chan->name, (unsigned int)res.a0); pr_debug(" res.a1=3D0x%016x, res.a2=3D0x%016x", (unsigned int)res.a1, (unsigned int)res.a2); pr_debug(" res.a3=3D0x%016x\n", (unsigned int)res.a3); @@ -728,6 +744,7 @@ static int svc_normal_to_secure_thread(void *data) cbdata->kaddr2 =3D NULL; cbdata->kaddr3 =3D NULL; pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata); + mutex_unlock(&ctrl->sdm_lock); continue; } =20 @@ -801,6 +818,8 @@ static int svc_normal_to_secure_thread(void *data) break; =20 } + + mutex_unlock(&ctrl->sdm_lock); } =20 kfree(cbdata); @@ -1696,22 +1715,33 @@ int stratix10_svc_send(struct stratix10_svc_chan *c= han, void *msg) if (!p_data) return -ENOMEM; =20 - /* first client will create kernel thread */ - if (!chan->ctrl->task) { - chan->ctrl->task =3D - kthread_run_on_cpu(svc_normal_to_secure_thread, - (void *)chan->ctrl, - cpu, "svc_smc_hvc_thread"); - if (IS_ERR(chan->ctrl->task)) { + /* first caller creates the per-channel kthread */ + if (!chan->task) { + struct task_struct *task; + + task =3D kthread_run_on_cpu(svc_normal_to_secure_thread, + (void *)chan, + cpu, "svc_smc_hvc_thread"); + if (IS_ERR(task)) { dev_err(chan->ctrl->dev, "failed to create svc_smc_hvc_thread\n"); kfree(p_data); return -EINVAL; } + + spin_lock(&chan->lock); + if (chan->task) { + /* another caller won the race; discard our thread */ + spin_unlock(&chan->lock); + kthread_stop(task); + } else { + chan->task =3D task; + spin_unlock(&chan->lock); + } } =20 - pr_debug("%s: sent P-va=3D%p, P-com=3D%x, P-size=3D%u\n", __func__, - p_msg->payload, p_msg->command, + pr_debug("%s: %s: sent P-va=3D%p, P-com=3D%x, P-size=3D%u\n", __func__, + chan->name, p_msg->payload, p_msg->command, (unsigned int)p_msg->payload_length); =20 if (list_empty(&svc_data_mem)) { @@ -1747,12 +1777,16 @@ int stratix10_svc_send(struct stratix10_svc_chan *c= han, void *msg) p_data->arg[2] =3D p_msg->arg[2]; p_data->size =3D p_msg->payload_length; p_data->chan =3D chan; - pr_debug("%s: put to FIFO pa=3D0x%016x, cmd=3D%x, size=3D%u\n", __func__, - (unsigned int)p_data->paddr, p_data->command, - (unsigned int)p_data->size); - ret =3D kfifo_in_spinlocked(&chan->ctrl->svc_fifo, p_data, + pr_debug("%s: %s: put to FIFO pa=3D0x%016x, cmd=3D%x, size=3D%u\n", + __func__, + chan->name, + (unsigned int)p_data->paddr, + p_data->command, + (unsigned int)p_data->size); + + ret =3D kfifo_in_spinlocked(&chan->svc_fifo, p_data, sizeof(*p_data), - &chan->ctrl->svc_fifo_lock); + &chan->svc_fifo_lock); =20 kfree(p_data); =20 @@ -1773,11 +1807,12 @@ 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 <=3D 1) { - pr_debug("svc_smc_hvc_shm_thread is stopped\n"); - kthread_stop(chan->ctrl->task); - chan->ctrl->task =3D NULL; + /* stop thread when thread is running */ + if (chan->task) { + pr_debug("%s: %s: svc_smc_hvc_shm_thread is stopping\n", + __func__, chan->name); + kthread_stop(chan->task); + chan->task =3D NULL; } } EXPORT_SYMBOL_GPL(stratix10_svc_done); @@ -1817,8 +1852,8 @@ void *stratix10_svc_allocate_memory(struct stratix10_= svc_chan *chan, pmem->paddr =3D pa; pmem->size =3D s; list_add_tail(&pmem->node, &svc_data_mem); - pr_debug("%s: va=3D%p, pa=3D0x%016x\n", __func__, - pmem->vaddr, (unsigned int)pmem->paddr); + pr_debug("%s: %s: va=3D%p, pa=3D0x%016x\n", __func__, + chan->name, pmem->vaddr, (unsigned int)pmem->paddr); =20 return (void *)va; } @@ -1855,6 +1890,13 @@ static const struct of_device_id stratix10_svc_drv_m= atch[] =3D { {}, }; =20 +static const char * const chan_names[SVC_NUM_CHANNEL] =3D { + SVC_CLIENT_FPGA, + SVC_CLIENT_RSU, + SVC_CLIENT_FCS, + SVC_CLIENT_HWMON +}; + static int stratix10_svc_drv_probe(struct platform_device *pdev) { struct device *dev =3D &pdev->dev; @@ -1862,11 +1904,11 @@ static int stratix10_svc_drv_probe(struct platform_= device *pdev) struct stratix10_svc_chan *chans; struct gen_pool *genpool; struct stratix10_svc_sh_memory *sh_memory; - struct stratix10_svc *svc; + struct stratix10_svc *svc =3D NULL; =20 svc_invoke_fn *invoke_fn; size_t fifo_size; - int ret; + int ret, i =3D 0; =20 /* get SMC or HVC function */ invoke_fn =3D get_invoke_func(dev); @@ -1905,8 +1947,8 @@ static int stratix10_svc_drv_probe(struct platform_de= vice *pdev) controller->num_active_client =3D 0; controller->chans =3D chans; controller->genpool =3D genpool; - controller->task =3D NULL; controller->invoke_fn =3D invoke_fn; + INIT_LIST_HEAD(&controller->node); init_completion(&controller->complete_status); =20 ret =3D stratix10_svc_async_init(controller); @@ -1917,32 +1959,20 @@ static int stratix10_svc_drv_probe(struct platform_= device *pdev) } =20 fifo_size =3D sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO; - ret =3D kfifo_alloc(&controller->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); - - chans[0].scl =3D NULL; - chans[0].ctrl =3D controller; - chans[0].name =3D SVC_CLIENT_FPGA; - spin_lock_init(&chans[0].lock); + mutex_init(&controller->sdm_lock); =20 - chans[1].scl =3D NULL; - chans[1].ctrl =3D controller; - chans[1].name =3D SVC_CLIENT_RSU; - spin_lock_init(&chans[1].lock); - - chans[2].scl =3D NULL; - chans[2].ctrl =3D controller; - chans[2].name =3D SVC_CLIENT_FCS; - spin_lock_init(&chans[2].lock); - - chans[3].scl =3D NULL; - chans[3].ctrl =3D controller; - chans[3].name =3D SVC_CLIENT_HWMON; - spin_lock_init(&chans[3].lock); + for (i =3D 0; i < SVC_NUM_CHANNEL; i++) { + chans[i].scl =3D NULL; + chans[i].ctrl =3D controller; + chans[i].name =3D (char *)chan_names[i]; + spin_lock_init(&chans[i].lock); + ret =3D kfifo_alloc(&chans[i].svc_fifo, fifo_size, GFP_KERNEL); + if (ret) { + dev_err(dev, "failed to allocate FIFO %d\n", i); + goto err_free_fifos; + } + spin_lock_init(&chans[i].svc_fifo_lock); + } =20 list_add_tail(&controller->node, &svc_ctrl); platform_set_drvdata(pdev, controller); @@ -1951,7 +1981,7 @@ static int stratix10_svc_drv_probe(struct platform_de= vice *pdev) svc =3D devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL); if (!svc) { ret =3D -ENOMEM; - goto err_free_kfifo; + goto err_free_fifos; } controller->svc =3D svc; =20 @@ -1959,51 +1989,43 @@ static int stratix10_svc_drv_probe(struct platform_= device *pdev) if (!svc->stratix10_svc_rsu) { dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU); ret =3D -ENOMEM; - goto err_free_kfifo; + goto err_free_fifos; } =20 ret =3D platform_device_add(svc->stratix10_svc_rsu); - if (ret) { - platform_device_put(svc->stratix10_svc_rsu); - goto err_free_kfifo; - } - - svc->intel_svc_fcs =3D platform_device_alloc(INTEL_FCS, 1); - if (!svc->intel_svc_fcs) { - dev_err(dev, "failed to allocate %s device\n", INTEL_FCS); - ret =3D -ENOMEM; - goto err_unregister_rsu_dev; - } - - ret =3D 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; =20 ret =3D of_platform_default_populate(dev_of_node(dev), NULL, dev); if (ret) - goto err_unregister_fcs_dev; + goto err_unregister_rsu_dev; =20 pr_info("Intel Service Layer Driver Initialized\n"); =20 return 0; =20 -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: + goto err_free_fifos; +err_put_device: + platform_device_put(svc->stratix10_svc_rsu); +err_free_fifos: + /* only remove from list if list_add_tail() was reached */ + if (!list_empty(&controller->node)) + list_del(&controller->node); + /* free only the FIFOs that were successfully allocated */ + while (i--) + kfifo_free(&chans[i].svc_fifo); stratix10_svc_async_exit(controller); err_destroy_pool: gen_pool_destroy(genpool); + return ret; } =20 static void stratix10_svc_drv_remove(struct platform_device *pdev) { + int i; struct stratix10_svc_controller *ctrl =3D platform_get_drvdata(pdev); struct stratix10_svc *svc =3D ctrl->svc; =20 @@ -2011,14 +2033,16 @@ static void stratix10_svc_drv_remove(struct platfor= m_device *pdev) =20 of_platform_depopulate(ctrl->dev); =20 - platform_device_unregister(svc->intel_svc_fcs); platform_device_unregister(svc->stratix10_svc_rsu); =20 - kfifo_free(&ctrl->svc_fifo); - if (ctrl->task) { - kthread_stop(ctrl->task); - ctrl->task =3D NULL; + for (i =3D 0; i < SVC_NUM_CHANNEL; i++) { + if (ctrl->chans[i].task) { + kthread_stop(ctrl->chans[i].task); + ctrl->chans[i].task =3D 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 =20 struct stratix10_svc_chan; =20 --=20 2.43.7