drivers: dai: alh: fix refcount logic for ALH ownership
Refcounting is used to track ALH block usage and to call alh_claim_ownership()/alh_release_ownership() accordingly. This is however incorrectly done on ALH instance basis, which means when one instance is released, ownership can be released even though one ALH instance is still active. Fix the logic by tracking ALH usage as a global property which matches the alh_claim_ownership/alh_release_ownership semantics. Link: https://github.com/thesofproject/sof/issues/7759 Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
This commit is contained in:
parent
b4fe506779
commit
f764e7e737
2 changed files with 16 additions and 11 deletions
|
@ -22,6 +22,9 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
|
||||||
|
|
||||||
#include "alh.h"
|
#include "alh.h"
|
||||||
|
|
||||||
|
/* global data shared between all alh instances */
|
||||||
|
struct dai_alh_global_shared dai_alh_global;
|
||||||
|
|
||||||
/* Digital Audio interface formatting */
|
/* Digital Audio interface formatting */
|
||||||
static int dai_alh_set_config_tplg(struct dai_intel_alh *dp, const void *spec_config)
|
static int dai_alh_set_config_tplg(struct dai_intel_alh *dp, const void *spec_config)
|
||||||
{
|
{
|
||||||
|
@ -157,38 +160,36 @@ static const struct dai_properties *dai_alh_get_properties(const struct device *
|
||||||
|
|
||||||
static int dai_alh_probe(const struct device *dev)
|
static int dai_alh_probe(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct dai_intel_alh *dp = (struct dai_intel_alh *)dev->data;
|
|
||||||
k_spinlock_key_t key;
|
k_spinlock_key_t key;
|
||||||
|
|
||||||
LOG_DBG("%s", __func__);
|
LOG_DBG("%s", __func__);
|
||||||
|
|
||||||
key = k_spin_lock(&dp->lock);
|
key = k_spin_lock(&dai_alh_global.lock);
|
||||||
|
|
||||||
if (dp->sref == 0) {
|
if (dai_alh_global.sref == 0) {
|
||||||
alh_claim_ownership();
|
alh_claim_ownership();
|
||||||
}
|
}
|
||||||
|
|
||||||
dp->sref++;
|
dai_alh_global.sref++;
|
||||||
|
|
||||||
k_spin_unlock(&dp->lock, key);
|
k_spin_unlock(&dai_alh_global.lock, key);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dai_alh_remove(const struct device *dev)
|
static int dai_alh_remove(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct dai_intel_alh *dp = (struct dai_intel_alh *)dev->data;
|
|
||||||
k_spinlock_key_t key;
|
k_spinlock_key_t key;
|
||||||
|
|
||||||
LOG_DBG("%s", __func__);
|
LOG_DBG("%s", __func__);
|
||||||
|
|
||||||
key = k_spin_lock(&dp->lock);
|
key = k_spin_lock(&dai_alh_global.lock);
|
||||||
|
|
||||||
if (--dp->sref == 0) {
|
if (--dai_alh_global.sref == 0) {
|
||||||
alh_release_ownership();
|
alh_release_ownership();
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spin_unlock(&dp->lock, key);
|
k_spin_unlock(&dai_alh_global.lock, key);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,10 +107,14 @@ struct dai_intel_alh_pdata {
|
||||||
|
|
||||||
struct dai_intel_alh {
|
struct dai_intel_alh {
|
||||||
uint32_t index; /**< index */
|
uint32_t index; /**< index */
|
||||||
struct k_spinlock lock; /**< locking mechanism */
|
|
||||||
int sref; /**< simple ref counter, guarded by lock */
|
|
||||||
struct dai_intel_alh_plat_data plat_data;
|
struct dai_intel_alh_plat_data plat_data;
|
||||||
struct dai_intel_alh_pdata priv_data;
|
struct dai_intel_alh_pdata priv_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Common data for all ALH DAI instances */
|
||||||
|
struct dai_alh_global_shared {
|
||||||
|
struct k_spinlock lock; /**< locking mechanism */
|
||||||
|
int sref; /**< simple ref counter, guarded by lock */
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue