On 6/22/20 1:18 PM, Andy Shevchenko wrote:
On Mon, Jun 22, 2020 at 10:42:38AM -0500, Pierre-Louis Bossart wrote:
The mainline code currently prevents modules from being removed.
The BE dailink .init() function calls devm_gpiod_get() using the codec component device as argument. When the machine driver is removed, the references to the gpiod are not released, and it's not possible to remove the codec driver module - which is the only entity which could free the gpiod.
This conceptual deadlock can be avoided by invoking gpiod_get() in the .init() callback, and calling gpiod_put() in the exit() callback.
Tested on SAMUS Chromebook with SOF driver.
+static void bdw_rt5677_exit(struct snd_soc_pcm_runtime *rtd) +{
- struct bdw_rt5677_priv *bdw_rt5677 =
snd_soc_card_get_drvdata(rtd->card);
- /*
* The .exit() can be reached without going through the .init()
* so explicitly test if the gpiod is valid
*/
- if (!IS_ERR_OR_NULL(bdw_rt5677->gpio_hp_en))
_OR_NULL is redundant. gpiod_put() is explicitly NULL-aware.
IS_ERR() I suppose can be avoided by using gpiod_get_optional(), if it suits the case. Otherwise it would be questionable why we got error pointer value on ->exit().
As I explained in the cover letter we can reach this function even if the init was not called or was not successful. There are tons of cases which reach the same probe_end label in the ASoC core.
So I explicitly added a test for all possible cases. I don't mind removing the _OR_NULL if indeed it's safe, but showing this redundancy also shows an intent to deal with such cases.
gpiod_put(bdw_rt5677->gpio_hp_en);
+}