Skip to content

Commit 7430dea

Browse files
plbossartbroonie
authored andcommitted
ASoC: SOF: Intel: hda-mlink: fix sublink refcounting
In hindsight it was a very bad idea to use the same refcount for Extended and 'legacy' HDaudio multi-links. The existing solution only powers-up the first sublink, which causes SoundWire and SSP tests to fail when more than one DAI is used concurrently. Solving this problem requires per-sublink refcounting, as suggested in this patch. The existing refcounting remains for 'legacy' HdAudio links, mainly to avoid changing the obscure programming sequence in snd_hdac_ext_bus_link_put(). Signed-off-by: Pierre-Louis Bossart <[email protected] Reviewed-by: Ranjani Sridharan <[email protected] Reviewed-by: Bard Liao <[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]
1 parent f63550e commit 7430dea

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

sound/soc/sof/intel/hda-mlink.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK)
2121

22+
/* worst-case number of sublinks is used for sublink refcount array allocation only */
23+
#define HDAML_MAX_SUBLINKS (AZX_ML_LCTL_CPA_SHIFT - AZX_ML_LCTL_SPA_SHIFT)
24+
2225
/**
2326
* struct hdac_ext2_link - HDAudio extended+alternate link
2427
*
@@ -33,6 +36,7 @@
3336
* @leptr: extended link pointer
3437
* @eml_lock: mutual exclusion to access shared registers e.g. CPA/SPA bits
3538
* in LCTL register
39+
* @sublink_ref_count: array of refcounts, required to power-manage sublinks independently
3640
* @base_ptr: pointer to shim/ip/shim_vs space
3741
* @instance_offset: offset between each of @slcount instances managed by link
3842
* @shim_offset: offset to SHIM register base
@@ -53,6 +57,7 @@ struct hdac_ext2_link {
5357
u32 leptr;
5458

5559
struct mutex eml_lock; /* prevent concurrent access to e.g. CPA/SPA */
60+
int sublink_ref_count[HDAML_MAX_SUBLINKS];
5661

5762
/* internal values computed from LCAP contents */
5863
void __iomem *base_ptr;
@@ -641,8 +646,13 @@ static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid,
641646
if (eml_lock)
642647
mutex_lock(&h2link->eml_lock);
643648

644-
if (++hlink->ref_count > 1)
645-
goto skip_init;
649+
if (!alt) {
650+
if (++hlink->ref_count > 1)
651+
goto skip_init;
652+
} else {
653+
if (++h2link->sublink_ref_count[sublink] > 1)
654+
goto skip_init;
655+
}
646656

647657
ret = hdaml_link_init(hlink->ml_addr + AZX_REG_ML_LCTL, sublink);
648658

@@ -684,9 +694,13 @@ static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid
684694
if (eml_lock)
685695
mutex_lock(&h2link->eml_lock);
686696

687-
if (--hlink->ref_count > 0)
688-
goto skip_shutdown;
689-
697+
if (!alt) {
698+
if (--hlink->ref_count > 0)
699+
goto skip_shutdown;
700+
} else {
701+
if (--h2link->sublink_ref_count[sublink] > 0)
702+
goto skip_shutdown;
703+
}
690704
ret = hdaml_link_shutdown(hlink->ml_addr + AZX_REG_ML_LCTL, sublink);
691705

692706
skip_shutdown:

0 commit comments

Comments
 (0)