ALSA: cs5535audio: Allocate resources with device-managed APIs

This patch converts the resource management in PCI cs5535audio 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.  A slight uncertain change is the call of
olpc_quirks_cleanup() at removal: formerly this was called
unconditionally at remove, but this should be a conditionally call,
hence the machine_is_olpc() check is added here as well.

This should give no user-visible functional changes.

Link: https://lore.kernel.org/r/20210715075941.23332-32-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2021-07-15 09:58:53 +02:00
parent 5bff69b364
commit 5eba4c646d
2 changed files with 25 additions and 80 deletions

View File

@ -237,51 +237,24 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
static void snd_cs5535audio_free(struct snd_card *card)
{
pci_set_power_state(cs5535au->pci, PCI_D3hot);
if (cs5535au->irq >= 0)
free_irq(cs5535au->irq, cs5535au);
pci_release_regions(cs5535au->pci);
pci_disable_device(cs5535au->pci);
kfree(cs5535au);
return 0;
}
static int snd_cs5535audio_dev_free(struct snd_device *device)
{
struct cs5535audio *cs5535au = device->device_data;
return snd_cs5535audio_free(cs5535au);
olpc_quirks_cleanup();
}
static int snd_cs5535audio_create(struct snd_card *card,
struct pci_dev *pci,
struct cs5535audio **rcs5535au)
struct pci_dev *pci)
{
struct cs5535audio *cs5535au;
struct cs5535audio *cs5535au = card->private_data;
int err;
static const struct snd_device_ops ops = {
.dev_free = snd_cs5535audio_dev_free,
};
*rcs5535au = NULL;
err = pci_enable_device(pci);
err = pcim_enable_device(pci);
if (err < 0)
return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_warn(card->dev, "unable to get 32bit dma\n");
err = -ENXIO;
goto pcifail;
}
cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
if (cs5535au == NULL) {
err = -ENOMEM;
goto pcifail;
return -ENXIO;
}
spin_lock_init(&cs5535au->reg_lock);
@ -290,38 +263,22 @@ static int snd_cs5535audio_create(struct snd_card *card,
cs5535au->irq = -1;
err = pci_request_regions(pci, "CS5535 Audio");
if (err < 0) {
kfree(cs5535au);
goto pcifail;
}
if (err < 0)
return err;
cs5535au->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_cs5535audio_interrupt,
IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
if (devm_request_irq(&pci->dev, pci->irq, snd_cs5535audio_interrupt,
IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
err = -EBUSY;
goto sndfail;
return -EBUSY;
}
cs5535au->irq = pci->irq;
card->sync_irq = cs5535au->irq;
pci_set_master(pci);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops);
if (err < 0)
goto sndfail;
*rcs5535au = cs5535au;
return 0;
sndfail: /* leave the device alive, just kill the snd */
snd_cs5535audio_free(cs5535au);
return err;
pcifail:
pci_disable_device(pci);
return err;
}
static int snd_cs5535audio_probe(struct pci_dev *pci,
@ -339,24 +296,24 @@ static int snd_cs5535audio_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(*cs5535au), &card);
if (err < 0)
return err;
cs5535au = card->private_data;
card->private_free = snd_cs5535audio_free;
err = snd_cs5535audio_create(card, pci);
if (err < 0)
return err;
err = snd_cs5535audio_create(card, pci, &cs5535au);
if (err < 0)
goto probefail_out;
card->private_data = cs5535au;
err = snd_cs5535audio_mixer(cs5535au);
if (err < 0)
goto probefail_out;
return err;
err = snd_cs5535audio_pcm(cs5535au);
if (err < 0)
goto probefail_out;
return err;
strcpy(card->driver, DRIVER_NAME);
@ -367,28 +324,17 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
goto probefail_out;
return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
probefail_out:
snd_card_free(card);
return err;
}
static void snd_cs5535audio_remove(struct pci_dev *pci)
{
olpc_quirks_cleanup();
snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver cs5535audio_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5535audio_ids,
.probe = snd_cs5535audio_probe,
.remove = snd_cs5535audio_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_cs5535audio_pm,

View File

@ -171,10 +171,8 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
ac97->private_data));
if (err < 0) {
gpio_free(OLPC_GPIO_MIC_AC);
if (err < 0)
return err;
}
}
/* turn off the mic by default */
@ -184,5 +182,6 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
void olpc_quirks_cleanup(void)
{
gpio_free(OLPC_GPIO_MIC_AC);
if (machine_is_olpc())
gpio_free(OLPC_GPIO_MIC_AC);
}