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 <quic_rmaina@quicinc.com> Reviewed-by: Bjorn Andersson <andersson@kernel.org> Signed-off-by: Chris Lew <quic_clew@quicinc.com> Link: https://lore.kernel.org/r/20240529-hwspinlock-bust-v3-1-c8b924ffa5a2@quicinc.com Signed-off-by: Bjorn Andersson <andersson@kernel.org> 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 <quic_deesin@quicinc.com>
This commit is contained in:
parent
8fff36db32
commit
422eacf6fc
@ -12,6 +12,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/qcom/qcom_hwspinlock.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#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;
|
||||
|
24
include/linux/soc/qcom/qcom_hwspinlock.h
Normal file
24
include/linux/soc/qcom/qcom_hwspinlock.h
Normal file
@ -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 */
|
Loading…
Reference in New Issue
Block a user