From nobody Thu Apr 16 06:43:56 2026 Received: from BL2PR02CU003.outbound.protection.outlook.com (mail-eastusazon11011040.outbound.protection.outlook.com [52.101.52.40]) (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 BDAE12BEFE8 for ; Mon, 2 Mar 2026 05:39:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.52.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772429991; cv=fail; b=pYhzfBdXlnQAVdwBemPXVJ/QY7YqcDBY0Xp7Afm0nS+1AvG+ENFvZ1raUm5Ti3EntOPv9BCgIHLe8cPwWuhTyfWJvXV6d4OAKuH8BlV3w1pXRJ+Ju8/05HPBaVDidGzHmvs31cITI6GoSVsXpEvePvg2vzTz1AzFqvQiatZMEmg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772429991; c=relaxed/simple; bh=Nszpm+921Ja73RdQByxRREC7RfDrOPfPlVowd0e5Cgg=; h=From:To:Cc:Subject:Date:Message-Id:Content-Type:MIME-Version; b=bvxh6ZRs4hwLTrTSJu/PygvnMdkImegkvE2xVKGGY8c0w6bbKiyh1PqmXtSb93t5JzC19fqeGdHFdCeF/no1rGGMFwxBKP/wlAfhkMWvZtj80M/ca2X7I0lD1WcaWOd5djEtI7gkcaZHPfH0bT+lX23LPBUSKhDqr183vzLelpk= 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=QlAYCLXI; arc=fail smtp.client-ip=52.101.52.40 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="QlAYCLXI" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=EjF+ieOyt+7gfGJ/0Pn72VH8XyO4h5DMD/VWrY+QT1Ha/OrrljcN7JftBzfyvKlLRGCDOQldkanaDBpG2ZJEMfmkLjoRW+YBngpQ47KtYx+qIbNJ1ErQ1VS7bQ7MxrwwRRE+bPqyuMJPuG3iHQpfP+PpA/ZisrcIzp0NglI2dV8wPBDTPM9XhTTL44u8THbyaNMsP4Yz3fWuDcqAGuBkEerwowNbrFqatdzwxaibDxdkg5poXO3m8/SB6BD5ih3MHk3lo71iB99RWiyewKeRPbEJIUYH85+jSkSlNocoV05rdAz8sedMnduFyYVYg6ZMohgyXjRFHaia/8Y3rI0Ksw== 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=gTxwyO/zM566JQoqCM2zz8IQ1ktULT5Zay1zHeKRyPY=; b=teACRWDY50/hVvAYW2zgApwLKhgEg25PxQP4C0gmyWc3ZdEue0n6vQ8cnrHxJKz8pUkyjzZZtQEoLcsOqPrwE/56YQT/Jcgb4dFX2EtyT8eajtr3eCk9W+iOQSM7r/Q2WGpWhCHjqV/ghkf60N4IPP6n+BMogpgTdHaqECrrP3J97m315tbWlChYAp0+A9I3Q924bLMcE8ABQlATsxn/oQ7Jk2attlDUFZS81S0sJ/UfV+bwCXMdSRnO8PYsNDVQvuocHiiuO+Osaje10W3GGaed2R2YvCsnmkJs7r2UcwB8IS9N5J9c/wHvogTmKk/TeZwW5OlQs7Tqs48CqPqG9A== 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=gTxwyO/zM566JQoqCM2zz8IQ1ktULT5Zay1zHeKRyPY=; b=QlAYCLXId+0Sgb+Xjoo+IwnjCleUZUOrWgyOgnVpmviumMKgKJCBXWQt3d6GTfbPEJU+0mSbFBwVqXVxmJWfAoxakJYQ7BcXNen+NC7rCyXC+AXSe9Vks+LUAHst/JZYnwpikL0cx4AYtWTr4W5oJPIMVdIY5F8JeUml+sPessVZ5DSlsk9wfRgpU5364BWYAnAk2KTnNxRH3Q62ZRdeiBkxNa+aK2K0f4NDdDgTUaVDv9fsYHZY/mEJm742JLHxPd61jcHqAvz5KNYWr0aF1No6as0biYUuf3yWccKdFP1lVudZcjF/rQnbJBDdRcW7YX5EXbBRhhSmxY8Kj09h6g== 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 CH0PR03MB6097.namprd03.prod.outlook.com (2603:10b6:610:b8::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9654.21; Mon, 2 Mar 2026 05:39:47 +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.9654.020; Mon, 2 Mar 2026 05:39:47 +0000 From: Muhammad Amirul Asyraf Mohamad Jamian To: Dinh Nguyen , linux-kernel@vger.kernel.org, Ang Tien Sung Cc: Markus Elfring Subject: [PATCH v5] firmware: stratix10-svc: Add Multi SVC clients support Date: Sun, 1 Mar 2026 21:39:44 -0800 Message-Id: <20260302053944.14300-1-muhammad.amirul.asyraf.mohamad.jamian@altera.com> X-Mailer: git-send-email 2.26.2 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SJ0PR03CA0134.namprd03.prod.outlook.com (2603:10b6:a03:33c::19) 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_|CH0PR03MB6097:EE_ X-MS-Office365-Filtering-Correlation-Id: 29de1db6-6e02-4a30-2b17-08de781e1d47 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: lGVHKNrjA9ia26y9PJF27fEgtaFbl7PyzX6XelTRz3HDGabo8iDkVSo8EeH0vy22XrU7LmqutfzvkhhiZN6RDE+QGr/gNEMOsCbHfbbOgdxkwOn0RyT3nrCOSqorV77vrmeNzhzBxJniPPF+FXadyyS5tqM46ul+HsbnY9LbslAeRmmbJVOnAGRD82LUgC7CdPESGu3RG9Cd1o21/jX5fv5ibhb6xe9Xtdc0kIturo0rhjPqMCwiJhav0phcbUYL5GjQtt5jXUe/8225L4sd5TxK/mB+ZmKh2o9R/0c2aI/vDLfik6tp+pv+jH32tJC4fnBSOIqsFPF4LpYLNjO0pVZ84q+8IrsyOnDwbQClTwleZrg60yMpKqgSSB3RB0GgqTaw9M5lX899jwE2iWEmcL6QgN9ir+ZGqlneDrhLOiyXb6GM+6fMgk2/WUVwp2X1ITR2ziY0e2kfWjN4bJNv4xpR2j8HBrHwgzn1T0DHROUGSdP1oq5Ch9FQgLnLUs4mw8OzDFaG1XapIROHfAmlyEvDDjlQ/Z3sQVWylz6klBTtbKiojyUGJSB531hlygaz+FzHtbFa83DGZk0psYBxfUgKmXaxbUyENk432GvW7qFLca9jeo1iPds3MKP7XN7nnKDdZ+gsYCV53QHw3KL0NqhHzpvbGyRH5S2raKfqDEsr1z+jTwsjEZgdqG/lcaCan22jmYJL8ufhNnr+YsG6d4o7QMAf3NQejs3qJQCafLc= 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?EXT3AG2rTsgw/HzcGugAuvH81RHgIMcamfXVoItpVoN+Y19A7uIRe2NCN02G?= =?us-ascii?Q?KOWr1IQV5003gfkoWrO2ngDQaEMiA1tlcem2mKWLLZKj7Ndnqpp7+Vl12dFt?= =?us-ascii?Q?w+1zRTeCGprvJIDiFggTb2HhojBrIXgn/CK+XphInuBtvmueKKIRlLuYUnQb?= =?us-ascii?Q?jZVhNb7meiXvnLeEcKAc09nq0x6mquW+1oK4Nf57l5dxV5W/c3+gg2ls+Oc/?= =?us-ascii?Q?LH5CociAl7S+/DnknLFE3vTPYcGrFBbok7ZMYPwGHkaiTTC+S2tHSP6So2h6?= =?us-ascii?Q?KDc7NpzSkHJseJxsPmQ7RyDXK5F1Pig2WSIiMFMNZIx3yZ4s4ls0QpknwvV2?= =?us-ascii?Q?GTPKnpoZXHZ3Z9tymFeWP4ECu80swlF+00nQwKBsMCx/WJ2FDkMxdIPjKjuJ?= =?us-ascii?Q?vJrKdprMX0zF+oQuaCzIohWIsycbCL2gUrvVt8fohsGse1/TO/3oi/ZkWjK+?= =?us-ascii?Q?L6CO4SaGpJ9lqxKnd1xv67j2+WEswaI00ir4VL5Lk1yIxro45SKvL3CqKjqN?= =?us-ascii?Q?U75odh0SEtJqo2q2lKq0vn1vFzDYj/49ps0o/j0O3yIanSnxxyPkX0GeggfN?= =?us-ascii?Q?qQGtg8wRPzNO7pJ4pVEufdT4vTSEDI+p3AX9VHDZY7zeQ7NWCabulek/2OzE?= =?us-ascii?Q?PdAAH+pr5M4FLJfHsPOVsjFuoyt+5/V9JWejehXUhzKZKz/P2G2UaDhJYWpv?= =?us-ascii?Q?ZML+E9TQQf+tUVsdmjoaDu+QzkbGvFmWRfh+59fGk5PifE1uQLxEuIa2HI+u?= =?us-ascii?Q?7PXidNsE8NZ96eqnlhqEkcjXClEZSJoGPAkgaikA2L3/d23lM6f5zr+sb6nI?= =?us-ascii?Q?CmAo3eFqt+bkDv03RZ18nZpt+nap8S3yJN9Yur4f0liEovwrGT2p8TyYNSPt?= =?us-ascii?Q?FvB6/m0rouZfY19VnFZWohRSRl6/nl95w8Vv/J+HU66QIkAnIq8YXoFnfSup?= =?us-ascii?Q?HWj/3wGKYvBTq6liGVNblY6FJeEjxuwHTeUCVlktkt9HcE5BSN+lH7yPquuM?= =?us-ascii?Q?5Q/Tj0dhbnPiahl7ReKKq0D8ASOGLHoNLoecF7UqPjeYyJMz8TNVSbaN99cN?= =?us-ascii?Q?IcnJBv++Inlu1ScHbgJtdTiWBm2WYjpWPh1VOyBxnI73dRFZ6t4adfkta4XI?= =?us-ascii?Q?a3ntZetG16Po3aMqf0bfovuITkKUkkY6wyi+097o4UbbSfViII44fVPmYmgk?= =?us-ascii?Q?I6CLJvFuk5TqbaYi3R4fsi6rW8U9mh72X88gi/+9/cL4Coz+N7fJidTiGiH4?= =?us-ascii?Q?uGpjuNZuW99OyGEiMg0y2jYAZblxzDkfiSimJYL91YY/QI8GIDrtO0ocgwfw?= =?us-ascii?Q?qOkqwOdASX/NYWEn4+EbCHia9zludAfsr2tGSKPg6cZepx1jW2CNYjCKTOJj?= =?us-ascii?Q?e0kLS8zRVe5im8gtKW8I6SC7v5UWhbbulxLdXTryALqa8BUrC0YqLUvOhft4?= =?us-ascii?Q?t+XXTDjPTRYXj9RAugLlTG9yEb13dqrSTsKjW7OK0VdDskedVfN00aHVf2Re?= =?us-ascii?Q?/lNOPeHm0UosVmDl42kfDDXQsLYSHARHHHmLL2xo58M3vbCJInd/bYKtRr0t?= =?us-ascii?Q?fqIjG8HCDpKO9YdLB23HrboewiCLYyPfNQ4LdrGOb2DGNF+NyYpYCeKMhp7U?= =?us-ascii?Q?cPnmSPpgdkzjYhu9sTnYh63+1RcdPv/iIPQDE1kZJfETzLcl7yX1ijEsYNjR?= =?us-ascii?Q?UzLafIsq7TmJC5me3/Mn5du8kNRcWtFFh7LqxSltpbacrBCmbWe9xCS88fm+?= =?us-ascii?Q?vyuDTh8NpVoKthLiYXVSRJSGlWXwK0pmjtKKtyegnQBFWu/6KUbIumSZ1qgA?= X-MS-Exchange-AntiSpam-MessageData-1: hKeSGXiZMTl6ujony6OcPTlGgOywk65o1Ds= X-OriginatorOrg: altera.com X-MS-Exchange-CrossTenant-Network-Message-Id: 29de1db6-6e02-4a30-2b17-08de781e1d47 X-MS-Exchange-CrossTenant-AuthSource: BLAPR03MB5458.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Mar 2026 05:39:47.1094 (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: l1zV/Aj2SjbYDAr8Ofi0jCO5/HryFrwRIcRmy9VKsWMtGvThk6JZ5V6R8XuTQhS6OUf9oNxicjYBKds3xJnredyk5545Akai0XoJy8JgDbvjbtbTnSBX73IOBkl4cIjEZEm9lsXaO3ssp9pus2X9tqw+rS/R+cflUXvtaVz/0nE= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH0PR03MB6097 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. 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 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 | 225 ++++++++++-------- .../firmware/intel/stratix10-svc-client.h | 8 +- 2 files changed, 128 insertions(+), 105 deletions(-) diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-= svc.c index 6f5c298582ab..2af95018f06d 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); @@ -1697,21 +1716,25 @@ int stratix10_svc_send(struct stratix10_svc_chan *c= han, void *msg) return -ENOMEM; =20 /* first client will create kernel thread */ - if (!chan->ctrl->task) { - chan->ctrl->task =3D + spin_lock(&chan->lock); + if (!chan->task) { + chan->task =3D 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)) { + if (IS_ERR(chan->task)) { + chan->task =3D NULL; + spin_unlock(&chan->lock); dev_err(chan->ctrl->dev, "failed to create svc_smc_hvc_thread\n"); kfree(p_data); return -EINVAL; } } + 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 +1770,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 +1800,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 +1845,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 +1883,18 @@ static const struct of_device_id stratix10_svc_drv_m= atch[] =3D { {}, }; =20 +/** + * mailbox_lock protects access to the SDM if thread is busy + */ +static DEFINE_MUTEX(mailbox_lock); + +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 +1902,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 +1945,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 +1957,24 @@ 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); - - 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); + /* + * This mutex is used to block threads from utilizing + * SDM to prevent out of order command tx + */ + controller->sdm_lock =3D &mailbox_lock; =20 - 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 +1983,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 +1991,40 @@ 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_put_device; =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: +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 +2032,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