Commit 5bff69b3 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: cs46xx: Allocate resources with device-managed APIs

This patch converts the resource management in PCI cs46xx driver with
devres as a clean up.  Each manual resource management is converted
with the corresponding devres helper, and the card object release is
managed now via card->private_free instead of a lowlevel snd_device.

This should give no user-visible functional changes.

Link: https://lore.kernel.org/r/20210715075941.23332-31-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1656fa6e
Loading
Loading
Loading
Loading
+13 −38
Original line number Diff line number Diff line
@@ -66,61 +66,44 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
		return -ENOENT;
	}

	err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
			   0, &card);
	err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
				sizeof(*chip), &card);
	if (err < 0)
		return err;
	chip = card->private_data;
	err = snd_cs46xx_create(card, pci,
				external_amp[dev], thinkpad[dev],
				&chip);
	if (err < 0) {
		snd_card_free(card);
				external_amp[dev], thinkpad[dev]);
	if (err < 0)
		return err;
	}
	card->private_data = chip;
	chip->accept_valid = mmap_valid[dev];
	err = snd_cs46xx_pcm(chip, 0);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
	err = snd_cs46xx_pcm_rear(chip, 1);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}
	err = snd_cs46xx_pcm_iec958(chip, 2);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}
#endif
	err = snd_cs46xx_mixer(chip, 2);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
	if (chip->nr_ac97_codecs ==2) {
		err = snd_cs46xx_pcm_center_lfe(chip, 3);
		if (err < 0) {
			snd_card_free(card);
		if (err < 0)
			return err;
	}
	}
#endif
	err = snd_cs46xx_midi(chip, 0);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}
	err = snd_cs46xx_start_dsp(chip);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}


	snd_cs46xx_gameport(chip);

@@ -133,26 +116,18 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
		chip->irq);

	err = snd_card_register(card);
	if (err < 0) {
		snd_card_free(card);
	if (err < 0)
		return err;
	}

	pci_set_drvdata(pci, card);
	dev++;
	return 0;
}

static void snd_card_cs46xx_remove(struct pci_dev *pci)
{
	snd_card_free(pci_get_drvdata(pci));
}

