ALSA: emu10k1: Allocate resources with device-managed APIs

This patch converts the resource management in PCI emu10k1 driver with
devres as a clean up.  Each manual resource management is converted
with the corresponding devres helper, the page allocations are done
with the 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-34-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2021-07-15 09:58:55 +02:00
parent 9c211bf392
commit 79e8b218b3
4 changed files with 52 additions and 131 deletions

View File

@ -1701,7 +1701,7 @@ struct snd_emu10k1 {
struct snd_dma_buffer silent_page; /* silent page */ struct snd_dma_buffer silent_page; /* silent page */
struct snd_dma_buffer ptb_pages; /* page table pages */ struct snd_dma_buffer ptb_pages; /* page table pages */
struct snd_dma_device p16v_dma_dev; struct snd_dma_device p16v_dma_dev;
struct snd_dma_buffer p16v_buffer; struct snd_dma_buffer *p16v_buffer;
struct snd_util_memhdr *memhdr; /* page allocation list */ struct snd_util_memhdr *memhdr; /* page allocation list */
@ -1796,14 +1796,12 @@ int snd_emu10k1_create(struct snd_card *card,
unsigned short extout_mask, unsigned short extout_mask,
long max_cache_bytes, long max_cache_bytes,
int enable_ir, int enable_ir,
uint subsystem, uint subsystem);
struct snd_emu10k1 ** remu);
int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device); int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device); int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device); int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device);
int snd_p16v_pcm(struct snd_emu10k1 *emu, int device); int snd_p16v_pcm(struct snd_emu10k1 *emu, int device);
int snd_p16v_free(struct snd_emu10k1 * emu);
int snd_p16v_mixer(struct snd_emu10k1 * emu); int snd_p16v_mixer(struct snd_emu10k1 * emu);
int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device); int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device); int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device);

View File

