Skip to content

Commit

Permalink
Merge tag 'sound-5.18-rc3' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/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
  ...
  • Loading branch information
torvalds committed Apr 14, 2022
2 parents 722985e + 24d0c9f commit b9b4c79
Show file tree
Hide file tree
Showing 55 changed files with 506 additions and 124 deletions.
1 change: 1 addition & 0 deletions include/sound/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ int snd_card_disconnect(struct snd_card *card);
void snd_card_disconnect_sync(struct snd_card *card);
int snd_card_free(struct snd_card *card);
int snd_card_free_when_closed(struct snd_card *card);
int snd_card_free_on_error(struct device *dev, int ret);
void snd_card_set_id(struct snd_card *card, const char *id);
int snd_card_register(struct snd_card *card);
int snd_card_info_init(void);
Expand Down
5 changes: 5 additions & 0 deletions include/sound/memalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ struct snd_dma_device {
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
#endif
/* fallback types, don't use those directly */
#ifdef CONFIG_SND_DMA_SGBUF
#define SNDRV_DMA_TYPE_DEV_SG_FALLBACK 10
#define SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK 11
#endif

/*
* info for buffer allocation
Expand Down
28 changes: 28 additions & 0 deletions sound/core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ static void __snd_card_release(struct device *dev, void *data)
* snd_card_register(), the very first devres action to call snd_card_free()
* is added automatically. In that way, the resource disconnection is assured
* at first, then released in the expected order.
*
* If an error happens at the probe before snd_card_register() is called and
* there have been other devres resources, you'd need to free the card manually
* via snd_card_free() call in the error; otherwise it may lead to UAF due to
* devres call orders. You can use snd_card_free_on_error() helper for
* handling it more easily.
*/
int snd_devm_card_new(struct device *parent, int idx, const char *xid,
struct module *module, size_t extra_size,
Expand All @@ -235,6 +241,28 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
}
EXPORT_SYMBOL_GPL(snd_devm_card_new);

/**
* snd_card_free_on_error - a small helper for handling devm probe errors
* @dev: the managed device object
* @ret: the return code from the probe callback
*
* This function handles the explicit snd_card_free() call at the error from
* the probe callback. It's just a small helper for simplifying the error
* handling with the managed devices.
*/
int snd_card_free_on_error(struct device *dev, int ret)
{
struct snd_card *card;

if (!ret)
return 0;
card = devres_find(dev, __snd_card_release, NULL, NULL);
if (card)
snd_card_free(card);
return ret;
}
EXPORT_SYMBOL_GPL(snd_card_free_on_error);

static int snd_card_init(struct snd_card *card, struct device *parent,
int idx, const char *xid, struct module *module,
size_t extra_size)
Expand Down
111 changes: 110 additions & 1 deletion sound/core/memalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
};
#endif /* CONFIG_X86 */

#ifdef CONFIG_SND_DMA_SGBUF
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
#endif

/*
* Non-contiguous pages allocator
*/
Expand All @@ -509,8 +513,18 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)

sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
DEFAULT_GFP, 0);
if (!sgt)
if (!sgt) {
#ifdef CONFIG_SND_DMA_SGBUF
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
else
dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
return snd_dma_sg_fallback_alloc(dmab, size);
#else
return NULL;
#endif
}

dmab->dev.need_sync = dma_need_sync(dmab->dev.dev,
sg_dma_address(sgt->sgl));
p = dma_vmap_noncontiguous(dmab->dev.dev, size, sgt);
Expand Down Expand Up @@ -633,6 +647,8 @@ static void *snd_dma_sg_wc_alloc(struct snd_dma_buffer *dmab, size_t size)

if (!p)
return NULL;
if (dmab->dev.type != SNDRV_DMA_TYPE_DEV_WC_SG)
return p;
for_each_sgtable_page(sgt, &iter, 0)
set_memory_wc(sg_wc_address(&iter), 1);
return p;
Expand Down Expand Up @@ -665,6 +681,95 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
.get_page = snd_dma_noncontig_get_page,
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
};

