Skip to content

Commit b9b4c79

Browse files
committed
Merge tag 'sound-5.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai: "This became an unexpectedly large pull request due to various regression fixes in the previous kernels. The majority of fixes are a series of patches to address the regression at probe errors in devres'ed drivers, while there are yet more fixes for the x86 SG allocations and for USB-audio buffer management. In addition, a few HD-audio quirks and other small fixes are found" * tag 'sound-5.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (52 commits) ALSA: usb-audio: Limit max buffer and period sizes per time ALSA: memalloc: Add fallback SG-buffer allocations for x86 ALSA: nm256: Don't call card private_free at probe error path ALSA: mtpav: Don't call card private_free at probe error path ALSA: rme9652: Fix the missing snd_card_free() call at probe error ALSA: hdspm: Fix the missing snd_card_free() call at probe error ALSA: hdsp: Fix the missing snd_card_free() call at probe error ALSA: oxygen: Fix the missing snd_card_free() call at probe error ALSA: lx6464es: Fix the missing snd_card_free() call at probe error ALSA: cmipci: Fix the missing snd_card_free() call at probe error ALSA: aw2: Fix the missing snd_card_free() call at probe error ALSA: als300: Fix the missing snd_card_free() call at probe error ALSA: lola: Fix the missing snd_card_free() call at probe error ALSA: bt87x: Fix the missing snd_card_free() call at probe error ALSA: sis7019: Fix the missing error handling ALSA: intel_hdmi: Fix the missing snd_card_free() call at probe error ALSA: via82xx: Fix the missing snd_card_free() call at probe error ALSA: sonicvibes: Fix the missing snd_card_free() call at probe error ALSA: rme96: Fix the missing snd_card_free() call at probe error ALSA: rme32: Fix the missing snd_card_free() call at probe error ...
2 parents 722985e + 24d0c9f commit b9b4c79

55 files changed

Lines changed: 506 additions & 124 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

include/sound/core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ int snd_card_disconnect(struct snd_card *card);
284284
void snd_card_disconnect_sync(struct snd_card *card);
285285
int snd_card_free(struct snd_card *card);
286286
int snd_card_free_when_closed(struct snd_card *card);
287+
int snd_card_free_on_error(struct device *dev, int ret);
287288
void snd_card_set_id(struct snd_card *card, const char *id);
288289
int snd_card_register(struct snd_card *card);
289290
int snd_card_info_init(void);

include/sound/memalloc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ struct snd_dma_device {
5151
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
5252
#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
5353
#endif
54+
/* fallback types, don't use those directly */
55+
#ifdef CONFIG_SND_DMA_SGBUF
56+
#define SNDRV_DMA_TYPE_DEV_SG_FALLBACK 10
57+
#define SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK 11
58+
#endif
5459

5560
/*
5661
* info for buffer allocation

sound/core/init.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ static void __snd_card_release(struct device *dev, void *data)
209209
* snd_card_register(), the very first devres action to call snd_card_free()
210210
* is added automatically. In that way, the resource disconnection is assured
211211
* at first, then released in the expected order.
212+
*
213+
* If an error happens at the probe before snd_card_register() is called and
214+
* there have been other devres resources, you'd need to free the card manually
215+
* via snd_card_free() call in the error; otherwise it may lead to UAF due to
216+
* devres call orders. You can use snd_card_free_on_error() helper for
217+
* handling it more easily.
212218
*/
213219
int snd_devm_card_new(struct device *parent, int idx, const char *xid,
214220
struct module *module, size_t extra_size,
@@ -235,6 +241,28 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
235241
}
236242
EXPORT_SYMBOL_GPL(snd_devm_card_new);
237243

244+
/**
245+
* snd_card_free_on_error - a small helper for handling devm probe errors
246+
* @dev: the managed device object
247+
* @ret: the return code from the probe callback
248+
*
249+
* This function handles the explicit snd_card_free() call at the error from
250+
* the probe callback. It's just a small helper for simplifying the error
251+
* handling with the managed devices.
252+
*/
253+
int snd_card_free_on_error(struct device *dev, int ret)
254+
{
255+
struct snd_card *card;
256+
257+
if (!ret)
258+
return 0;
259+
card = devres_find(dev, __snd_card_release, NULL, NULL);
260+
if (card)
261+
snd_card_free(card);
262+
return ret;
263+
}
264+
EXPORT_SYMBOL_GPL(snd_card_free_on_error);
265+
238266
static int snd_card_init(struct snd_card *card, struct device *parent,
239267
int idx, const char *xid, struct module *module,
240268
size_t extra_size)

sound/core/memalloc.c

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,10 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
499499
};
500500
#endif /* CONFIG_X86 */
501501

502+
#ifdef CONFIG_SND_DMA_SGBUF
503+
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
504+
#endif
505+
502506
/*
503507
* Non-contiguous pages allocator
504508
*/
@@ -509,8 +513,18 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
509513

