summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>2023-04-28 12:59:39 +0300
committerTakashi Iwai <tiwai@suse.de>2023-05-08 10:22:18 +0300
commit35d1d5824ffe1cfc849aa1694488d779dc79a920 (patch)
tree7ecd8a8f2d1221153fc3434374ad9fbb28f65421
parent50164f69f8c71377bfa3d356b8a6bc18b2197a45 (diff)
downloadlinux-35d1d5824ffe1cfc849aa1694488d779dc79a920.tar.xz
ALSA: emu10k1: fix locking in snd_emu1010_fpga_link_dst_src_write()
This is a multi-register operation, which must be locked in its entirety. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Link: https://lore.kernel.org/r/20230428095941.1706278-5-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/emu10k1/io.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index cfb96a67aa35..aee84c3f9f37 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -233,16 +233,13 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
return err;
}
-void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
+static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32 value)
{
- unsigned long flags;
-
if (snd_BUG_ON(reg > 0x3f))
return;
reg += 0x40; /* 0x40 upwards are registers. */
if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */
return;
- spin_lock_irqsave(&emu->emu_lock, flags);
outw(reg, emu->port + A_GPIO);
udelay(10);
outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
@@ -250,6 +247,14 @@ void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
outw(value, emu->port + A_GPIO);
udelay(10);
outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
+}
+
+void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ snd_emu1010_fpga_write_locked(emu, reg, value);
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
@@ -276,14 +281,18 @@ void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
*/
void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)
{
+ unsigned long flags;
+
if (snd_BUG_ON(dst & ~0x71f))
return;
if (snd_BUG_ON(src & ~0x71f))
return;
- snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
- snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
- snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);
- snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
+ snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
+ snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCHI, src >> 8);
+ snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCLO, src & 0x1f);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
}
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)