/* Fallback SG-buffer allocations for x86 */
struct snd_dma_sg_fallback {
size_t count;
struct page **pages;
dma_addr_t *addrs;
};

static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
struct snd_dma_sg_fallback *sgbuf)
{
size_t i;

if (sgbuf->count && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
set_pages_array_wb(sgbuf->pages, sgbuf->count);
for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
dma_free_coherent(dmab->dev.dev, PAGE_SIZE,
page_address(sgbuf->pages[i]),
sgbuf->addrs[i]);
kvfree(sgbuf->pages);
kvfree(sgbuf->addrs);
kfree(sgbuf);
}

static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
{
struct snd_dma_sg_fallback *sgbuf;
struct page **pages;
size_t i, count;
void *p;

sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
if (!sgbuf)
return NULL;
count = PAGE_ALIGN(size) >> PAGE_SHIFT;
pages = kvcalloc(count, sizeof(*pages), GFP_KERNEL);
if (!pages)
goto error;
sgbuf->pages = pages;
sgbuf->addrs = kvcalloc(count, sizeof(*sgbuf->addrs), GFP_KERNEL);
if (!sgbuf->addrs)
goto error;

for (i = 0; i < count; sgbuf->count++, i++) {
p = dma_alloc_coherent(dmab->dev.dev, PAGE_SIZE,
&sgbuf->addrs[i], DEFAULT_GFP);
if (!p)
goto error;
sgbuf->pages[i] = virt_to_page(p);
}

if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
set_pages_array_wc(pages, count);
p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
if (!p)
goto error;
dmab->private_data = sgbuf;
return p;

error:
__snd_dma_sg_fallback_free(dmab, sgbuf);
return NULL;
}

static void snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab)
{
vunmap(dmab->area);
__snd_dma_sg_fallback_free(dmab, dmab->private_data);
}

static int snd_dma_sg_fallback_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
struct snd_dma_sg_fallback *sgbuf = dmab->private_data;

if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
return vm_map_pages(area, sgbuf->pages, sgbuf->count);
}

static const struct snd_malloc_ops snd_dma_sg_fallback_ops = {
.alloc = snd_dma_sg_fallback_alloc,
.free = snd_dma_sg_fallback_free,
.mmap = snd_dma_sg_fallback_mmap,
/* reuse vmalloc helpers */
.get_addr = snd_dma_vmalloc_get_addr,
.get_page = snd_dma_vmalloc_get_page,
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
};
#endif /* CONFIG_SND_DMA_SGBUF */

/*
Expand Down Expand Up @@ -736,6 +841,10 @@ static const struct snd_malloc_ops *dma_ops[] = {
#ifdef CONFIG_GENERIC_ALLOCATOR
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
#endif /* CONFIG_GENERIC_ALLOCATOR */
#ifdef CONFIG_SND_DMA_SGBUF
[SNDRV_DMA_TYPE_DEV_SG_FALLBACK] = &snd_dma_sg_fallback_ops,
[SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK] = &snd_dma_sg_fallback_ops,
#endif
#endif /* CONFIG_HAS_DMA */
};

Expand Down
2 changes: 1 addition & 1 deletion sound/core/pcm_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
return 0;
width = pcm_formats[(INT)format].phys; /* physical width */
pat = pcm_formats[(INT)format].silence;
if (! width)
if (!width || !pat)
return -EINVAL;
/* signed or 1 byte data */
if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
Expand Down
4 changes: 2 additions & 2 deletions sound/drivers/mtpav.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,6 @@ static int snd_mtpav_probe(struct platform_device *dev)
mtp_card->outmidihwport = 0xffffffff;
timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0);

card->private_free = snd_mtpav_free;

err = snd_mtpav_get_RAWMIDI(mtp_card);
if (err < 0)
return err;
Expand All @@ -716,6 +714,8 @@ static int snd_mtpav_probe(struct platform_device *dev)
if (err < 0)
return err;

card->private_free = snd_mtpav_free;

platform_set_drvdata(dev, card);
printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
return 0;
Expand Down
29 changes: 19 additions & 10 deletions sound/hda/hdac_i915.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,25 @@ static int i915_component_master_match(struct device *dev, int subcomponent,
return 0;
}

