Commit 2ca6cbde authored by Takashi Iwai's avatar Takashi Iwai

ALSA: sonicvibes: Allocate resources with device-managed APIs

This patch converts the resource management in PCI sonicvibes 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-25-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 499ddc16
...@@ -1193,69 +1193,43 @@ static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { ret ...@@ -1193,69 +1193,43 @@ static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { ret
static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { } static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
#endif #endif
static int snd_sonicvibes_free(struct sonicvibes *sonic) static void snd_sonicvibes_free(struct snd_card *card)
{ {
struct sonicvibes *sonic = card->private_data;
snd_sonicvibes_free_gameport(sonic); snd_sonicvibes_free_gameport(sonic);
pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port); pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port); pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
if (sonic->irq >= 0)
free_irq(sonic->irq, sonic);
release_and_free_resource(sonic->res_dmaa);
release_and_free_resource(sonic->res_dmac);
pci_release_regions(sonic->pci);
pci_disable_device(sonic->pci);
kfree(sonic);
return 0;
}
static int snd_sonicvibes_dev_free(struct snd_device *device)
{
struct sonicvibes *sonic = device->device_data;
return snd_sonicvibes_free(sonic);
} }
static int snd_sonicvibes_create(struct snd_card *card, static int snd_sonicvibes_create(struct snd_card *card,
struct pci_dev *pci, struct pci_dev *pci,
int reverb, int reverb,
int mge, int mge)
struct sonicvibes **rsonic)
{ {
struct sonicvibes *sonic; struct sonicvibes *sonic = card->private_data;
unsigned int dmaa, dmac; unsigned int dmaa, dmac;
int err; int err;
static const struct snd_device_ops ops = {
.dev_free = snd_sonicvibes_dev_free,
};
*rsonic = NULL;
/* enable PCI device */ /* enable PCI device */
err = pci_enable_device(pci); err = pcim_enable_device(pci);
if (err < 0) if (err < 0)
return err; return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */ /* check, if we can restrict PCI DMA transfers to 24 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(card->dev, dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n"); "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO; return -ENXIO;
} }
sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
if (sonic == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
spin_lock_init(&sonic->reg_lock); spin_lock_init(&sonic->reg_lock);
sonic->card = card; sonic->card = card;
sonic->pci = pci; sonic->pci = pci;
sonic->irq = -1; sonic->irq = -1;
err = pci_request_regions(pci, "S3 SonicVibes"); err = pci_request_regions(pci, "S3 SonicVibes");
if (err < 0) { if (err < 0)
kfree(sonic);
pci_disable_device(pci);
return err; return err;
}
sonic->sb_port = pci_resource_start(pci, 0); sonic->sb_port = pci_resource_start(pci, 0);
sonic->enh_port = pci_resource_start(pci, 1); sonic->enh_port = pci_resource_start(pci, 1);
...@@ -1263,14 +1237,14 @@ static int snd_sonicvibes_create(struct snd_card *card, ...@@ -1263,14 +1237,14 @@ static int snd_sonicvibes_create(struct snd_card *card,
sonic->midi_port = pci_resource_start(pci, 3); sonic->midi_port = pci_resource_start(pci, 3);
sonic->game_port = pci_resource_start(pci, 4); sonic->game_port = pci_resource_start(pci, 4);
if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED, if (devm_request_irq(&pci->dev, pci->irq, snd_sonicvibes_interrupt,
KBUILD_MODNAME, sonic)) { IRQF_SHARED, KBUILD_MODNAME, sonic)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
snd_sonicvibes_free(sonic);
return -EBUSY; return -EBUSY;
} }
sonic->irq = pci->irq; sonic->irq = pci->irq;
card->sync_irq = sonic->irq; card->sync_irq = sonic->irq;
card->private_free = snd_sonicvibes_free;
pci_read_config_dword(pci, 0x40, &dmaa); pci_read_config_dword(pci, 0x40, &dmaa);
pci_read_config_dword(pci, 0x48, &dmac); pci_read_config_dword(pci, 0x48, &dmac);
...@@ -1294,17 +1268,17 @@ static int snd_sonicvibes_create(struct snd_card *card, ...@@ -1294,17 +1268,17 @@ static int snd_sonicvibes_create(struct snd_card *card,
pci_write_config_dword(pci, 0x40, dmaa); pci_write_config_dword(pci, 0x40, dmaa);
pci_write_config_dword(pci, 0x48, dmac); pci_write_config_dword(pci, 0x48, dmac);
sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A"); sonic->res_dmaa = devm_request_region(&pci->dev, dmaa, 0x10,
"S3 SonicVibes DDMA-A");
if (!sonic->res_dmaa) { if (!sonic->res_dmaa) {
snd_sonicvibes_free(sonic);
dev_err(card->dev, dev_err(card->dev,
"unable to grab DDMA-A port at 0x%x-0x%x\n", "unable to grab DDMA-A port at 0x%x-0x%x\n",
dmaa, dmaa + 0x10 - 1); dmaa, dmaa + 0x10 - 1);
return -EBUSY; return -EBUSY;
} }
sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C"); sonic->res_dmac = devm_request_region(&pci->dev, dmac, 0x10,
"S3 SonicVibes DDMA-C");
if (!sonic->res_dmac) { if (!sonic->res_dmac) {
snd_sonicvibes_free(sonic);
dev_err(card->dev, dev_err(card->dev,
"unable to grab DDMA-C port at 0x%x-0x%x\n", "unable to grab DDMA-C port at 0x%x-0x%x\n",
dmac, dmac + 0x10 - 1); dmac, dmac + 0x10 - 1);
...@@ -1365,15 +1339,7 @@ static int snd_sonicvibes_create(struct snd_card *card, ...@@ -1365,15 +1339,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
#endif #endif
sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION); sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops);
if (err < 0) {
snd_sonicvibes_free(sonic);
return err;
}
snd_sonicvibes_proc_init(sonic); snd_sonicvibes_proc_init(sonic);
*rsonic = sonic;
return 0; return 0;
} }
...@@ -1429,7 +1395,7 @@ static int snd_sonic_probe(struct pci_dev *pci, ...@@ -1429,7 +1395,7 @@ static int snd_sonic_probe(struct pci_dev *pci,
struct sonicvibes *sonic; struct sonicvibes *sonic;
struct snd_rawmidi *midi_uart; struct snd_rawmidi *midi_uart;
struct snd_opl3 *opl3; struct snd_opl3 *opl3;
int idx, err; int err;
if (dev >= SNDRV_CARDS) if (dev >= SNDRV_CARDS)
return -ENODEV; return -ENODEV;
...@@ -1438,25 +1404,16 @@ static int snd_sonic_probe(struct pci_dev *pci, ...@@ -1438,25 +1404,16 @@ static int snd_sonic_probe(struct pci_dev *pci,
return -ENOENT; return -ENOENT;
} }
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
0, &card); sizeof(*sonic), &card);
if (err < 0) if (err < 0)
return err; return err;
for (idx = 0; idx < 5; idx++) { sonic = card->private_data;
if (pci_resource_start(pci, idx) == 0 ||
!(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
snd_card_free(card);
return -ENODEV;
}
}
err = snd_sonicvibes_create(card, pci, err = snd_sonicvibes_create(card, pci,
reverb[dev] ? 1 : 0, reverb[dev] ? 1 : 0,
mge[dev] ? 1 : 0, mge[dev] ? 1 : 0);
&sonic); if (err < 0)
if (err < 0) {
snd_card_free(card);
return err; return err;
}
strcpy(card->driver, "SonicVibes"); strcpy(card->driver, "SonicVibes");
strcpy(card->shortname, "S3 SonicVibes"); strcpy(card->shortname, "S3 SonicVibes");
...@@ -1467,65 +1424,45 @@ static int snd_sonic_probe(struct pci_dev *pci, ...@@ -1467,65 +1424,45 @@ static int snd_sonic_probe(struct pci_dev *pci,
sonic->irq); sonic->irq);
err = snd_sonicvibes_pcm(sonic, 0); err = snd_sonicvibes_pcm(sonic, 0);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_sonicvibes_mixer(sonic); err = snd_sonicvibes_mixer(sonic);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
sonic->midi_port, sonic->midi_port,
MPU401_INFO_INTEGRATED | MPU401_INFO_INTEGRATED |
MPU401_INFO_IRQ_HOOK, MPU401_INFO_IRQ_HOOK,
-1, &midi_uart); -1, &midi_uart);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
snd_sonicvibes_midi(sonic, midi_uart); snd_sonicvibes_midi(sonic, midi_uart);
err = snd_opl3_create(card, sonic->synth_port, err = snd_opl3_create(card, sonic->synth_port,
sonic->synth_port + 2, sonic->synth_port + 2,
OPL3_HW_OPL3_SV, 1, &opl3); OPL3_HW_OPL3_SV, 1, &opl3);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_sonicvibes_create_gameport(sonic); err = snd_sonicvibes_create_gameport(sonic);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_card_register(card); err = snd_card_register(card);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
dev++; dev++;
return 0; return 0;
} }
static void snd_sonic_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver sonicvibes_driver = { static struct pci_driver sonicvibes_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.id_table = snd_sonic_ids, .id_table = snd_sonic_ids,
.probe = snd_sonic_probe, .probe = snd_sonic_probe,
.remove = snd_sonic_remove,
}; };
module_pci_driver(sonicvibes_driver); module_pci_driver(sonicvibes_driver);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment