From 422eacf6fcb1795e89b2075b3f052e612f3c8b95 Mon Sep 17 00:00:00 2001 From: Richard Maina Date: Wed, 7 Aug 2024 00:38:09 -0700 Subject: [PATCH] hwspinlock: qcom: Provide function to bust hwspinlock 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. Change-Id: I0486d5345a47007f254f17c4b88f802a6c962e3a Signed-off-by: Richard Maina Reviewed-by: Bjorn Andersson Signed-off-by: Chris Lew Link: https://lore.kernel.org/r/20240529-hwspinlock-bust-v3-1-c8b924ffa5a2@quicinc.com Signed-off-by: Bjorn Andersson Git-commit: 73100deb59c3892e280234fcc0171a5376c71788 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [quic_deesin@quicinc.com: Adding bust api in core hwspinlock module is breaking KMI, so exporting bust function from qcom hwspilock module to avoid dependency on core hwspinlock function] Signed-off-by: Deepak Kumar Singh --- drivers/hwspinlock/qcom_hwspinlock.c | 38 ++++++++++++++++++++++++ include/linux/soc/qcom/qcom_hwspinlock.h | 24 +++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 include/linux/soc/qcom/qcom_hwspinlock.h diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c index 3f08cd4a5c28..e6cb9426c91d 100644 --- a/drivers/hwspinlock/qcom_hwspinlock.c +++ b/drivers/hwspinlock/qcom_hwspinlock.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "hwspinlock_internal.h" @@ -25,6 +26,43 @@ struct qcom_hwspinlock_of_data { const struct regmap_config *regmap_config; }; +/** + * qcom_hwspinlock_bust() - bust qcom specific hwspinlock + * @hwlock: a previously-acquired hwspinlock which we want to bust + * @id: identifier of the remote lock holder, if applicable + * + * This function will bust a hwspinlock that was previously acquired as + * long as the current owner of the lock matches the id given by the caller. + * + * Context: Process context. + * + * Returns: 0 on success, or error if bust operation fails + */ +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) { + pr_err("%s: unable to query spinlock owner\n", __func__); + return ret; + } + + if (owner != id) + return 0; + + ret = regmap_field_write(field, 0); + if (ret) { + pr_err("%s: failed to bust spinlock\n", __func__); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_hwspinlock_bust); + static int qcom_hwspinlock_trylock(struct hwspinlock *lock) { struct regmap_field *field = lock->priv; diff --git a/include/linux/soc/qcom/qcom_hwspinlock.h b/include/linux/soc/qcom/qcom_hwspinlock.h new file mode 100644 index 000000000000..a5f5a7ec85fc --- /dev/null +++ b/include/linux/soc/qcom/qcom_hwspinlock.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __QCOM_HWSPINLOCK_H +#define __QCOM_HWSPINLOCK_H + +struct hwspinlock; + +#if IS_ENABLED(CONFIG_HWSPINLOCK_QCOM) + +int qcom_hwspinlock_bust(struct hwspinlock *hwlock, unsigned int id); + +#else /* !CONFIG_HWSPINLOCK_QCOM */ + +static inline int qcom_hwspinlock_bust(struct hwspinlock *hwlock, unsigned int id) +{ + return 0; +} + +#endif /* CONFIG_HWSPINLOCK_QCOM */ + +#endif /* __QCOM_HWSPINLOCK_H */