510514
sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
511515
DEFAULT_GFP, 0);
512-
if (!sgt)
516+
if (!sgt) {
517+
#ifdef CONFIG_SND_DMA_SGBUF
518+
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
519+
dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
520+
else
521+
dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
522+
return snd_dma_sg_fallback_alloc(dmab, size);
523+
#else
513524
return NULL;
525+
#endif
526+
}
527+
514528
dmab->dev.need_sync = dma_need_sync(dmab->dev.dev,
515529
sg_dma_address(sgt->sgl));
516530
p = dma_vmap_noncontiguous(dmab->dev.dev, size, sgt);
@@ -633,6 +647,8 @@ static void *snd_dma_sg_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
633647

634648
if (!p)
635649
return NULL;
650+
if (dmab->dev.type != SNDRV_DMA_TYPE_DEV_WC_SG)
651+
return p;
636652
for_each_sgtable_page(sgt, &iter, 0)
637653
set_memory_wc(sg_wc_address(&iter), 1);
638654
return p;
@@ -665,6 +681,95 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
665681
.get_page = snd_dma_noncontig_get_page,
666682
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
667683
};
684+
685+
/* Fallback SG-buffer allocations for x86 */
686+
struct snd_dma_sg_fallback {
687+
size_t count;
688+
struct page **pages;
689+
dma_addr_t *addrs;
690+
};
691+
692+
static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
693+
struct snd_dma_sg_fallback *sgbuf)
694+
{
695+
size_t i;
696+
697+
if (sgbuf->count && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
698+
set_pages_array_wb(sgbuf->pages, sgbuf->count);
699+
for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
700+
dma_free_coherent(dmab->dev.dev, PAGE_SIZE,
701+
page_address(sgbuf->pages[i]),
702+
sgbuf->addrs[i]);
703+
kvfree(sgbuf->pages);
704+
kvfree(sgbuf->addrs);
705+
kfree(sgbuf);
706+
}
707+
708+
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
709+
{
710+
struct snd_dma_sg_fallback *sgbuf;
711+
struct page **pages;
712+
size_t i, count;
713+
void *p;
714+
715+
sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
716+
if (!sgbuf)
717+
return NULL;
718+
count = PAGE_ALIGN(size) >> PAGE_SHIFT;
719+
pages = kvcalloc(count, sizeof(*pages), GFP_KERNEL);
720+
if (!pages)
721+
goto error;
722+
sgbuf->pages = pages;
723+
sgbuf->addrs = kvcalloc(count, sizeof(*sgbuf->addrs), GFP_KERNEL);
724+
if (!sgbuf->addrs)
725+
goto error;
726+
727+
for (i = 0; i < count; sgbuf->count++, i++) {
728+
p = dma_alloc_coherent(dmab->dev.dev, PAGE_SIZE,
729+
&sgbuf->addrs[i], DEFAULT_GFP);
730+
if (!p)
731+
goto error;
732+
sgbuf->pages[i] = virt_to_page(p);
733+
}
734+
735+
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
736+
set_pages_array_wc(pages, count);
737+
p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
738+
if (!p)
739+
goto error;
740+
dmab->private_data = sgbuf;
741+
return p;
742+
743+
error:
744+
__snd_dma_sg_fallback_free(dmab, sgbuf);
745+
return NULL;
746+
}
747+
748+
static void snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab)
749+
{
750+
vunmap(dmab->area);
751+
__snd_dma_sg_fallback_free(dmab, dmab->private_data);
752+
}
753+
754+
static int snd_dma_sg_fallback_mmap(struct snd_dma_buffer *dmab,
755+
struct vm_area_struct *area)
756+
{
757+
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
758+
759+
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
760+
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
761+
return vm_map_pages(area, sgbuf->pages, sgbuf->count);
762+
}
763+
764+
static const struct snd_malloc_ops snd_dma_sg_fallback_ops = {
765+
.alloc = snd_dma_sg_fallback_alloc,
766+
.free = snd_dma_sg_fallback_free,
767+
.mmap = snd_dma_sg_fallback_mmap,
768+
/* reuse vmalloc helpers */
769+
.get_addr = snd_dma_vmalloc_get_addr,
770+
.get_page = snd_dma_vmalloc_get_page,
771+
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
772+
};
668773
#endif /* CONFIG_SND_DMA_SGBUF */
669774

670775
/*
@@ -736,6 +841,10 @@ static const struct snd_malloc_ops *dma_ops[] = {
736841
#ifdef CONFIG_GENERIC_ALLOCATOR
737842
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
738843
#endif /* CONFIG_GENERIC_ALLOCATOR */
844+
#ifdef CONFIG_SND_DMA_SGBUF
845+
[SNDRV_DMA_TYPE_DEV_SG_FALLBACK] = &snd_dma_sg_fallback_ops,
846+
[SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK] = &snd_dma_sg_fallback_ops,
847+
#endif
739848
#endif /* CONFIG_HAS_DMA */
740849
};
741850