static struct pci_driver cs46xx_driver = {
	.name = KBUILD_MODNAME,
	.id_table = snd_cs46xx_ids,
	.probe = snd_card_cs46xx_probe,
	.remove = snd_card_cs46xx_remove,
#ifdef CONFIG_PM_SLEEP
	.driver = {
		.pm = &snd_cs46xx_pm,
+1 −3
Original line number Diff line number Diff line
@@ -1635,7 +1635,6 @@ struct snd_cs46xx_region {
	unsigned long base;
	void __iomem *remap_addr;
	unsigned long size;
	struct resource *resource;
};

struct snd_cs46xx {
@@ -1718,8 +1717,7 @@ struct snd_cs46xx {

int snd_cs46xx_create(struct snd_card *card,
		      struct pci_dev *pci,
		      int external_amp, int thinkpad,
		      struct snd_cs46xx **rcodec);
		      int external_amp, int thinkpad);
extern const struct dev_pm_ops snd_cs46xx_pm;

int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device);
+24 −87
Original line number Diff line number Diff line
@@ -1865,13 +1865,6 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
/*
 *  Mixer routines
 */
static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
	struct snd_cs46xx *chip = bus->private_data;

	chip->ac97_bus = NULL;
}

static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
{
	struct snd_cs46xx *chip = ac97->private_data;
@@ -2487,7 +2480,6 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
	err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
	if (err < 0)
		return err;
	chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;

	if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
		return -ENXIO;
@@ -2913,12 +2905,12 @@ static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
}


static int snd_cs46xx_free(struct snd_cs46xx *chip)
static void snd_cs46xx_free(struct snd_card *card)
{
	struct snd_cs46xx *chip = card->private_data;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
	int idx;

	if (snd_BUG_ON(!chip))
		return -EINVAL;
#endif

	if (chip->active_ctrl)
		chip->active_ctrl(chip, 1);
@@ -2930,22 +2922,11 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
	
	snd_cs46xx_proc_done(chip);

	if (chip->region.idx[0].resource)
	snd_cs46xx_hw_stop(chip);

	if (chip->irq >= 0)
		free_irq(chip->irq, chip);

	if (chip->active_ctrl)
		chip->active_ctrl(chip, -chip->amplifier);

	for (idx = 0; idx < 5; idx++) {
		struct snd_cs46xx_region *region = &chip->region.idx[idx];

		iounmap(region->remap_addr);
		release_and_free_resource(region->resource);
	}

#ifdef CONFIG_SND_CS46XX_NEW_DSP
	if (chip->dsp_spos_instance) {
		cs46xx_dsp_spos_destroy(chip);
@@ -2956,20 +2937,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
#else
	vfree(chip->ba1);
#endif
	
#ifdef CONFIG_PM_SLEEP
	kfree(chip->saved_regs);
#endif

	pci_disable_device(chip->pci);
	kfree(chip);
	return 0;
}

static int snd_cs46xx_dev_free(struct snd_device *device)
{
	struct snd_cs46xx *chip = device->device_data;
	return snd_cs46xx_free(chip);
}

/*
@@ -3868,30 +3835,19 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);

int snd_cs46xx_create(struct snd_card *card,
		      struct pci_dev *pci,
		      int external_amp, int thinkpad,
		      struct snd_cs46xx **rchip)
		      int external_amp, int thinkpad)
{
	struct snd_cs46xx *chip;
	struct snd_cs46xx *chip = card->private_data;
	int err, idx;
	struct snd_cs46xx_region *region;
	struct cs_card_type *cp;
	u16 ss_card, ss_vendor;
	static const struct snd_device_ops ops = {
		.dev_free =	snd_cs46xx_dev_free,
	};
	
	*rchip = NULL;
	
	/* enable PCI device */
	err = pci_enable_device(pci);
	err = pcim_enable_device(pci);
	if (err < 0)
		return err;

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (chip == NULL) {
		pci_disable_device(pci);
		return -ENOMEM;
	}
	spin_lock_init(&chip->reg_lock);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
	mutex_init(&chip->spos_mutex);
@@ -3899,6 +3855,10 @@ int snd_cs46xx_create(struct snd_card *card,
	chip->card = card;
	chip->pci = pci;
	chip->irq = -1;

	err = pci_request_regions(pci, "CS46xx");
	if (err < 0)
		return err;
	chip->ba0_addr = pci_resource_start(pci, 0);
	chip->ba1_addr = pci_resource_start(pci, 1);
	if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
@@ -3906,7 +3866,6 @@ int snd_cs46xx_create(struct snd_card *card,
		dev_err(chip->card->dev,
			"wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
			   chip->ba0_addr, chip->ba1_addr);
	    	snd_cs46xx_free(chip);
	    	return -ENOMEM;
	}

@@ -3978,67 +3937,45 @@ int snd_cs46xx_create(struct snd_card *card,

	for (idx = 0; idx < 5; idx++) {
		region = &chip->region.idx[idx];
		region->resource = request_mem_region(region->base, region->size,
						      region->name);
		if (!region->resource) {
			dev_err(chip->card->dev,
				"unable to request memory region 0x%lx-0x%lx\n",
				   region->base, region->base + region->size - 1);
			snd_cs46xx_free(chip);
			return -EBUSY;
		}
		region->remap_addr = ioremap(region->base, region->size);
		region->remap_addr = devm_ioremap(&pci->dev, region->base,
						  region->size);
		if (region->remap_addr == NULL) {
			dev_err(chip->card->dev,
				"%s ioremap problem\n", region->name);
			snd_cs46xx_free(chip);
			return -ENOMEM;
		}
	}

	if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
			KBUILD_MODNAME, chip)) {
	if (devm_request_irq(&pci->dev, pci->irq, snd_cs46xx_interrupt,
			     IRQF_SHARED, KBUILD_MODNAME, chip)) {
		dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
		snd_cs46xx_free(chip);
		return -EBUSY;
	}
	chip->irq = pci->irq;
	card->sync_irq = chip->irq;
	card->private_free = snd_cs46xx_free;

#ifdef CONFIG_SND_CS46XX_NEW_DSP
	chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
	if (chip->dsp_spos_instance == NULL) {
		snd_cs46xx_free(chip);
	if (!chip->dsp_spos_instance)
		return -ENOMEM;
	}
#endif

	err = snd_cs46xx_chip_init(chip);
	if (err < 0) {
		snd_cs46xx_free(chip);
		return err;
	}

	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
	if (err < 0) {
		snd_cs46xx_free(chip);
	if (err < 0)
		return err;
	}
	
	snd_cs46xx_proc_init(card, chip);

#ifdef CONFIG_PM_SLEEP
	chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs),
	chip->saved_regs = devm_kmalloc_array(&pci->dev,
					      ARRAY_SIZE(saved_regs),
					      sizeof(*chip->saved_regs),
					      GFP_KERNEL);
	if (!chip->saved_regs) {
		snd_cs46xx_free(chip);
	if (!chip->saved_regs)
		return -ENOMEM;
	}
#endif

	chip->active_ctrl(chip, -1); /* disable CLKRUN */

	*rchip = chip;
	return 0;
}