hwspinlocks can be acquired by many devices on the SoC. If any of these
devices go into a bad state before the device releases the hwspinlock,
then that hwspinlock may end up in an unusable state.
In the case of smem, each remoteproc takes a hwspinlock before trying to
allocate an smem item. If the remoteproc were to suddenly crash without
releasing this, it would be impossible for other remoteprocs to allocate
any smem items.
We propose a new api to bust a hwspinlock. A driver can use the
the bust api if it detects the device has gone into an error state, thus
allowing other entities in the system to use the hwspinlock.
These patches were tested on an sm8650 mtp using engineering cdsp
firmware that triggers a watchdog with the smem hwspinlock acquired.
Checked for error in dt-bindings with below.
- make DT_CHECKER_FLAGS=-m DT_SCHEMA_FILES=remoteproc/qcom,pas-common.yaml dt_binding_check
- make qcom/sm8650-mtp.dtb CHECK_DTBS=1
Signed-off-by: Chris Lew <[email protected]>
---
Changes in v2:
- Remove extra print in qcom_q6v5_pas as suggested by Konrad
- Expose SMEM API that remotproc can call to bust the smem hwlock as suggested by Krzysztof
- Drop patches related to multiple references on a hwlock
- Link to v1: https://lore.kernel.org/r/[email protected]
---
Chris Lew (1):
soc: qcom: smem: Add qcom_smem_bust_hwspin_lock_by_host()
Richard Maina (3):
hwspinlock: Introduce hwspin_lock_bust()
hwspinlock: qcom: implement bust operation
remoteproc: qcom_q6v5_pas: Add hwspinlock bust on stop
Documentation/locking/hwspinlock.rst | 11 +++++++++++
drivers/hwspinlock/hwspinlock_core.c | 28 ++++++++++++++++++++++++++++
drivers/hwspinlock/hwspinlock_internal.h | 3 +++
drivers/hwspinlock/qcom_hwspinlock.c | 25 +++++++++++++++++++++++++
drivers/remoteproc/qcom_q6v5_pas.c | 11 +++++++++++
drivers/soc/qcom/smem.c | 28 ++++++++++++++++++++++++++++
include/linux/hwspinlock.h | 6 ++++++
include/linux/soc/qcom/smem.h | 2 ++
8 files changed, 114 insertions(+)
---
base-commit: e7b4ef8fffaca247809337bb78daceb406659f2d
change-id: 20240509-hwspinlock-bust-d497a70c1a3a
Best regards,
--
Chris Lew <[email protected]>
From: Richard Maina <[email protected]>
Implement a new operation qcom_hwspinlock_bust() which can be invoked
to bust any locks that are in use when a remoteproc is stopped or
crashed.
Signed-off-by: Richard Maina <[email protected]>
Signed-off-by: Chris Lew <[email protected]>
---
drivers/hwspinlock/qcom_hwspinlock.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c
index 814dfe8697bf..0390979fd765 100644
--- a/drivers/hwspinlock/qcom_hwspinlock.c
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
@@ -64,9 +64,34 @@ static void qcom_hwspinlock_unlock(struct hwspinlock *lock)
pr_err("%s: failed to unlock spinlock\n", __func__);
}
+static int qcom_hwspinlock_bust(struct hwspinlock *lock, unsigned int id)
+{
+ struct regmap_field *field = lock->priv;
+ u32 owner;
+ int ret;
+
+ ret = regmap_field_read(field, &owner);
+ if (ret) {
+ dev_err(lock->bank->dev, "unable to query spinlock owner\n");
+ return ret;
+ }
+
+ if (owner != id)
+ return 0;
+
+ ret = regmap_field_write(field, 0);
+ if (ret) {
+ dev_err(lock->bank->dev, "failed to bust spinlock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct hwspinlock_ops qcom_hwspinlock_ops = {
.trylock = qcom_hwspinlock_trylock,
.unlock = qcom_hwspinlock_unlock,
+ .bust = qcom_hwspinlock_bust,
};
static const struct regmap_config sfpb_mutex_config = {
--
2.25.1
On Fri, May 24, 2024 at 06:26:41PM -0700, Chris Lew wrote:
> From: Richard Maina <[email protected]>
>
> Implement a new operation qcom_hwspinlock_bust() which can be invoked
> to bust any locks that are in use when a remoteproc is stopped or
> crashed.
>
> Signed-off-by: Richard Maina <[email protected]>
> Signed-off-by: Chris Lew <[email protected]>
Reviewed-by: Bjorn Andersson <[email protected]>
Regards,
Bjorn
> ---
> drivers/hwspinlock/qcom_hwspinlock.c | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c
> index 814dfe8697bf..0390979fd765 100644
> --- a/drivers/hwspinlock/qcom_hwspinlock.c
> +++ b/drivers/hwspinlock/qcom_hwspinlock.c
> @@ -64,9 +64,34 @@ static void qcom_hwspinlock_unlock(struct hwspinlock *lock)
> pr_err("%s: failed to unlock spinlock\n", __func__);
> }
>
> +static int qcom_hwspinlock_bust(struct hwspinlock *lock, unsigned int id)
> +{
> + struct regmap_field *field = lock->priv;
> + u32 owner;
> + int ret;
> +
> + ret = regmap_field_read(field, &owner);
> + if (ret) {
> + dev_err(lock->bank->dev, "unable to query spinlock owner\n");
> + return ret;
> + }
> +
> + if (owner != id)
> + return 0;
> +
> + ret = regmap_field_write(field, 0);
> + if (ret) {
> + dev_err(lock->bank->dev, "failed to bust spinlock\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> static const struct hwspinlock_ops qcom_hwspinlock_ops = {
> .trylock = qcom_hwspinlock_trylock,
> .unlock = qcom_hwspinlock_unlock,
> + .bust = qcom_hwspinlock_bust,
> };
>
> static const struct regmap_config sfpb_mutex_config = {
>
> --
> 2.25.1
>