[alsa-devel] [PATCH v2 0/2] ASoC hdmi-codec: fix HDMI jack reporting
With proper unbinding audio components and inserting the HDMI external display, kernel crashes as the following messages:
Unable to handle kernel NULL pointer dereference at virtual address ... [snip] Call trace: plugged_cb+0x1c/0x74 mtk_hdmi_update_plugged_status+0x48/0x6c hdmi_conn_detect+0x1c/0x28 drm_helper_probe_detect+0x110/0x170 drm_helper_probe_single_connector_modes+0xd4/0x608 drm_mode_getconnector+0x1e8/0x418
The 1st patch fixes the crash by notifying hdmi-codec's consumers to not report jack status anymore when component removing.
The 2nd patch fixes race condition in mediatek/mtk_hdmi.c.
Changes from v1: (https://patchwork.kernel.org/patch/11379979/) - added the 1st patch - use mutex to protect plugged_cb and codec_dev in 2nd patch
Tzung-Bi Shih (2): ASoC: hdmi-codec: set plugged_cb to NULL when component removing drm/mediatek: fix race condition for HDMI jack status reporting
drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++++++++++- sound/soc/codecs/hdmi-codec.c | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-)
Sets plugged_cb to NULL when component removing to notify its consumers : no further plugged status report is required.
Signed-off-by: Tzung-Bi Shih tzungbi@google.com --- sound/soc/codecs/hdmi-codec.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 444cc4e3374e..f005751da2cc 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -779,7 +779,17 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component, return ret; }
+static void hdmi_remove(struct snd_soc_component *component) +{ + struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); + + if (hcp->hcd.ops->hook_plugged_cb) + hcp->hcd.ops->hook_plugged_cb(component->dev->parent, + hcp->hcd.data, NULL, NULL); +} + static const struct snd_soc_component_driver hdmi_driver = { + .remove = hdmi_remove, .dapm_widgets = hdmi_widgets, .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), .of_xlate_dai_id = hdmi_of_xlate_dai_id,
The patch
ASoC: hdmi-codec: set plugged_cb to NULL when component removing
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4aadf4b49ec7d80c5db842ca28479d07108c9484 Mon Sep 17 00:00:00 2001
From: Tzung-Bi Shih tzungbi@google.com Date: Mon, 17 Feb 2020 11:16:52 +0800 Subject: [PATCH] ASoC: hdmi-codec: set plugged_cb to NULL when component removing
Sets plugged_cb to NULL when component removing to notify its consumers : no further plugged status report is required.
Signed-off-by: Tzung-Bi Shih tzungbi@google.com Link: https://lore.kernel.org/r/20200217105513.1.Icc323daaf71ad02f191fd8d91136b01b... Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/hdmi-codec.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 543363102d03..bc2903d27e6e 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -779,7 +779,17 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component, return ret; }
+static void hdmi_remove(struct snd_soc_component *component) +{ + struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); + + if (hcp->hcd.ops->hook_plugged_cb) + hcp->hcd.ops->hook_plugged_cb(component->dev->parent, + hcp->hcd.data, NULL, NULL); +} + static const struct snd_soc_component_driver hdmi_driver = { + .remove = hdmi_remove, .dapm_widgets = hdmi_widgets, .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), .of_xlate_dai_id = hdmi_of_xlate_dai_id,
hdmi_conn_detect and mtk_hdmi_audio_hook_plugged_cb would be called by different threads.
Imaging the following calling sequence: Thread A Thread B -------------------------------------------------------------------- mtk_hdmi_audio_hook_plugged_cb() mtk_cec_hpd_high() -> disconnected hdmi_conn_detect() mtk_cec_hpd_high() -> connected plugged_cb(connected) plugged_cb(disconnected)
The latest disconnected is false reported. Makes mtk_cec_hpd_high and plugged_cb atomic to fix.
Also uses the same lock to protect read/write of plugged_cb and codec_dev.
Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting") Signed-off-by: Tzung-Bi Shih tzungbi@google.com --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 03aeb73005ef..d80017e3d84a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> +#include <linux/mutex.h> #include <linux/of_platform.h> #include <linux/of.h> #include <linux/of_gpio.h> @@ -171,6 +172,7 @@ struct mtk_hdmi { bool enabled; hdmi_codec_plugged_cb plugged_cb; struct device *codec_dev; + struct mutex update_plugged_status_lock; };
static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) @@ -1199,10 +1201,13 @@ static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi) static enum drm_connector_status mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) { - bool connected = mtk_cec_hpd_high(hdmi->cec_dev); + bool connected;
+ mutex_lock(&hdmi->update_plugged_status_lock); + connected = mtk_cec_hpd_high(hdmi->cec_dev); if (hdmi->plugged_cb && hdmi->codec_dev) hdmi->plugged_cb(hdmi->codec_dev, connected); + mutex_unlock(&hdmi->update_plugged_status_lock);
return connected ? connector_status_connected : connector_status_disconnected; @@ -1669,8 +1674,11 @@ static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, { struct mtk_hdmi *hdmi = data;
+ mutex_lock(&hdmi->update_plugged_status_lock); hdmi->plugged_cb = fn; hdmi->codec_dev = codec_dev; + mutex_unlock(&hdmi->update_plugged_status_lock); + mtk_hdmi_update_plugged_status(hdmi);
return 0; @@ -1729,6 +1737,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; }
+ mutex_init(&hdmi->update_plugged_status_lock); platform_set_drvdata(pdev, hdmi);
ret = mtk_hdmi_output_init(hdmi);
Hi, Tzhung-Bi:
On Mon, 2020-02-17 at 11:16 +0800, Tzung-Bi Shih wrote:
hdmi_conn_detect and mtk_hdmi_audio_hook_plugged_cb would be called by different threads.
Imaging the following calling sequence: Thread A Thread B
mtk_hdmi_audio_hook_plugged_cb() mtk_cec_hpd_high() -> disconnected hdmi_conn_detect() mtk_cec_hpd_high() -> connected plugged_cb(connected) plugged_cb(disconnected)
The latest disconnected is false reported. Makes mtk_cec_hpd_high and plugged_cb atomic to fix.
Also uses the same lock to protect read/write of plugged_cb and codec_dev.
Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting")
This patch looks good to me, but please merge this patch with the patch it fix.
Regards, CK
Signed-off-by: Tzung-Bi Shih tzungbi@google.com
drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 03aeb73005ef..d80017e3d84a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> +#include <linux/mutex.h> #include <linux/of_platform.h> #include <linux/of.h> #include <linux/of_gpio.h> @@ -171,6 +172,7 @@ struct mtk_hdmi { bool enabled; hdmi_codec_plugged_cb plugged_cb; struct device *codec_dev;
- struct mutex update_plugged_status_lock;
};
static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) @@ -1199,10 +1201,13 @@ static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi) static enum drm_connector_status mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) {
- bool connected = mtk_cec_hpd_high(hdmi->cec_dev);
bool connected;
mutex_lock(&hdmi->update_plugged_status_lock);
connected = mtk_cec_hpd_high(hdmi->cec_dev); if (hdmi->plugged_cb && hdmi->codec_dev) hdmi->plugged_cb(hdmi->codec_dev, connected);
mutex_unlock(&hdmi->update_plugged_status_lock);
return connected ? connector_status_connected : connector_status_disconnected;
@@ -1669,8 +1674,11 @@ static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, { struct mtk_hdmi *hdmi = data;
mutex_lock(&hdmi->update_plugged_status_lock); hdmi->plugged_cb = fn; hdmi->codec_dev = codec_dev;
mutex_unlock(&hdmi->update_plugged_status_lock);
mtk_hdmi_update_plugged_status(hdmi);
return 0;
@@ -1729,6 +1737,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; }
mutex_init(&hdmi->update_plugged_status_lock); platform_set_drvdata(pdev, hdmi);
ret = mtk_hdmi_output_init(hdmi);
On Mon, Feb 17, 2020 at 11:44 AM CK Hu ck.hu@mediatek.com wrote:
On Mon, 2020-02-17 at 11:16 +0800, Tzung-Bi Shih wrote:
Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting")
This patch looks good to me, but please merge this patch with the patch it fix.
5d3c64477392 ("drm/mediatek: support HDMI jack status reporting") has applied to ASoC for-next branch. This is a fixup patch.
On Mon, 2020-02-17 at 11:55 +0800, Tzung-Bi Shih wrote:
On Mon, Feb 17, 2020 at 11:44 AM CK Hu ck.hu@mediatek.com wrote:
On Mon, 2020-02-17 at 11:16 +0800, Tzung-Bi Shih wrote:
Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting")
This patch looks good to me, but please merge this patch with the patch it fix.
5d3c64477392 ("drm/mediatek: support HDMI jack status reporting") has applied to ASoC for-next branch. This is a fixup patch.
I thought a patch need an ack by the maintainer. OK, so I could do is, for this patch,
Acked-by: CK Hu ck.hu@mediatek.com
The patch
drm/mediatek: fix race condition for HDMI jack status reporting
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From f07980d4ed60fbb35857b655c94b111f4ddf2abf Mon Sep 17 00:00:00 2001
From: Tzung-Bi Shih tzungbi@google.com Date: Mon, 17 Feb 2020 11:16:53 +0800 Subject: [PATCH] drm/mediatek: fix race condition for HDMI jack status reporting
hdmi_conn_detect and mtk_hdmi_audio_hook_plugged_cb would be called by different threads.
Imaging the following calling sequence: Thread A Thread B -------------------------------------------------------------------- mtk_hdmi_audio_hook_plugged_cb() mtk_cec_hpd_high() -> disconnected hdmi_conn_detect() mtk_cec_hpd_high() -> connected plugged_cb(connected) plugged_cb(disconnected)
The latest disconnected is false reported. Makes mtk_cec_hpd_high and plugged_cb atomic to fix.
Also uses the same lock to protect read/write of plugged_cb and codec_dev.
Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting") Signed-off-by: Tzung-Bi Shih tzungbi@google.com Acked-by: CK Hu ck.hu@mediatek.com Link: https://lore.kernel.org/r/20200217105513.2.I477092c2f104fd589133436c3ae4590e... Signed-off-by: Mark Brown broonie@kernel.org --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 03aeb73005ef..d80017e3d84a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> +#include <linux/mutex.h> #include <linux/of_platform.h> #include <linux/of.h> #include <linux/of_gpio.h> @@ -171,6 +172,7 @@ struct mtk_hdmi { bool enabled; hdmi_codec_plugged_cb plugged_cb; struct device *codec_dev; + struct mutex update_plugged_status_lock; };
static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) @@ -1199,10 +1201,13 @@ static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi) static enum drm_connector_status mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) { - bool connected = mtk_cec_hpd_high(hdmi->cec_dev); + bool connected;
+ mutex_lock(&hdmi->update_plugged_status_lock); + connected = mtk_cec_hpd_high(hdmi->cec_dev); if (hdmi->plugged_cb && hdmi->codec_dev) hdmi->plugged_cb(hdmi->codec_dev, connected); + mutex_unlock(&hdmi->update_plugged_status_lock);
return connected ? connector_status_connected : connector_status_disconnected; @@ -1669,8 +1674,11 @@ static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, { struct mtk_hdmi *hdmi = data;
+ mutex_lock(&hdmi->update_plugged_status_lock); hdmi->plugged_cb = fn; hdmi->codec_dev = codec_dev; + mutex_unlock(&hdmi->update_plugged_status_lock); + mtk_hdmi_update_plugged_status(hdmi);
return 0; @@ -1729,6 +1737,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; }
+ mutex_init(&hdmi->update_plugged_status_lock); platform_set_drvdata(pdev, hdmi);
ret = mtk_hdmi_output_init(hdmi);
participants (3)
-
CK Hu
-
Mark Brown
-
Tzung-Bi Shih