Patch "ASoC: qcom: Actually clear DMA interrupt register for HDMI" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ASoC: qcom: Actually clear DMA interrupt register for HDMI

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     asoc-qcom-actually-clear-dma-interrupt-register-for-.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit b4f1e694a9485f7a82e6895a25d927c15a45e854
Author: Stephen Boyd <swboyd@xxxxxxxxxxxx>
Date:   Wed Feb 9 15:25:20 2022 -0800

    ASoC: qcom: Actually clear DMA interrupt register for HDMI
    
    [ Upstream commit c8d251f51ee61df06ee0e419348d8c9160bbfb86 ]
    
    In commit da0363f7bfd3 ("ASoC: qcom: Fix for DMA interrupt clear reg
    overwriting") we changed regmap_write() to regmap_update_bits() so that
    we can avoid overwriting bits that we didn't intend to modify.
    Unfortunately this change breaks the case where a register is writable
    but not readable, which is exactly how the HDMI irq clear register is
    designed (grep around LPASS_HDMITX_APP_IRQCLEAR_REG to see how it's
    write only). That's because regmap_update_bits() tries to read the
    register from the hardware and if it isn't readable it looks in the
    regmap cache to see what was written there last time to compare against
    what we want to write there. Eventually, we're unable to modify this
    register at all because the bits that we're trying to set are already
    set in the cache.
    
    This is doubly bad for the irq clear register because you have to write
    the bit to clear an interrupt. Given the irq is level triggered, we see
    an interrupt storm upon plugging in an HDMI cable and starting audio
    playback. The irq storm is so great that performance degrades
    significantly, leading to CPU soft lockups.
    
    Fix it by using regmap_write_bits() so that we really do write the bits
    in the clear register that we want to. This brings the number of irqs
    handled by lpass_dma_interrupt_handler() down from ~150k/sec to ~10/sec.
    
    Fixes: da0363f7bfd3 ("ASoC: qcom: Fix for DMA interrupt clear reg overwriting")
    Cc: Srinivasa Rao Mandadapu <srivasam@xxxxxxxxxxxxxx>
    Cc: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx>
    Signed-off-by: Stephen Boyd <swboyd@xxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20220209232520.4017634-1-swboyd@xxxxxxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index a59e9d20cb46b..4b1773c1fb95f 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -524,7 +524,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
 			return -EINVAL;
 		}
 
-		ret = regmap_update_bits(map, reg_irqclr, val_irqclr, val_irqclr);
+		ret = regmap_write_bits(map, reg_irqclr, val_irqclr, val_irqclr);
 		if (ret) {
 			dev_err(soc_runtime->dev, "error writing to irqclear reg: %d\n", ret);
 			return ret;
@@ -665,7 +665,7 @@ static irqreturn_t lpass_dma_interrupt_handler(
 	return -EINVAL;
 	}
 	if (interrupts & LPAIF_IRQ_PER(chan)) {
-		rv = regmap_update_bits(map, reg, mask, (LPAIF_IRQ_PER(chan) | val));
+		rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_PER(chan) | val));
 		if (rv) {
 			dev_err(soc_runtime->dev,
 				"error writing to irqclear reg: %d\n", rv);
@@ -676,7 +676,7 @@ static irqreturn_t lpass_dma_interrupt_handler(
 	}
 
 	if (interrupts & LPAIF_IRQ_XRUN(chan)) {
-		rv = regmap_update_bits(map, reg, mask, (LPAIF_IRQ_XRUN(chan) | val));
+		rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_XRUN(chan) | val));
 		if (rv) {
 			dev_err(soc_runtime->dev,
 				"error writing to irqclear reg: %d\n", rv);
@@ -688,7 +688,7 @@ static irqreturn_t lpass_dma_interrupt_handler(
 	}
 
 	if (interrupts & LPAIF_IRQ_ERR(chan)) {
-		rv = regmap_update_bits(map, reg, mask, (LPAIF_IRQ_ERR(chan) | val));
+		rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_ERR(chan) | val));
 		if (rv) {
 			dev_err(soc_runtime->dev,
 				"error writing to irqclear reg: %d\n", rv);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux