Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: emu10k1: Use workqueue instead of kthread for emu1010 fw polling

This patch is a cleanup of EMU1010 dock probing code in emu10k1 driver
to use work instead of kthread in a loop. The work is lighter and
easier to control than kthread, in general.

Instead of a loop with the explicit sleep, we do simply
delayed-schedule the work. At suspend/resume callbacks, the work is
canceled and restarted, respectively.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

+66 -76
+2 -1
include/sound/emu10k1.h
··· 1688 1688 unsigned int internal_clock; /* 44100 or 48000 */ 1689 1689 unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ 1690 1690 unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ 1691 - struct task_struct *firmware_thread; 1691 + struct delayed_work firmware_work; 1692 + u32 last_reg; 1692 1693 }; 1693 1694 1694 1695 struct snd_emu10k1 {
+9
sound/pci/emu10k1/emu10k1.c
··· 194 194 if ((err = snd_card_register(card)) < 0) 195 195 goto error; 196 196 197 + if (emu->card_capabilities->emu_model) 198 + schedule_delayed_work(&emu->emu1010.firmware_work, 0); 199 + 197 200 pci_set_drvdata(pci, card); 198 201 dev++; 199 202 return 0; ··· 221 218 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 222 219 223 220 emu->suspend = 1; 221 + 222 + cancel_delayed_work_sync(&emu->emu1010.firmware_work); 224 223 225 224 snd_pcm_suspend_all(emu->pcm); 226 225 snd_pcm_suspend_all(emu->pcm_mic); ··· 257 252 emu->suspend = 0; 258 253 259 254 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 255 + 256 + if (emu->card_capabilities->emu_model) 257 + schedule_delayed_work(&emu->emu1010.firmware_work, 0); 258 + 260 259 return 0; 261 260 } 262 261
+55 -75
sound/pci/emu10k1/emu10k1_main.c
··· 32 32 */ 33 33 34 34 #include <linux/sched.h> 35 - #include <linux/kthread.h> 36 35 #include <linux/delay.h> 37 36 #include <linux/init.h> 38 37 #include <linux/module.h> ··· 741 742 return snd_emu1010_load_firmware_entry(emu, *fw); 742 743 } 743 744 744 - static int emu1010_firmware_thread(void *data) 745 + static void emu1010_firmware_work(struct work_struct *work) 745 746 { 746 - struct snd_emu10k1 *emu = data; 747 + struct snd_emu10k1 *emu; 747 748 u32 tmp, tmp2, reg; 748 - u32 last_reg = 0; 749 749 int err; 750 750 751 - for (;;) { 752 - /* Delay to allow Audio Dock to settle */ 753 - msleep_interruptible(1000); 754 - if (kthread_should_stop()) 755 - break; 751 + emu = container_of(work, struct snd_emu10k1, 752 + emu1010.firmware_work.work); 753 + if (emu->card->shutdown) 754 + return; 756 755 #ifdef CONFIG_PM_SLEEP 757 - if (emu->suspend) 758 - continue; 756 + if (emu->suspend) 757 + return; 759 758 #endif 760 - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ 761 - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */ 762 - if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { 763 - /* Audio Dock attached */ 764 - /* Return to Audio Dock programming mode */ 765 - dev_info(emu->card->dev, 766 - "emu1010: Loading Audio Dock Firmware\n"); 767 - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); 768 - err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); 769 - if (err < 0) 770 - continue; 759 + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ 760 + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */ 761 + if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { 762 + /* Audio Dock attached */ 763 + /* Return to Audio Dock programming mode */ 764 + dev_info(emu->card->dev, 765 + "emu1010: Loading Audio Dock Firmware\n"); 766 + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 767 + EMU_HANA_FPGA_CONFIG_AUDIODOCK); 768 + err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); 769 + if (err < 0) 770 + goto next; 771 771 772 - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); 773 - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); 772 + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); 773 + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); 774 + dev_info(emu->card->dev, 775 + "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp); 776 + /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ 777 + snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); 778 + dev_info(emu->card->dev, 779 + "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); 780 + if ((tmp & 0x1f) != 0x15) { 781 + /* FPGA failed to be programmed */ 774 782 dev_info(emu->card->dev, 775 - "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", 783 + "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", 776 784 tmp); 777 - /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ 778 - snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); 779 - dev_info(emu->card->dev, 780 - "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); 781 - if ((tmp & 0x1f) != 0x15) { 782 - /* FPGA failed to be programmed */ 783 - dev_info(emu->card->dev, 784 - "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", 785 - tmp); 786 - continue; 787 - } 788 - dev_info(emu->card->dev, 789 - "emu1010: Audio Dock Firmware loaded\n"); 790 - snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); 791 - snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); 792 - dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", 793 - tmp, tmp2); 794 - /* Sync clocking between 1010 and Dock */ 795 - /* Allow DLL to settle */ 796 - msleep(10); 797 - /* Unmute all. Default is muted after a firmware load */ 798 - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); 799 - } else if (!reg && last_reg) { 800 - /* Audio Dock removed */ 801 - dev_info(emu->card->dev, 802 - "emu1010: Audio Dock detached\n"); 803 - /* Unmute all */ 804 - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); 785 + goto next; 805 786 } 806 - 807 - last_reg = reg; 787 + dev_info(emu->card->dev, 788 + "emu1010: Audio Dock Firmware loaded\n"); 789 + snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); 790 + snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); 791 + dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); 792 + /* Sync clocking between 1010 and Dock */ 793 + /* Allow DLL to settle */ 794 + msleep(10); 795 + /* Unmute all. Default is muted after a firmware load */ 796 + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); 797 + } else if (!reg && emu->emu1010.last_reg) { 798 + /* Audio Dock removed */ 799 + dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); 800 + /* Unmute all */ 801 + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); 808 802 } 809 - dev_info(emu->card->dev, "emu1010: firmware thread stopping\n"); 810 - return 0; 803 + 804 + next: 805 + emu->emu1010.last_reg = reg; 806 + if (!emu->card->shutdown) 807 + schedule_delayed_work(&emu->emu1010.firmware_work, 808 + msecs_to_jiffies(1000)); 811 809 } 812 810 813 811 /* ··· 1110 1114 snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); 1111 1115 snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ 1112 1116 1113 - /* Start Micro/Audio Dock firmware loader thread */ 1114 - if (!emu->emu1010.firmware_thread) { 1115 - emu->emu1010.firmware_thread = 1116 - kthread_create(emu1010_firmware_thread, emu, 1117 - "emu1010_firmware"); 1118 - if (IS_ERR(emu->emu1010.firmware_thread)) { 1119 - err = PTR_ERR(emu->emu1010.firmware_thread); 1120 - emu->emu1010.firmware_thread = NULL; 1121 - dev_info(emu->card->dev, 1122 - "emu1010: Creating thread failed\n"); 1123 - return err; 1124 - } 1125 - 1126 - wake_up_process(emu->emu1010.firmware_thread); 1127 - } 1128 - 1129 1117 #if 0 1130 1118 snd_emu1010_fpga_link_dst_src_write(emu, 1131 1119 EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ ··· 1267 1287 /* Disable 48Volt power to Audio Dock */ 1268 1288 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); 1269 1289 } 1270 - if (emu->emu1010.firmware_thread) 1271 - kthread_stop(emu->emu1010.firmware_thread); 1290 + cancel_delayed_work_sync(&emu->emu1010.firmware_work); 1272 1291 release_firmware(emu->firmware); 1273 1292 release_firmware(emu->dock_fw); 1274 1293 if (emu->irq >= 0) ··· 1809 1830 emu->irq = -1; 1810 1831 emu->synth = NULL; 1811 1832 emu->get_synth_voice = NULL; 1833 + INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); 1812 1834 /* read revision & serial */ 1813 1835 emu->revision = pci->revision; 1814 1836 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);