/* check whether intel graphics is present */
static bool i915_gfx_present(void)
/* check whether Intel graphics is present and reachable */
static int i915_gfx_present(struct pci_dev *hdac_pci)
{
static const struct pci_device_id ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
.class = PCI_BASE_CLASS_DISPLAY << 16,
.class_mask = 0xff << 16 },
{}
};
return pci_dev_present(ids);
unsigned int class = PCI_BASE_CLASS_DISPLAY << 16;
struct pci_dev *display_dev = NULL;
bool match = false;

do {
display_dev = pci_get_class(class, display_dev);

if (display_dev && display_dev->vendor == PCI_VENDOR_ID_INTEL &&
connectivity_check(display_dev, hdac_pci))
match = true;

pci_dev_put(display_dev);

} while (!match && display_dev);

return match;
}

/**
Expand All @@ -145,7 +154,7 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
struct drm_audio_component *acomp;
int err;

if (!i915_gfx_present())
if (!i915_gfx_present(to_pci_dev(bus->dev)))
return -ENODEV;

err = snd_hdac_acomp_init(bus, NULL,
Expand Down
18 changes: 16 additions & 2 deletions sound/hda/intel-dsp-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,22 +390,36 @@ static const struct config_entry config_table[] = {

/* Alder Lake */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
/* Alderlake-S */
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x7ad0,
},
/* RaptorLake-S */
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x51c8,
.device = 0x7a50,
},
/* Alderlake-P */
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x51cc,
.device = 0x51c8,
},
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x51cd,
},
/* Alderlake-PS */
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x51c9,
},
/* Alderlake-M */
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x51cc,
},
/* Alderlake-N */
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x54c8,
Expand Down
7 changes: 6 additions & 1 deletion sound/isa/galaxy/galaxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ static void snd_galaxy_free(struct snd_card *card)
galaxy_set_config(galaxy, galaxy->config);
}

static int snd_galaxy_probe(struct device *dev, unsigned int n)
static int __snd_galaxy_probe(struct device *dev, unsigned int n)
{
struct snd_galaxy *galaxy;
struct snd_wss *chip;
Expand Down Expand Up @@ -598,6 +598,11 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
return 0;
}

static int snd_galaxy_probe(struct device *dev, unsigned int n)
{
return snd_card_free_on_error(dev, __snd_galaxy_probe(dev, n));
}

static struct isa_driver snd_galaxy_driver = {
.match = snd_galaxy_match,
.probe = snd_galaxy_probe,
Expand Down
7 changes: 6 additions & 1 deletion sound/isa/sc6000.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ static void snd_sc6000_free(struct snd_card *card)
sc6000_setup_board(vport, 0);
}

static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
static int __snd_sc6000_probe(struct device *devptr, unsigned int dev)
{
static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
static const int possible_dmas[] = { 1, 3, 0, -1 };
Expand Down Expand Up @@ -662,6 +662,11 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
return 0;
}

static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
{
return snd_card_free_on_error(devptr, __snd_sc6000_probe(devptr, dev));
}

static struct isa_driver snd_sc6000_driver = {
.match = snd_sc6000_match,
.probe = snd_sc6000_probe,
Expand Down
6 changes: 0 additions & 6 deletions sound/oss/dmasound/dmasound.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,7 @@ static inline int ioctl_return(int __user *addr, int value)
*/

extern int dmasound_init(void);
#ifdef MODULE
extern void dmasound_deinit(void);
#else
#define dmasound_deinit() do { } while (0)
#endif

/* description of the set-up applies to either hard or soft settings */

Expand All @@ -114,9 +110,7 @@ typedef struct {
void *(*dma_alloc)(unsigned int, gfp_t);
void (*dma_free)(void *, unsigned int);
int (*irqinit)(void);
#ifdef MODULE
void (*irqcleanup)(void);
#endif
void (*init)(void);
void (*silence)(void);
int (*setFormat)(int);
Expand Down
Loading

0 comments on commit b9b4c79

Please sign in to comment.