@ -99,67 +99,67 @@ static int snd_card_emu10k1_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(*emu), &card);
if (err < 0) if (err < 0)
return err; return err;
emu = card->private_data;
if (max_buffer_size[dev] < 32) if (max_buffer_size[dev] < 32)
max_buffer_size[dev] = 32; max_buffer_size[dev] = 32;
else if (max_buffer_size[dev] > 1024) else if (max_buffer_size[dev] > 1024)
max_buffer_size[dev] = 1024; max_buffer_size[dev] = 1024;
err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
(long)max_buffer_size[dev] * 1024 * 1024, (long)max_buffer_size[dev] * 1024 * 1024,
enable_ir[dev], subsystem[dev], enable_ir[dev], subsystem[dev]);
&emu);
if (err < 0) if (err < 0)
goto error; return err;
card->private_data = emu;
emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
err = snd_emu10k1_pcm(emu, 0); err = snd_emu10k1_pcm(emu, 0);
if (err < 0) if (err < 0)
goto error; return err;
err = snd_emu10k1_pcm_mic(emu, 1); err = snd_emu10k1_pcm_mic(emu, 1);
if (err < 0) if (err < 0)
goto error; return err;
err = snd_emu10k1_pcm_efx(emu, 2); err = snd_emu10k1_pcm_efx(emu, 2);
if (err < 0) if (err < 0)
goto error; return err;
/* This stores the periods table. */ /* This stores the periods table. */
if (emu->card_capabilities->ca0151_chip) { /* P16V */ if (emu->card_capabilities->ca0151_chip) { /* P16V */
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, emu->p16v_buffer =
1024, &emu->p16v_buffer); snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
if (err < 0) if (!emu->p16v_buffer)
goto error; return -ENOMEM;
} }
err = snd_emu10k1_mixer(emu, 0, 3); err = snd_emu10k1_mixer(emu, 0, 3);
if (err < 0) if (err < 0)
goto error; return err;
err = snd_emu10k1_timer(emu, 0); err = snd_emu10k1_timer(emu, 0);
if (err < 0) if (err < 0)
goto error; return err;
err = snd_emu10k1_pcm_multi(emu, 3); err = snd_emu10k1_pcm_multi(emu, 3);
if (err < 0) if (err < 0)
goto error; return err;
if (emu->card_capabilities->ca0151_chip) { /* P16V */ if (emu->card_capabilities->ca0151_chip) { /* P16V */
err = snd_p16v_pcm(emu, 4); err = snd_p16v_pcm(emu, 4);
if (err < 0) if (err < 0)
goto error; return err;
} }
if (emu->audigy) { if (emu->audigy) {
err = snd_emu10k1_audigy_midi(emu); err = snd_emu10k1_audigy_midi(emu);
if (err < 0) if (err < 0)
goto error; return err;
} else { } else {
err = snd_emu10k1_midi(emu); err = snd_emu10k1_midi(emu);
if (err < 0) if (err < 0)
goto error; return err;
} }
err = snd_emu10k1_fx8010_new(emu, 0); err = snd_emu10k1_fx8010_new(emu, 0);
if (err < 0) if (err < 0)
goto error; return err;
#ifdef ENABLE_SYNTH #ifdef ENABLE_SYNTH
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 || sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 ||
@ -187,7 +187,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
err = snd_card_register(card); err = snd_card_register(card);
if (err < 0) if (err < 0)
goto error; return err;
if (emu->card_capabilities->emu_model) if (emu->card_capabilities->emu_model)
schedule_delayed_work(&emu->emu1010.firmware_work, 0); schedule_delayed_work(&emu->emu1010.firmware_work, 0);
@ -195,18 +195,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
dev++; dev++;
return 0; return 0;
error:
snd_card_free(card);
return err;
} }
static void snd_card_emu10k1_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int snd_emu10k1_suspend(struct device *dev) static int snd_emu10k1_suspend(struct device *dev)
{ {
@ -263,7 +253,6 @@ static struct pci_driver emu10k1_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.id_table = snd_emu10k1_ids, .id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe, .probe = snd_card_emu10k1_probe,
.remove = snd_card_emu10k1_remove,
.driver = { .driver = {
.pm = SND_EMU10K1_PM_OPS, .pm = SND_EMU10K1_PM_OPS,
}, },

View File

@ -1242,8 +1242,10 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu);
static void free_pm_buffer(struct snd_emu10k1 *emu); static void free_pm_buffer(struct snd_emu10k1 *emu);
#endif #endif
static int snd_emu10k1_free(struct snd_emu10k1 *emu) static void snd_emu10k1_free(struct snd_card *card)
{ {
struct snd_emu10k1 *emu = card->private_data;
if (emu->port) { /* avoid access to already used hardware */ if (emu->port) { /* avoid access to already used hardware */
snd_emu10k1_fx8010_tram_setup(emu, 0); snd_emu10k1_fx8010_tram_setup(emu, 0);
snd_emu10k1_done(emu); snd_emu10k1_done(emu);
@ -1256,8 +1258,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
cancel_delayed_work_sync(&emu->emu1010.firmware_work); cancel_delayed_work_sync(&emu->emu1010.firmware_work);
release_firmware(emu->firmware); release_firmware(emu->firmware);
release_firmware(emu->dock_fw); release_firmware(emu->dock_fw);
if (emu->irq >= 0)
free_irq(emu->irq, emu);
snd_util_memhdr_free(emu->memhdr); snd_util_memhdr_free(emu->memhdr);
if (emu->silent_page.area) if (emu->silent_page.area)
snd_dma_free_pages(&emu->silent_page); snd_dma_free_pages(&emu->silent_page);
@ -1268,19 +1268,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
free_pm_buffer(emu); free_pm_buffer(emu);
#endif #endif
if (emu->port)
pci_release_regions(emu->pci);
if (emu->card_capabilities->ca0151_chip) /* P16V */
snd_p16v_free(emu);
pci_disable_device(emu->pci);
kfree(emu);
return 0;
}
static int snd_emu10k1_dev_free(struct snd_device *device)
{
struct snd_emu10k1 *emu = device->device_data;
return snd_emu10k1_free(emu);
} }
static const struct snd_emu_chip_details emu_chip_details[] = { static const struct snd_emu_chip_details emu_chip_details[] = {
@ -1782,32 +1769,22 @@ int snd_emu10k1_create(struct snd_card *card,
unsigned short extout_mask, unsigned short extout_mask,
long max_cache_bytes, long max_cache_bytes,
int enable_ir, int enable_ir,
uint subsystem, uint subsystem)
struct snd_emu10k1 **remu)
{ {
struct snd_emu10k1 *emu; struct snd_emu10k1 *emu = card->private_data;
int idx, err; int idx, err;
int is_audigy; int is_audigy;
size_t page_table_size; size_t page_table_size;
__le32 *pgtbl; __le32 *pgtbl;
unsigned int silent_page; unsigned int silent_page;
const struct snd_emu_chip_details *c; const struct snd_emu_chip_details *c;
static const struct snd_device_ops ops = {
.dev_free = snd_emu10k1_dev_free,
};
*remu = 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;
emu = kzalloc(sizeof(*emu), GFP_KERNEL); card->private_free = snd_emu10k1_free;
if (emu == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
emu->card = card; emu->card = card;
spin_lock_init(&emu->reg_lock); spin_lock_init(&emu->reg_lock);
spin_lock_init(&emu->emu_lock); spin_lock_init(&emu->emu_lock);
@ -1850,8 +1827,6 @@ int snd_emu10k1_create(struct snd_card *card,
} }
if (c->vendor == 0) { if (c->vendor == 0) {
dev_err(card->dev, "emu10k1: Card not recognised\n"); dev_err(card->dev, "emu10k1: Card not recognised\n");
kfree(emu);
pci_disable_device(pci);
return -ENOENT; return -ENOENT;
} }
emu->card_capabilities = c; emu->card_capabilities = c;
@ -1883,8 +1858,6 @@ int snd_emu10k1_create(struct snd_card *card,
dev_err(card->dev, dev_err(card->dev,
"architecture does not support PCI busmaster DMA with mask 0x%lx\n", "architecture does not support PCI busmaster DMA with mask 0x%lx\n",
emu->dma_mask); emu->dma_mask);
kfree(emu);
pci_disable_device(pci);
return -ENXIO; return -ENXIO;
} }
if (is_audigy) if (is_audigy)
@ -1893,11 +1866,8 @@ int snd_emu10k1_create(struct snd_card *card,
emu->gpr_base = FXGPREGBASE; emu->gpr_base = FXGPREGBASE;
err = pci_request_regions(pci, "EMU10K1"); err = pci_request_regions(pci, "EMU10K1");
if (err < 0) { if (err < 0)
kfree(emu);
pci_disable_device(pci);
return err; return err;
}
emu->port = pci_resource_start(pci, 0); emu->port = pci_resource_start(pci, 0);
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
@ -1905,10 +1875,8 @@ int snd_emu10k1_create(struct snd_card *card,
page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 : page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
MAXPAGES0); MAXPAGES0);
if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size, if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
&emu->ptb_pages) < 0) { &emu->ptb_pages) < 0)
err = -ENOMEM; return -ENOMEM;
goto error;
}
dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n", dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n",
(unsigned long)emu->ptb_pages.addr, (unsigned long)emu->ptb_pages.addr,
(unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes)); (unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
@ -1917,26 +1885,20 @@ int snd_emu10k1_create(struct snd_card *card,
emu->max_cache_pages)); emu->max_cache_pages));
emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long), emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long),
emu->max_cache_pages)); emu->max_cache_pages));
if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { if (!emu->page_ptr_table || !emu->page_addr_table)
err = -ENOMEM; return -ENOMEM;
goto error;
}
if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE, if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
&emu->silent_page) < 0) { &emu->silent_page) < 0)
err = -ENOMEM; return -ENOMEM;
goto error;
}
dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n", dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n",
(unsigned long)emu->silent_page.addr, (unsigned long)emu->silent_page.addr,
(unsigned long)(emu->silent_page.addr + (unsigned long)(emu->silent_page.addr +
emu->silent_page.bytes)); emu->silent_page.bytes));
emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE); emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
if (emu->memhdr == NULL) { if (!emu->memhdr)
err = -ENOMEM; return -ENOMEM;
goto error;
}
emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) - emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
sizeof(struct snd_util_memblk); sizeof(struct snd_util_memblk);
@ -1954,18 +1916,16 @@ int snd_emu10k1_create(struct snd_card *card,
if (emu->card_capabilities->ca_cardbus_chip) { if (emu->card_capabilities->ca_cardbus_chip) {
err = snd_emu10k1_cardbus_init(emu); err = snd_emu10k1_cardbus_init(emu);
if (err < 0) if (err < 0)
goto error; return err;
} }
if (emu->card_capabilities->ecard) { if (emu->card_capabilities->ecard) {
err = snd_emu10k1_ecard_init(emu); err = snd_emu10k1_ecard_init(emu);
if (err < 0) if (err < 0)
goto error; return err;
} else if (emu->card_capabilities->emu_model) { } else if (emu->card_capabilities->emu_model) {
err = snd_emu10k1_emu1010_init(emu); err = snd_emu10k1_emu1010_init(emu);
if (err < 0) { if (err < 0)
snd_emu10k1_free(emu);
return err; return err;
}
} else { } else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this, it shouldn't do any harm */ does not support this, it shouldn't do any harm */
@ -1979,11 +1939,9 @@ int snd_emu10k1_create(struct snd_card *card,
emu->fx8010.etram_pages.bytes = 0; emu->fx8010.etram_pages.bytes = 0;
/* irq handler must be registered after I/O ports are activated */ /* irq handler must be registered after I/O ports are activated */
if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED, if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1_interrupt,
KBUILD_MODNAME, emu)) { IRQF_SHARED, KBUILD_MODNAME, emu))
err = -EBUSY; return -EBUSY;
goto error;
}
emu->irq = pci->irq; emu->irq = pci->irq;
card->sync_irq = emu->irq; card->sync_irq = emu->irq;
@ -2022,33 +1980,23 @@ int snd_emu10k1_create(struct snd_card *card,
err = snd_emu10k1_init(emu, enable_ir, 0); err = snd_emu10k1_init(emu, enable_ir, 0);
if (err < 0) if (err < 0)
goto error; return err;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
err = alloc_pm_buffer(emu); err = alloc_pm_buffer(emu);
if (err < 0) if (err < 0)
goto error; return err;
#endif #endif
/* Initialize the effect engine */ /* Initialize the effect engine */
err = snd_emu10k1_init_efx(emu); err = snd_emu10k1_init_efx(emu);
if (err < 0) if (err < 0)
goto error; return err;
snd_emu10k1_audio_enable(emu); snd_emu10k1_audio_enable(emu);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
if (err < 0)
goto error;
#ifdef CONFIG_SND_PROC_FS #ifdef CONFIG_SND_PROC_FS
snd_emu10k1_proc_init(emu); snd_emu10k1_proc_init(emu);
#endif #endif
*remu = emu;
return 0; return 0;
error:
snd_emu10k1_free(emu);
return err;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP

View File

@ -290,7 +290,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
int channel = substream->pcm->device - emu->p16v_device_offset; int channel = substream->pcm->device - emu->p16v_device_offset;
u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
int i; int i;
u32 tmp; u32 tmp;
@ -308,8 +308,8 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
runtime->dma_addr, runtime->dma_area, table_base); runtime->dma_addr, runtime->dma_area, table_base);
dev_dbg(emu->card->dev, dev_dbg(emu->card->dev,
"dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer->addr, emu->p16v_buffer->area,
emu->p16v_buffer.bytes); emu->p16v_buffer->bytes);
#endif /* debug */ #endif /* debug */
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
switch (runtime->rate) { switch (runtime->rate) {
@ -333,7 +333,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
table_base[(i*2)+1]=period_size_bytes<<16; table_base[(i*2)+1]=period_size_bytes<<16;
} }
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel)); snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel));
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@ -567,20 +567,6 @@ static const struct snd_pcm_ops snd_p16v_capture_ops = {
.pointer = snd_p16v_pcm_pointer_capture, .pointer = snd_p16v_pcm_pointer_capture,
}; };
int snd_p16v_free(struct snd_emu10k1 *chip)
{
// release the data
if (chip->p16v_buffer.area) {
snd_dma_free_pages(&chip->p16v_buffer);
/*
dev_dbg(chip->card->dev, "period lables free: %p\n",
&chip->p16v_buffer);
*/
}
return 0;
}
int snd_p16v_pcm(struct snd_emu10k1 *emu, int device) int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
{ {
struct snd_pcm *pcm; struct snd_pcm *pcm;