From: Wolfram Sang <wsa+renesas@sang-engineering.com>
To: linux-renesas-soc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
Wolfram Sang <wsa+renesas@sang-engineering.com>,
Bjorn Andersson <andersson@kernel.org>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
Boqun Feng <boqun@kernel.org>, Waiman Long <longman@redhat.com>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Orson Zhai <orsonzhai@gmail.com>,
Chunyan Zhang <zhang.lyra@gmail.com>,
Maxime Coquelin <mcoquelin.stm32@gmail.com>,
Alexandre Torgue <alexandre.torgue@foss.st.com>,
Wilken Gottwalt <wilken.gottwalt@posteo.net>,
Chen-Yu Tsai <wens@kernel.org>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Samuel Holland <samuel@sholland.org>,
linux-remoteproc@vger.kernel.org, linux-doc@vger.kernel.org,
linux-omap@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org,
linux-sunxi@lists.linux.dev
Subject: [PATCH v5 10/15] hwspinlock: handle hwspinlock device allocation in the core
Date: Thu, 19 Mar 2026 11:59:32 +0100 [thread overview]
Message-ID: <20260319105947.6237-11-wsa+renesas@sang-engineering.com> (raw)
In-Reply-To: <20260319105947.6237-1-wsa+renesas@sang-engineering.com>
Providers have been refactored to avoid using core internal structures.
As a result, they do not need to allocate the hwspinlock device on their
own anymore because they can access everything they need with helpers.
So, the allocation is moved to the core. As a result, the registering
functions now return a pointer to the (soon) opaque hwspinlock device
which may be needed for unregistering only.
Because the argument list of the registering functions is changed, all
users are changed here as well.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
Documentation/locking/hwspinlock.rst | 6 ++--
drivers/hwspinlock/hwspinlock_core.c | 48 +++++++++++++++------------
drivers/hwspinlock/omap_hwspinlock.c | 10 ++----
drivers/hwspinlock/qcom_hwspinlock.c | 11 ++----
drivers/hwspinlock/sprd_hwspinlock.c | 17 ++++------
drivers/hwspinlock/stm32_hwspinlock.c | 7 ++--
drivers/hwspinlock/sun6i_hwspinlock.c | 12 ++-----
include/linux/hwspinlock.h | 17 ++++++----
8 files changed, 55 insertions(+), 73 deletions(-)
diff --git a/Documentation/locking/hwspinlock.rst b/Documentation/locking/hwspinlock.rst
index cedeeab7387c..6cf1975b4291 100644
--- a/Documentation/locking/hwspinlock.rst
+++ b/Documentation/locking/hwspinlock.rst
@@ -350,9 +350,9 @@ API for implementors
::
- int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id,
- int num_locks, void *init_data);
+ struct hwspinlock_device *hwspin_lock_register(struct device *dev,
+ const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data);
To be called from the underlying platform-specific implementation, in
order to register a new hwspinlock device (which is usually a bank of
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index afe1e7ce2829..a7610ba755b4 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -21,6 +21,7 @@
#include <linux/pm_runtime.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include "hwspinlock_internal.h"
@@ -502,7 +503,6 @@ static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
/**
* hwspin_lock_register() - register a new hw spinlock device
- * @bank: the hwspinlock device, which usually provides numerous hw locks
* @dev: the backing device
* @ops: hwspinlock handlers for this device
* @base_id: id of the first hardware spinlock in this bank
@@ -514,21 +514,25 @@ static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
*
* Should be called from a process context (might sleep)
*
- * Returns: %0 on success, or an appropriate error code on failure
+ * Returns: a pointer to the device (needed for unregistering), or an
+ * appropriate error pointer on failure
*/
-int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id, int num_locks,
- void *init_data)
+struct hwspinlock_device *hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data)
{
+ struct hwspinlock_device *bank;
struct hwspinlock *hwlock;
int ret, i;
- if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
- !ops->unlock) {
+ if (!ops || !dev || !num_locks || !ops->trylock || !ops->unlock) {
pr_err("invalid parameters\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
+ bank = kzalloc(struct_size(bank, lock, num_locks), GFP_KERNEL);
+ if (!bank)
+ return ERR_PTR(-ENOMEM);
+
bank->dev = dev;
bank->ops = ops;
bank->base_id = base_id;
@@ -553,12 +557,13 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
goto reg_failed;
}
- return 0;
+ return bank;
reg_failed:
while (--i >= 0)
hwspin_lock_unregister_single(base_id + i);
- return ret;
+ kfree(bank);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(hwspin_lock_register);
@@ -589,6 +594,8 @@ int hwspin_lock_unregister(struct hwspinlock_device *bank)
WARN_ON(tmp != hwlock);
}
+ kfree(bank);
+
return 0;
}
EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
@@ -639,7 +646,6 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
* devm_hwspin_lock_register() - register a new hw spinlock device for
* a managed device
* @dev: the backing device
- * @bank: the hwspinlock device, which usually provides numerous hw locks
* @ops: hwspinlock handlers for this device
* @base_id: id of the first hardware spinlock in this bank
* @num_locks: number of hwspinlocks provided by this device
@@ -650,29 +656,27 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
*
* Should be called from a process context (might sleep)
*
- * Returns: %0 on success, or an appropriate error code on failure
+ * Returns: a pointer to the device (usable for unregistering), or an
+ * appropriate error pointer on failure
*/
-int devm_hwspin_lock_register(struct device *dev,
- struct hwspinlock_device *bank,
- const struct hwspinlock_ops *ops,
- int base_id, int num_locks, void *init_data)
+struct hwspinlock_device *devm_hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data)
{
- struct hwspinlock_device **ptr;
- int ret;
+ struct hwspinlock_device **ptr, *bank;
ptr = devres_alloc(devm_hwspin_lock_unreg, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- ret = hwspin_lock_register(bank, dev, ops, base_id, num_locks, init_data);
- if (!ret) {
+ bank = hwspin_lock_register(dev, ops, base_id, num_locks, init_data);
+ if (!IS_ERR(bank)) {
*ptr = bank;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
- return ret;
+ return bank;
}
EXPORT_SYMBOL_GPL(devm_hwspin_lock_register);
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 868b93131796..87ab30614e1d 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -80,7 +80,6 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
static int omap_hwspinlock_probe(struct platform_device *pdev)
{
- struct hwspinlock_device *bank;
void __iomem *io_base;
int num_locks, i, ret;
/* Only a single hwspinlock block device is supported */
@@ -117,13 +116,8 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
num_locks = i * 32; /* actual number of locks in this device */
- bank = devm_kzalloc(&pdev->dev, struct_size(bank, lock, num_locks),
- GFP_KERNEL);
- if (!bank)
- return -ENOMEM;
-
- return devm_hwspin_lock_register(&pdev->dev, bank, &omap_hwspinlock_ops,
- base_id, num_locks, io_base + LOCK_BASE_OFFSET);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &omap_hwspinlock_ops, base_id,
+ num_locks, io_base + LOCK_BASE_OFFSET);
}
static const struct of_device_id omap_hwspinlock_of_match[] = {
diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c
index 73b280988109..e2836d6728e8 100644
--- a/drivers/hwspinlock/qcom_hwspinlock.c
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
@@ -223,9 +223,7 @@ static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev,
static int qcom_hwspinlock_probe(struct platform_device *pdev)
{
struct qcom_hwspinlock_priv_init_data init;
- struct hwspinlock_device *bank;
struct regmap *regmap;
- size_t array_size;
regmap = qcom_hwspinlock_probe_syscon(pdev, &init.base, &init.stride);
if (IS_ERR(regmap) && PTR_ERR(regmap) == -ENODEV)
@@ -234,16 +232,11 @@ static int qcom_hwspinlock_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- array_size = QCOM_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock);
- bank = devm_kzalloc(&pdev->dev, sizeof(*bank) + array_size, GFP_KERNEL);
- if (!bank)
- return -ENOMEM;
-
init.dev = &pdev->dev;
init.regmap = regmap;
- return devm_hwspin_lock_register(&pdev->dev, bank, &qcom_hwspinlock_ops,
- 0, QCOM_MUTEX_NUM_LOCKS, &init);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &qcom_hwspinlock_ops,
+ 0, QCOM_MUTEX_NUM_LOCKS, &init);
}
static struct platform_driver qcom_hwspinlock_driver = {
diff --git a/drivers/hwspinlock/sprd_hwspinlock.c b/drivers/hwspinlock/sprd_hwspinlock.c
index f906f5fa74ef..bbae37e25243 100644
--- a/drivers/hwspinlock/sprd_hwspinlock.c
+++ b/drivers/hwspinlock/sprd_hwspinlock.c
@@ -33,15 +33,14 @@
struct sprd_hwspinlock_dev {
void __iomem *base;
struct clk *clk;
- struct hwspinlock_device bank;
};
/* try to lock the hardware spinlock */
static int sprd_hwspinlock_trylock(struct hwspinlock *lock)
{
- struct sprd_hwspinlock_dev *sprd_hwlock =
- dev_get_drvdata(hwspin_lock_get_dev(lock));
void __iomem *addr = hwspin_lock_get_priv(lock);
+ struct device *dev = hwspin_lock_get_dev(lock);
+ struct sprd_hwspinlock_dev *sprd_hwlock = dev_get_drvdata(dev);
int user_id, lock_id;
if (!readl(addr))
@@ -50,8 +49,7 @@ static int sprd_hwspinlock_trylock(struct hwspinlock *lock)
lock_id = hwlock_to_id(lock);
/* get the hardware spinlock master/user id */
user_id = readl(sprd_hwlock->base + HWSPINLOCK_MASTERID(lock_id));
- dev_warn(sprd_hwlock->bank.dev,
- "hwspinlock [%d] lock failed and master/user id = %d!\n",
+ dev_warn(dev, "hwspinlock [%d] lock failed and master/user id = %d!\n",
lock_id, user_id);
return 0;
}
@@ -97,9 +95,7 @@ static int sprd_hwspinlock_probe(struct platform_device *pdev)
if (!pdev->dev.of_node)
return -ENODEV;
- sprd_hwlock = devm_kzalloc(&pdev->dev,
- struct_size(sprd_hwlock, bank.lock, SPRD_HWLOCKS_NUM),
- GFP_KERNEL);
+ sprd_hwlock = devm_kzalloc(&pdev->dev, sizeof(*sprd_hwlock), GFP_KERNEL);
if (!sprd_hwlock)
return -ENOMEM;
@@ -130,9 +126,8 @@ static int sprd_hwspinlock_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sprd_hwlock);
- return devm_hwspin_lock_register(&pdev->dev, &sprd_hwlock->bank,
- &sprd_hwspinlock_ops, 0,
- SPRD_HWLOCKS_NUM, sprd_hwlock->base);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &sprd_hwspinlock_ops, 0,
+ SPRD_HWLOCKS_NUM, sprd_hwlock->base);
}
static const struct of_device_id sprd_hwspinlock_of_match[] = {
diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c
index 62214f31f909..ed937bc26bf5 100644
--- a/drivers/hwspinlock/stm32_hwspinlock.c
+++ b/drivers/hwspinlock/stm32_hwspinlock.c
@@ -22,7 +22,6 @@
struct stm32_hwspinlock {
struct clk *clk;
- struct hwspinlock_device bank;
};
static int stm32_hwspinlock_trylock(struct hwspinlock *lock)
@@ -85,7 +84,7 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev)
if (IS_ERR(io_base))
return PTR_ERR(io_base);
- hw = devm_kzalloc(dev, struct_size(hw, bank.lock, STM32_MUTEX_NUM_LOCKS), GFP_KERNEL);
+ hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return -ENOMEM;
@@ -112,8 +111,8 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev)
return ret;
}
- ret = devm_hwspin_lock_register(dev, &hw->bank, &stm32_hwspinlock_ops,
- 0, STM32_MUTEX_NUM_LOCKS, io_base);
+ ret = devm_hwspin_lock_register_errno(dev, &stm32_hwspinlock_ops,
+ 0, STM32_MUTEX_NUM_LOCKS, io_base);
if (ret)
dev_err(dev, "Failed to register hwspinlock\n");
diff --git a/drivers/hwspinlock/sun6i_hwspinlock.c b/drivers/hwspinlock/sun6i_hwspinlock.c
index c3db81cb1793..8bbed23af5f4 100644
--- a/drivers/hwspinlock/sun6i_hwspinlock.c
+++ b/drivers/hwspinlock/sun6i_hwspinlock.c
@@ -27,7 +27,6 @@
#define SPINLOCK_NOTTAKEN 0
struct sun6i_hwspinlock_data {
- struct hwspinlock_device *bank;
struct reset_control *reset;
struct clk *ahb_clk;
struct dentry *debugfs;
@@ -159,13 +158,6 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev)
goto bank_fail;
}
- priv->bank = devm_kzalloc(&pdev->dev, struct_size(priv->bank, lock, priv->nlocks),
- GFP_KERNEL);
- if (!priv->bank) {
- err = -ENOMEM;
- goto bank_fail;
- }
-
/* failure of debugfs is considered non-fatal */
sun6i_hwspinlock_debugfs_init(priv);
if (IS_ERR(priv->debugfs))
@@ -177,8 +169,8 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev)
goto bank_fail;
}
- return devm_hwspin_lock_register(&pdev->dev, priv->bank, &sun6i_hwspinlock_ops,
- SPINLOCK_BASE_ID, priv->nlocks, io_base + SPINLOCK_LOCK_REGN);
+ return devm_hwspin_lock_register_errno(&pdev->dev, &sun6i_hwspinlock_ops, SPINLOCK_BASE_ID,
+ priv->nlocks, io_base + SPINLOCK_LOCK_REGN);
bank_fail:
clk_disable_unprepare(priv->ahb_clk);
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h
index 094a6d0d39d6..58733cda7a9a 100644
--- a/include/linux/hwspinlock.h
+++ b/include/linux/hwspinlock.h
@@ -29,8 +29,8 @@ struct hwspinlock_ops;
void *hwspin_lock_get_priv(struct hwspinlock *hwlock);
struct device *hwspin_lock_get_dev(struct hwspinlock *hwlock);
-int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id, int num_locks, void *init_data);
+struct hwspinlock_device *hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data);
int hwspin_lock_unregister(struct hwspinlock_device *bank);
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
int hwspin_lock_free(struct hwspinlock *hwlock);
@@ -46,10 +46,15 @@ struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev,
unsigned int id);
int devm_hwspin_lock_unregister(struct device *dev,
struct hwspinlock_device *bank);
-int devm_hwspin_lock_register(struct device *dev,
- struct hwspinlock_device *bank,
- const struct hwspinlock_ops *ops,
- int base_id, int num_locks, void *init_data);
+struct hwspinlock_device *devm_hwspin_lock_register(struct device *dev, const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data);
+
+static inline int devm_hwspin_lock_register_errno(struct device *dev,
+ const struct hwspinlock_ops *ops,
+ int base_id, int num_locks, void *init_data)
+{
+ return PTR_ERR_OR_ZERO(devm_hwspin_lock_register(dev, ops, base_id, num_locks, init_data));
+}
#else /* !CONFIG_HWSPINLOCK */
--
2.51.0
next prev parent reply other threads:[~2026-03-19 11:00 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-19 10:59 [PATCH v5 00/15] hwspinlock: move device alloc into core and refactor includes Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 01/15] hwspinlock: u8500: delete driver Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 02/15] hwspinlock: remove now unused pdata from header file Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 03/15] hwspinlock: add helpers to retrieve core data Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 04/15] hwspinlock: add callback to fill private data of a hwspinlock Wolfram Sang
2026-03-19 13:07 ` Chen-Yu Tsai
2026-03-19 10:59 ` [PATCH v5 05/15] hwspinlock: omap: use new callback to initialize hwspinlock priv Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 06/15] hwspinlock: qcom: " Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 07/15] hwspinlock: sprd: " Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 08/15] hwspinlock: stm32: " Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 09/15] hwspinlock: sun6i: " Wolfram Sang
2026-03-19 10:59 ` Wolfram Sang [this message]
2026-03-19 13:09 ` [PATCH v5 10/15] hwspinlock: handle hwspinlock device allocation in the core Chen-Yu Tsai
2026-03-19 10:59 ` [PATCH v5 11/15] hwspinlock: move entries from internal to public header Wolfram Sang
2026-03-19 13:09 ` Chen-Yu Tsai
2026-03-19 10:59 ` [PATCH v5 12/15] hwspinlock: remove internal header Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 13/15] hwspinlock: sort include and update copyright Wolfram Sang
2026-03-19 10:59 ` [PATCH v5 14/15] hwspinlock: refactor provider.h from public header Wolfram Sang
2026-03-19 13:10 ` Chen-Yu Tsai
2026-03-19 10:59 ` [PATCH v5 15/15] hwspinlock/treewide: refactor consumer.h " Wolfram Sang
2026-03-27 11:43 ` [PATCH v5 00/15] hwspinlock: move device alloc into core and refactor includes Wolfram Sang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260319105947.6237-11-wsa+renesas@sang-engineering.com \
--to=wsa+renesas@sang-engineering.com \
--cc=alexandre.torgue@foss.st.com \
--cc=andersson@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=boqun@kernel.org \
--cc=corbet@lwn.net \
--cc=jernej.skrabec@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux-remoteproc@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=linux-sunxi@lists.linux.dev \
--cc=longman@redhat.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=mingo@redhat.com \
--cc=orsonzhai@gmail.com \
--cc=peterz@infradead.org \
--cc=samuel@sholland.org \
--cc=skhan@linuxfoundation.org \
--cc=wens@kernel.org \
--cc=wilken.gottwalt@posteo.net \
--cc=will@kernel.org \
--cc=zhang.lyra@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®