Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aeaa6203 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 4e4dfe4c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1688,7 +1688,8 @@ struct snd_emu1010 {
	unsigned int internal_clock; /* 44100 or 48000 */
	unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
	unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
	struct task_struct *firmware_thread;
	struct delayed_work firmware_work;
	u32 last_reg;
};

struct snd_emu10k1 {
+9 −0
Original line number Diff line number Diff line
@@ -194,6 +194,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
	if ((err = snd_card_register(card)) < 0)
		goto error;

	if (emu->card_capabilities->emu_model)
		schedule_delayed_work(&emu->emu1010.firmware_work, 0);

	pci_set_drvdata(pci, card);
	dev++;
	return 0;
@@ -219,6 +222,8 @@ static int snd_emu10k1_suspend(struct device *dev)

	emu->suspend = 1;

	cancel_delayed_work_sync(&emu->emu1010.firmware_work);

	snd_pcm_suspend_all(emu->pcm);
	snd_pcm_suspend_all(emu->pcm_mic);
	snd_pcm_suspend_all(emu->pcm_efx);
@@ -252,6 +257,10 @@ static int snd_emu10k1_resume(struct device *dev)
	emu->suspend = 0;

	snd_power_change_state(card, SNDRV_CTL_POWER_D0);

	if (emu->card_capabilities->emu_model)
		schedule_delayed_work(&emu->emu1010.firmware_work, 0);

	return 0;
}

+56 −76
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@
 */

#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -742,21 +741,19 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
	return snd_emu1010_load_firmware_entry(emu, *fw);
}

static int emu1010_firmware_thread(void *data)
static void emu1010_firmware_work(struct work_struct *work)
{
	struct snd_emu10k1 *emu = data;
	struct snd_emu10k1 *emu;
	u32 tmp, tmp2, reg;
	u32 last_reg = 0;
	int err;

	for (;;) {
		/* Delay to allow Audio Dock to settle */
		msleep_interruptible(1000);
		if (kthread_should_stop())
			break;
	emu = container_of(work, struct snd_emu10k1,
			   emu1010.firmware_work.work);
	if (emu->card->shutdown)
		return;
#ifdef CONFIG_PM_SLEEP
	if (emu->suspend)
			continue;
		return;
#endif
	snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
@@ -765,16 +762,16 @@ static int emu1010_firmware_thread(void *data)
		/* Return to Audio Dock programming mode */
		dev_info(emu->card->dev,
			 "emu1010: Loading Audio Dock Firmware\n");
			snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
		snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
				       EMU_HANA_FPGA_CONFIG_AUDIODOCK);
		err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
		if (err < 0)
				continue;
			goto next;

		snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
		snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp);
		dev_info(emu->card->dev,
				 "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n",
				 tmp);
			 "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp);
		/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
		snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
		dev_info(emu->card->dev,
@@ -784,31 +781,30 @@ static int emu1010_firmware_thread(void *data)
			dev_info(emu->card->dev,
				 "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
				 tmp);
				continue;
			goto next;
		}
		dev_info(emu->card->dev,
			 "emu1010: Audio Dock Firmware loaded\n");
		snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
		snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
			dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n",
				   tmp, tmp2);
		dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
		/* Sync clocking between 1010 and Dock */
		/* Allow DLL to settle */
		msleep(10);
		/* Unmute all. Default is muted after a firmware load */
		snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
		} else if (!reg && last_reg) {
	} else if (!reg && emu->emu1010.last_reg) {
		/* Audio Dock removed */
			dev_info(emu->card->dev,
				 "emu1010: Audio Dock detached\n");
		dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
		/* Unmute all */
		snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
	}

		last_reg = reg;
	}
	dev_info(emu->card->dev, "emu1010: firmware thread stopping\n");
	return 0;
 next:
	emu->emu1010.last_reg = reg;
	if (!emu->card->shutdown)
		schedule_delayed_work(&emu->emu1010.firmware_work,
				      msecs_to_jiffies(1000));
}

/*
@@ -1114,22 +1110,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
	snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
	snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif  (or 0x11 for aes/ebu) */

	/* Start Micro/Audio Dock firmware loader thread */
	if (!emu->emu1010.firmware_thread) {
		emu->emu1010.firmware_thread =
			kthread_create(emu1010_firmware_thread, emu,
				       "emu1010_firmware");
		if (IS_ERR(emu->emu1010.firmware_thread)) {
			err = PTR_ERR(emu->emu1010.firmware_thread);
			emu->emu1010.firmware_thread = NULL;
			dev_info(emu->card->dev,
					"emu1010: Creating thread failed\n");
			return err;
		}

		wake_up_process(emu->emu1010.firmware_thread);
	}

#if 0
	snd_emu1010_fpga_link_dst_src_write(emu,
		EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
@@ -1287,8 +1267,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
		/* Disable 48Volt power to Audio Dock */
		snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
	}
	if (emu->emu1010.firmware_thread)
		kthread_stop(emu->emu1010.firmware_thread);
	cancel_delayed_work_sync(&emu->emu1010.firmware_work);
	release_firmware(emu->firmware);
	release_firmware(emu->dock_fw);
	if (emu->irq >= 0)
@@ -1830,6 +1809,7 @@ int snd_emu10k1_create(struct snd_card *card,
	emu->irq = -1;
	emu->synth = NULL;
	emu->get_synth_voice = NULL;
	INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
	/* read revision & serial */
	emu->revision = pci->revision;
	pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);