From: Greg Kroah-Hartman Date: Sat, 28 Nov 2020 14:56:49 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.4.247~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d0129b31f306b7e07242ce3a86e43b5f04d9d1b3;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: alsa-hda-hdmi-fix-incorrect-locking-in-hdmi_pcm_close.patch alsa-hda-hdmi-use-single-mutex-unlock-in-error-paths.patch i2c-imx-fix-reset-of-i2sr_ial-flag.patch --- diff --git a/queue-4.14/alsa-hda-hdmi-fix-incorrect-locking-in-hdmi_pcm_close.patch b/queue-4.14/alsa-hda-hdmi-fix-incorrect-locking-in-hdmi_pcm_close.patch new file mode 100644 index 00000000000..b4699b6f6d9 --- /dev/null +++ b/queue-4.14/alsa-hda-hdmi-fix-incorrect-locking-in-hdmi_pcm_close.patch @@ -0,0 +1,84 @@ +From foo@baz Sat Nov 28 03:55:03 PM CET 2020 +From: Kai Vehmanen +Date: Tue, 13 Oct 2020 18:26:28 +0300 +Subject: ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close + +From: Kai Vehmanen + +commit ce1558c285f9ad04c03b46833a028230771cc0a7 upstream + +A race exists between closing a PCM and update of ELD data. In +hdmi_pcm_close(), hinfo->nid value is modified without taking +spec->pcm_lock. If this happens concurrently while processing an ELD +update in hdmi_pcm_setup_pin(), converter assignment may be done +incorrectly. + +This bug was found by hitting a WARN_ON in snd_hda_spdif_ctls_assign() +in a HDMI receiver connection stress test: + +[2739.684569] WARNING: CPU: 5 PID: 2090 at sound/pci/hda/patch_hdmi.c:1898 check_non_pcm_per_cvt+0x41/0x50 [snd_hda_codec_hdmi] +... +[2739.684707] Call Trace: +[2739.684720] update_eld+0x121/0x5a0 [snd_hda_codec_hdmi] +[2739.684736] hdmi_present_sense+0x21e/0x3b0 [snd_hda_codec_hdmi] +[2739.684750] check_presence_and_report+0x81/0xd0 [snd_hda_codec_hdmi] +[2739.684842] intel_audio_codec_enable+0x122/0x190 [i915] + +Fixes: 42b2987079ec ("ALSA: hda - hdmi playback without monitor in dynamic pcm bind mode") +Signed-off-by: Kai Vehmanen +Cc: +Link: https://lore.kernel.org/r/20201013152628.920764-1-kai.vehmanen@linux.intel.com +Signed-off-by: Takashi Iwai +[sudip: adjust context] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/patch_hdmi.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1955,20 +1955,23 @@ static int hdmi_pcm_close(struct hda_pcm + int pinctl; + int err = 0; + ++ mutex_lock(&spec->pcm_lock); + if (hinfo->nid) { + pcm_idx = hinfo_to_pcm_index(codec, hinfo); +- if (snd_BUG_ON(pcm_idx < 0)) +- return -EINVAL; ++ if (snd_BUG_ON(pcm_idx < 0)) { ++ err = -EINVAL; ++ goto unlock; ++ } + cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); +- if (snd_BUG_ON(cvt_idx < 0)) +- return -EINVAL; ++ if (snd_BUG_ON(cvt_idx < 0)) { ++ err = -EINVAL; ++ goto unlock; ++ } + per_cvt = get_cvt(spec, cvt_idx); +- + snd_BUG_ON(!per_cvt->assigned); + per_cvt->assigned = 0; + hinfo->nid = 0; + +- mutex_lock(&spec->pcm_lock); + snd_hda_spdif_ctls_unassign(codec, pcm_idx); + clear_bit(pcm_idx, &spec->pcm_in_use); + pin_idx = hinfo_to_pin_index(codec, hinfo); +@@ -1996,10 +1999,11 @@ static int hdmi_pcm_close(struct hda_pcm + per_pin->setup = false; + per_pin->channels = 0; + mutex_unlock(&per_pin->lock); +- unlock: +- mutex_unlock(&spec->pcm_lock); + } + ++unlock: ++ mutex_unlock(&spec->pcm_lock); ++ + return err; + } + diff --git a/queue-4.14/alsa-hda-hdmi-use-single-mutex-unlock-in-error-paths.patch b/queue-4.14/alsa-hda-hdmi-use-single-mutex-unlock-in-error-paths.patch new file mode 100644 index 00000000000..50969e1d5e4 --- /dev/null +++ b/queue-4.14/alsa-hda-hdmi-use-single-mutex-unlock-in-error-paths.patch @@ -0,0 +1,215 @@ +From foo@baz Sat Nov 28 03:55:03 PM CET 2020 +From: Takashi Iwai +Date: Thu, 12 Jul 2018 23:06:51 +0200 +Subject: ALSA: hda/hdmi: Use single mutex unlock in error paths + +From: Takashi Iwai + +commit f69548ffafcc4942022f16f2f192b24143de1dba upstream + +Instead of calling mutex_unlock() at each error path multiple times, +take the standard goto-and-a-single-unlock approach. This will +simplify the code and make easier to find the unbalanced mutex locks. + +No functional changes, but only the code readability improvement as a +preliminary work for further changes. + +Signed-off-by: Takashi Iwai +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/patch_hdmi.c | 67 ++++++++++++++++++++++----------------------- + 1 file changed, 33 insertions(+), 34 deletions(-) + +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -339,13 +339,13 @@ static int hdmi_eld_ctl_info(struct snd_ + if (!per_pin) { + /* no pin is bound to the pcm */ + uinfo->count = 0; +- mutex_unlock(&spec->pcm_lock); +- return 0; ++ goto unlock; + } + eld = &per_pin->sink_eld; + uinfo->count = eld->eld_valid ? eld->eld_size : 0; +- mutex_unlock(&spec->pcm_lock); + ++ unlock: ++ mutex_unlock(&spec->pcm_lock); + return 0; + } + +@@ -357,6 +357,7 @@ static int hdmi_eld_ctl_get(struct snd_k + struct hdmi_spec_per_pin *per_pin; + struct hdmi_eld *eld; + int pcm_idx; ++ int err = 0; + + pcm_idx = kcontrol->private_value; + mutex_lock(&spec->pcm_lock); +@@ -365,16 +366,15 @@ static int hdmi_eld_ctl_get(struct snd_k + /* no pin is bound to the pcm */ + memset(ucontrol->value.bytes.data, 0, + ARRAY_SIZE(ucontrol->value.bytes.data)); +- mutex_unlock(&spec->pcm_lock); +- return 0; ++ goto unlock; + } +- eld = &per_pin->sink_eld; + ++ eld = &per_pin->sink_eld; + if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || + eld->eld_size > ELD_MAX_SIZE) { +- mutex_unlock(&spec->pcm_lock); + snd_BUG(); +- return -EINVAL; ++ err = -EINVAL; ++ goto unlock; + } + + memset(ucontrol->value.bytes.data, 0, +@@ -382,9 +382,10 @@ static int hdmi_eld_ctl_get(struct snd_k + if (eld->eld_valid) + memcpy(ucontrol->value.bytes.data, eld->eld_buffer, + eld->eld_size); +- mutex_unlock(&spec->pcm_lock); + +- return 0; ++ unlock: ++ mutex_unlock(&spec->pcm_lock); ++ return err; + } + + static const struct snd_kcontrol_new eld_bytes_ctl = { +@@ -1209,8 +1210,8 @@ static int hdmi_pcm_open(struct hda_pcm_ + pin_idx = hinfo_to_pin_index(codec, hinfo); + if (!spec->dyn_pcm_assign) { + if (snd_BUG_ON(pin_idx < 0)) { +- mutex_unlock(&spec->pcm_lock); +- return -EINVAL; ++ err = -EINVAL; ++ goto unlock; + } + } else { + /* no pin is assigned to the PCM +@@ -1218,16 +1219,13 @@ static int hdmi_pcm_open(struct hda_pcm_ + */ + if (pin_idx < 0) { + err = hdmi_pcm_open_no_pin(hinfo, codec, substream); +- mutex_unlock(&spec->pcm_lock); +- return err; ++ goto unlock; + } + } + + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); +- if (err < 0) { +- mutex_unlock(&spec->pcm_lock); +- return err; +- } ++ if (err < 0) ++ goto unlock; + + per_cvt = get_cvt(spec, cvt_idx); + /* Claim converter */ +@@ -1264,12 +1262,11 @@ static int hdmi_pcm_open(struct hda_pcm_ + per_cvt->assigned = 0; + hinfo->nid = 0; + snd_hda_spdif_ctls_unassign(codec, pcm_idx); +- mutex_unlock(&spec->pcm_lock); +- return -ENODEV; ++ err = -ENODEV; ++ goto unlock; + } + } + +- mutex_unlock(&spec->pcm_lock); + /* Store the updated parameters */ + runtime->hw.channels_min = hinfo->channels_min; + runtime->hw.channels_max = hinfo->channels_max; +@@ -1278,7 +1275,9 @@ static int hdmi_pcm_open(struct hda_pcm_ + + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, 2); +- return 0; ++ unlock: ++ mutex_unlock(&spec->pcm_lock); ++ return err; + } + + /* +@@ -1876,7 +1875,7 @@ static int generic_hdmi_playback_pcm_pre + struct snd_pcm_runtime *runtime = substream->runtime; + bool non_pcm; + int pinctl; +- int err; ++ int err = 0; + + mutex_lock(&spec->pcm_lock); + pin_idx = hinfo_to_pin_index(codec, hinfo); +@@ -1888,13 +1887,12 @@ static int generic_hdmi_playback_pcm_pre + pin_cvt_fixup(codec, NULL, cvt_nid); + snd_hda_codec_setup_stream(codec, cvt_nid, + stream_tag, 0, format); +- mutex_unlock(&spec->pcm_lock); +- return 0; ++ goto unlock; + } + + if (snd_BUG_ON(pin_idx < 0)) { +- mutex_unlock(&spec->pcm_lock); +- return -EINVAL; ++ err = -EINVAL; ++ goto unlock; + } + per_pin = get_pin(spec, pin_idx); + pin_nid = per_pin->pin_nid; +@@ -1933,6 +1931,7 @@ static int generic_hdmi_playback_pcm_pre + /* snd_hda_set_dev_select() has been called before */ + err = spec->ops.setup_stream(codec, cvt_nid, pin_nid, + stream_tag, format); ++ unlock: + mutex_unlock(&spec->pcm_lock); + return err; + } +@@ -1954,6 +1953,7 @@ static int hdmi_pcm_close(struct hda_pcm + struct hdmi_spec_per_cvt *per_cvt; + struct hdmi_spec_per_pin *per_pin; + int pinctl; ++ int err = 0; + + if (hinfo->nid) { + pcm_idx = hinfo_to_pcm_index(codec, hinfo); +@@ -1972,14 +1972,12 @@ static int hdmi_pcm_close(struct hda_pcm + snd_hda_spdif_ctls_unassign(codec, pcm_idx); + clear_bit(pcm_idx, &spec->pcm_in_use); + pin_idx = hinfo_to_pin_index(codec, hinfo); +- if (spec->dyn_pcm_assign && pin_idx < 0) { +- mutex_unlock(&spec->pcm_lock); +- return 0; +- } ++ if (spec->dyn_pcm_assign && pin_idx < 0) ++ goto unlock; + + if (snd_BUG_ON(pin_idx < 0)) { +- mutex_unlock(&spec->pcm_lock); +- return -EINVAL; ++ err = -EINVAL; ++ goto unlock; + } + per_pin = get_pin(spec, pin_idx); + +@@ -1998,10 +1996,11 @@ static int hdmi_pcm_close(struct hda_pcm + per_pin->setup = false; + per_pin->channels = 0; + mutex_unlock(&per_pin->lock); ++ unlock: + mutex_unlock(&spec->pcm_lock); + } + +- return 0; ++ return err; + } + + static const struct hda_pcm_ops generic_ops = { diff --git a/queue-4.14/i2c-imx-fix-reset-of-i2sr_ial-flag.patch b/queue-4.14/i2c-imx-fix-reset-of-i2sr_ial-flag.patch new file mode 100644 index 00000000000..bc073156f27 --- /dev/null +++ b/queue-4.14/i2c-imx-fix-reset-of-i2sr_ial-flag.patch @@ -0,0 +1,69 @@ +From foo@baz Sat Nov 28 03:53:05 PM CET 2020 +From: Christian Eggers +Date: Wed, 7 Oct 2020 10:45:22 +0200 +Subject: i2c: imx: Fix reset of I2SR_IAL flag + +From: Christian Eggers + +commit fa4d30556883f2eaab425b88ba9904865a4d00f3 upstream + +According to the "VFxxx Controller Reference Manual" (and the comment +block starting at line 97), Vybrid requires writing a one for clearing +an interrupt flag. Syncing the method for clearing I2SR_IIF in +i2c_imx_isr(). + +Signed-off-by: Christian Eggers +Fixes: 4b775022f6fd ("i2c: imx: add struct to hold more configurable quirks") +Reviewed-by: Uwe Kleine-König +Cc: stable@vger.kernel.org +Signed-off-by: Wolfram Sang +[sudip: adjust context] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-imx.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -413,6 +413,19 @@ static void i2c_imx_dma_free(struct imx_ + dma->chan_using = NULL; + } + ++static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits) ++{ ++ unsigned int temp; ++ ++ /* ++ * i2sr_clr_opcode is the value to clear all interrupts. Here we want to ++ * clear only , so we write ~i2sr_clr_opcode with just ++ * toggled. This is required because i.MX needs W1C and Vybrid uses W0C. ++ */ ++ temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits; ++ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); ++} ++ + static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) + { + unsigned long orig_jiffies = jiffies; +@@ -425,8 +438,7 @@ static int i2c_imx_bus_busy(struct imx_i + + /* check for arbitration lost */ + if (temp & I2SR_IAL) { +- temp &= ~I2SR_IAL; +- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); ++ i2c_imx_clear_irq(i2c_imx, I2SR_IAL); + return -EAGAIN; + } + +@@ -595,9 +607,7 @@ static irqreturn_t i2c_imx_isr(int irq, + if (temp & I2SR_IIF) { + /* save status register */ + i2c_imx->i2csr = temp; +- temp &= ~I2SR_IIF; +- temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF); +- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); ++ i2c_imx_clear_irq(i2c_imx, I2SR_IIF); + wake_up(&i2c_imx->queue); + return IRQ_HANDLED; + } diff --git a/queue-4.14/series b/queue-4.14/series index bfc15fec554..4f8b6c455c5 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -9,3 +9,6 @@ btrfs-inode-verify-inode-mode-to-avoid-null-pointer-dereference.patch kvm-x86-fix-split-irqchip-vs-interrupt-injection-window-request.patch arm64-pgtable-fix-pte_accessible.patch arm64-pgtable-ensure-dirty-bit-is-preserved-across-pte_wrprotect.patch +i2c-imx-fix-reset-of-i2sr_ial-flag.patch +alsa-hda-hdmi-use-single-mutex-unlock-in-error-paths.patch +alsa-hda-hdmi-fix-incorrect-locking-in-hdmi_pcm_close.patch