sound/core/pcm_misc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
433433
return 0;
434434
width = pcm_formats[(INT)format].phys; /* physical width */
435435
pat = pcm_formats[(INT)format].silence;
436-
if (! width)
436+
if (!width || !pat)
437437
return -EINVAL;
438438
/* signed or 1 byte data */
439439
if (pcm_formats[(INT)format].signd == 1 || width <= 8) {

sound/drivers/mtpav.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,8 +693,6 @@ static int snd_mtpav_probe(struct platform_device *dev)
693693
mtp_card->outmidihwport = 0xffffffff;
694694
timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0);
695695

696-
card->private_free = snd_mtpav_free;
697-
698696
err = snd_mtpav_get_RAWMIDI(mtp_card);
699697
if (err < 0)
700698
return err;
@@ -716,6 +714,8 @@ static int snd_mtpav_probe(struct platform_device *dev)
716714
if (err < 0)
717715
return err;
718716

717+
card->private_free = snd_mtpav_free;
718+
719719
platform_set_drvdata(dev, card);
720720
printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
721721
return 0;

sound/hda/hdac_i915.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,25 @@ static int i915_component_master_match(struct device *dev, int subcomponent,
116116
return 0;
117117
}
118118

119-
/* check whether intel graphics is present */
120-
static bool i915_gfx_present(void)
119+
/* check whether Intel graphics is present and reachable */
120+
static int i915_gfx_present(struct pci_dev *hdac_pci)
121121
{
122-
static const struct pci_device_id ids[] = {
123-
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
124-
.class = PCI_BASE_CLASS_DISPLAY << 16,
125-
.class_mask = 0xff << 16 },
126-
{}
127-
};
128-
return pci_dev_present(ids);
122+
unsigned int class = PCI_BASE_CLASS_DISPLAY << 16;
123+
struct pci_dev *display_dev = NULL;
124+
bool match = false;
125+
126+
do {
127+
display_dev = pci_get_class(class, display_dev);
128+
129+
if (display_dev && display_dev->vendor == PCI_VENDOR_ID_INTEL &&
130+
connectivity_check(display_dev, hdac_pci))
131+
match = true;
132+
133+
pci_dev_put(display_dev);
134+
135+
} while (!match && display_dev);
136+
137+
return match;
129138
}
130139

131140
/**
@@ -145,7 +154,7 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
145154
struct drm_audio_component *acomp;
146155
int err;
147156

148-
if (!i915_gfx_present())
157+
if (!i915_gfx_present(to_pci_dev(bus->dev)))
149158
return -ENODEV;
150159

151160
err = snd_hdac_acomp_init(bus, NULL,

sound/hda/intel-dsp-config.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,22 +390,36 @@ static const struct config_entry config_table[] = {
390390

391391
/* Alder Lake */
392392
#if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
393+
/* Alderlake-S */
393394
{
394395
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
395396
.device = 0x7ad0,
396397
},
398+
/* RaptorLake-S */
397399
{
398400
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
399-
.device = 0x51c8,
401+
.device = 0x7a50,
400402
},
403+
/* Alderlake-P */
401404
{
402405
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
403-
.device = 0x51cc,
406+
.device = 0x51c8,
404407
},
405408
{
406409
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
407410
.device = 0x51cd,
408411
},
412+
/* Alderlake-PS */
413+
{
414+
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
415+
.device = 0x51c9,
416+
},
417+
/* Alderlake-M */
418+
{
419+
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
420+
.device = 0x51cc,
421+
},
422+
/* Alderlake-N */
409423
{
410424
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
411425
.device = 0x54c8,

sound/isa/galaxy/galaxy.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ static void snd_galaxy_free(struct snd_card *card)
478478
galaxy_set_config(galaxy, galaxy->config);
479479
}
480480

481-
static int snd_galaxy_probe(struct device *dev, unsigned int n)
481+
static int __snd_galaxy_probe(struct device *dev, unsigned int n)
482482
{
483483
struct snd_galaxy *galaxy;
484484
struct snd_wss *chip;
@@ -598,6 +598,11 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
598598
return 0;
599599
}
600600

601+
static int snd_galaxy_probe(struct device *dev, unsigned int n)
602+
{
603+
return snd_card_free_on_error(dev, __snd_galaxy_probe(dev, n));
604+
}
605+
601606
static struct isa_driver snd_galaxy_driver = {
602607
.match = snd_galaxy_match,
603608
.probe = snd_galaxy_probe,

sound/isa/sc6000.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ static void snd_sc6000_free(struct snd_card *card)
537537
sc6000_setup_board(vport, 0);
538538
}
539539

540-
static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
540+
static int __snd_sc6000_probe(struct device *devptr, unsigned int dev)
541541
{
542542
static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
543543
static const int possible_dmas[] = { 1, 3, 0, -1 };
@@ -662,6 +662,11 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
662662
return 0;
663663
}
664664

665+
static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
666+
{
667+
return snd_card_free_on_error(devptr, __snd_sc6000_probe(devptr, dev));
668+
}
669+
665670
static struct isa_driver snd_sc6000_driver = {
666671
.match = snd_sc6000_match,
667672
.probe = snd_sc6000_probe,

0 commit comments

Comments
 (0)