Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: trident: Allocate resources with device-managed APIs

This patch converts the resource management in PCI trident 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-49-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+44 -100
+10 -29
sound/pci/trident/trident.c
··· 62 62 return -ENOENT; 63 63 } 64 64 65 - err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 66 - 0, &card); 65 + err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 66 + sizeof(*trident), &card); 67 67 if (err < 0) 68 68 return err; 69 + trident = card->private_data; 69 70 70 71 err = snd_trident_create(card, pci, 71 72 pcm_channels[dev], 72 73 ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2, 73 - wavetable_size[dev], 74 - &trident); 75 - if (err < 0) { 76 - snd_card_free(card); 74 + wavetable_size[dev]); 75 + if (err < 0) 77 76 return err; 78 - } 79 - card->private_data = trident; 80 77 81 78 switch (trident->device) { 82 79 case TRIDENT_DEVICE_ID_DX: ··· 99 102 card->shortname, trident->port, trident->irq); 100 103 101 104 err = snd_trident_pcm(trident, pcm_dev++); 102 - if (err < 0) { 103 - snd_card_free(card); 105 + if (err < 0) 104 106 return err; 105 - } 106 107 switch (trident->device) { 107 108 case TRIDENT_DEVICE_ID_DX: 108 109 case TRIDENT_DEVICE_ID_NX: 109 110 err = snd_trident_foldback_pcm(trident, pcm_dev++); 110 - if (err < 0) { 111 - snd_card_free(card); 111 + if (err < 0) 112 112 return err; 113 - } 114 113 break; 115 114 } 116 115 if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { 117 116 err = snd_trident_spdif_pcm(trident, pcm_dev++); 118 - if (err < 0) { 119 - snd_card_free(card); 117 + if (err < 0) 120 118 return err; 121 - } 122 119 } 123 120 if (trident->device != TRIDENT_DEVICE_ID_SI7018) { 124 121 err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, ··· 120 129 MPU401_INFO_INTEGRATED | 121 130 MPU401_INFO_IRQ_HOOK, 122 131 -1, &trident->rmidi); 123 - if (err < 0) { 124 - snd_card_free(card); 132 + if (err < 0) 125 133 return err; 126 - } 127 134 } 128 135 129 136 snd_trident_create_gameport(trident); 130 137 131 138 err = snd_card_register(card); 132 - if (err < 0) { 133 - snd_card_free(card); 139 + if (err < 0) 134 140 return err; 135 - } 136 141 pci_set_drvdata(pci, card); 137 142 dev++; 138 143 return 0; 139 - } 140 - 141 - static void snd_trident_remove(struct pci_dev *pci) 142 - { 143 - snd_card_free(pci_get_drvdata(pci)); 144 144 } 145 145 146 146 static struct pci_driver trident_driver = { 147 147 .name = KBUILD_MODNAME, 148 148 .id_table = snd_trident_ids, 149 149 .probe = snd_trident_probe, 150 - .remove = snd_trident_remove, 151 150 #ifdef CONFIG_PM_SLEEP 152 151 .driver = { 153 152 .pm = &snd_trident_pm,
+3 -4
sound/pci/trident/trident.h
··· 251 251 struct snd_trident_tlb { 252 252 __le32 *entries; /* 16k-aligned TLB table */ 253 253 dma_addr_t entries_dmaaddr; /* 16k-aligned PCI address to TLB table */ 254 - struct snd_dma_buffer buffer; 254 + struct snd_dma_buffer *buffer; 255 255 struct snd_util_memhdr * memhdr; /* page allocation list */ 256 - struct snd_dma_buffer silent_page; 256 + struct snd_dma_buffer *silent_page; 257 257 }; 258 258 259 259 struct snd_trident_voice { ··· 400 400 struct pci_dev *pci, 401 401 int pcm_streams, 402 402 int pcm_spdif_device, 403 - int max_wavetable_size, 404 - struct snd_trident ** rtrident); 403 + int max_wavetable_size); 405 404 int snd_trident_create_gameport(struct snd_trident *trident); 406 405 407 406 int snd_trident_pcm(struct snd_trident *trident, int device);
+27 -63
sound/pci/trident/trident_main.c
··· 42 42 43 43 static void snd_trident_clear_voices(struct snd_trident * trident, 44 44 unsigned short v_min, unsigned short v_max); 45 - static int snd_trident_free(struct snd_trident *trident); 45 + static void snd_trident_free(struct snd_card *card); 46 46 47 47 /* 48 48 * common I/O routines ··· 3299 3299 snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read); 3300 3300 } 3301 3301 3302 - static int snd_trident_dev_free(struct snd_device *device) 3303 - { 3304 - struct snd_trident *trident = device->device_data; 3305 - return snd_trident_free(trident); 3306 - } 3307 - 3308 3302 /*--------------------------------------------------------------------------- 3309 3303 snd_trident_tlb_alloc 3310 3304 ··· 3318 3324 /* TLB array must be aligned to 16kB !!! so we allocate 3319 3325 32kB region and correct offset when necessary */ 3320 3326 3321 - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev, 3322 - 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) { 3327 + trident->tlb.buffer = 3328 + snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV, 3329 + 2 * SNDRV_TRIDENT_MAX_PAGES * 4); 3330 + if (!trident->tlb.buffer) { 3323 3331 dev_err(trident->card->dev, "unable to allocate TLB buffer\n"); 3324 3332 return -ENOMEM; 3325 3333 } 3326 - trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); 3327 - trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4); 3334 + trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer->area, SNDRV_TRIDENT_MAX_PAGES * 4); 3335 + trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer->addr, SNDRV_TRIDENT_MAX_PAGES * 4); 3328 3336 3329 3337 /* allocate and setup silent page and initialise TLB entries */ 3330 - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev, 3331 - SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) { 3338 + trident->tlb.silent_page = 3339 + snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV, 3340 + SNDRV_TRIDENT_PAGE_SIZE); 3341 + if (!trident->tlb.silent_page) { 3332 3342 dev_err(trident->card->dev, "unable to allocate silent page\n"); 3333 3343 return -ENOMEM; 3334 3344 } 3335 - memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE); 3345 + memset(trident->tlb.silent_page->area, 0, SNDRV_TRIDENT_PAGE_SIZE); 3336 3346 for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) 3337 - trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); 3347 + trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page->addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); 3338 3348 3339 3349 /* use emu memory block manager code to manage tlb page allocation */ 3340 3350 trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES); ··· 3495 3497 struct pci_dev *pci, 3496 3498 int pcm_streams, 3497 3499 int pcm_spdif_device, 3498 - int max_wavetable_size, 3499 - struct snd_trident ** rtrident) 3500 + int max_wavetable_size) 3500 3501 { 3501 - struct snd_trident *trident; 3502 + struct snd_trident *trident = card->private_data; 3502 3503 int i, err; 3503 3504 struct snd_trident_voice *voice; 3504 3505 struct snd_trident_pcm_mixer *tmix; 3505 - static const struct snd_device_ops ops = { 3506 - .dev_free = snd_trident_dev_free, 3507 - }; 3508 - 3509 - *rtrident = NULL; 3510 3506 3511 3507 /* enable PCI device */ 3512 - err = pci_enable_device(pci); 3508 + err = pcim_enable_device(pci); 3513 3509 if (err < 0) 3514 3510 return err; 3515 3511 /* check, if we can restrict PCI DMA transfers to 30 bits */ 3516 3512 if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) { 3517 3513 dev_err(card->dev, 3518 3514 "architecture does not support 30bit PCI busmaster DMA\n"); 3519 - pci_disable_device(pci); 3520 3515 return -ENXIO; 3521 3516 } 3522 3517 3523 - trident = kzalloc(sizeof(*trident), GFP_KERNEL); 3524 - if (trident == NULL) { 3525 - pci_disable_device(pci); 3526 - return -ENOMEM; 3527 - } 3528 3518 trident->device = (pci->vendor << 16) | pci->device; 3529 3519 trident->card = card; 3530 3520 trident->pci = pci; ··· 3528 3542 max_wavetable_size = 0; 3529 3543 trident->synth.max_size = max_wavetable_size * 1024; 3530 3544 trident->irq = -1; 3545 + card->private_free = snd_trident_free; 3531 3546 3532 3547 trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE); 3533 3548 pci_set_master(pci); 3534 3549 3535 3550 err = pci_request_regions(pci, "Trident Audio"); 3536 - if (err < 0) { 3537 - kfree(trident); 3538 - pci_disable_device(pci); 3551 + if (err < 0) 3539 3552 return err; 3540 - } 3541 3553 trident->port = pci_resource_start(pci, 0); 3542 3554 3543 - if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED, 3544 - KBUILD_MODNAME, trident)) { 3555 + if (devm_request_irq(&pci->dev, pci->irq, snd_trident_interrupt, 3556 + IRQF_SHARED, KBUILD_MODNAME, trident)) { 3545 3557 dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); 3546 - snd_trident_free(trident); 3547 3558 return -EBUSY; 3548 3559 } 3549 3560 trident->irq = pci->irq; ··· 3548 3565 3549 3566 /* allocate 16k-aligned TLB for NX cards */ 3550 3567 trident->tlb.entries = NULL; 3551 - trident->tlb.buffer.area = NULL; 3552 3568 if (trident->device == TRIDENT_DEVICE_ID_NX) { 3553 3569 err = snd_trident_tlb_alloc(trident); 3554 - if (err < 0) { 3555 - snd_trident_free(trident); 3570 + if (err < 0) 3556 3571 return err; 3557 - } 3558 3572 } 3559 3573 3560 3574 trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; ··· 3571 3591 snd_BUG(); 3572 3592 break; 3573 3593 } 3574 - if (err < 0) { 3575 - snd_trident_free(trident); 3594 + if (err < 0) 3576 3595 return err; 3577 - } 3578 - 3579 - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops); 3580 - if (err < 0) { 3581 - snd_trident_free(trident); 3582 - return err; 3583 - } 3584 3596 3585 3597 err = snd_trident_mixer(trident, pcm_spdif_device); 3586 3598 if (err < 0) ··· 3596 3624 snd_trident_enable_eso(trident); 3597 3625 3598 3626 snd_trident_proc_init(trident); 3599 - *rtrident = trident; 3600 3627 return 0; 3601 3628 } 3602 3629 ··· 3605 3634 Description: This routine will free the device specific class for 3606 3635 the 4DWave card. 3607 3636 3608 - Parameters: trident - device specific private data for 4DWave card 3637 + Parameters: card - card to release 3609 3638 3610 3639 Returns: None. 3611 3640 3612 3641 ---------------------------------------------------------------------------*/ 3613 3642 3614 - static int snd_trident_free(struct snd_trident *trident) 3643 + static void snd_trident_free(struct snd_card *card) 3615 3644 { 3645 + struct snd_trident *trident = card->private_data; 3646 + 3616 3647 snd_trident_free_gameport(trident); 3617 3648 snd_trident_disable_eso(trident); 3618 3649 // Disable S/PDIF out ··· 3623 3650 else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { 3624 3651 outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); 3625 3652 } 3626 - if (trident->irq >= 0) 3627 - free_irq(trident->irq, trident); 3628 - if (trident->tlb.buffer.area) { 3653 + if (trident->tlb.buffer) { 3629 3654 outl(0, TRID_REG(trident, NX_TLBC)); 3630 3655 snd_util_memhdr_free(trident->tlb.memhdr); 3631 - if (trident->tlb.silent_page.area) 3632 - snd_dma_free_pages(&trident->tlb.silent_page); 3633 - snd_dma_free_pages(&trident->tlb.buffer); 3634 3656 } 3635 - pci_release_regions(trident->pci); 3636 - pci_disable_device(trident->pci); 3637 - kfree(trident); 3638 - return 0; 3639 3657 } 3640 3658 3641 3659 /*---------------------------------------------------------------------------
+4 -4
sound/pci/trident/trident_memory.c
··· 31 31 /* fill TLB entrie(s) corresponding to page with ptr */ 32 32 #define set_tlb_bus(trident,page,addr) __set_tlb_bus(trident,page,addr) 33 33 /* fill TLB entrie(s) corresponding to page with silence pointer */ 34 - #define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page.addr) 34 + #define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page->addr) 35 35 /* get aligned page from offset address */ 36 36 #define get_aligned_page(offset) ((offset) >> 12) 37 37 /* get offset address from aligned page */ ··· 58 58 static inline void set_silent_tlb(struct snd_trident *trident, int page) 59 59 { 60 60 page <<= 1; 61 - __set_tlb_bus(trident, page, trident->tlb.silent_page.addr); 62 - __set_tlb_bus(trident, page+1, trident->tlb.silent_page.addr); 61 + __set_tlb_bus(trident, page, trident->tlb.silent_page->addr); 62 + __set_tlb_bus(trident, page+1, trident->tlb.silent_page->addr); 63 63 } 64 64 65 65 #else ··· 92 92 int i; 93 93 page *= UNIT_PAGES; 94 94 for (i = 0; i < UNIT_PAGES; i++, page++) 95 - __set_tlb_bus(trident, page, trident->tlb.silent_page.addr); 95 + __set_tlb_bus(trident, page, trident->tlb.silent_page->addr); 96 96 } 97 97 98 98 #endif /* PAGE_SIZE */