Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8ec59ac
ALSA: usb-audio: Fix a missing error check in scarlett gen2 mixer
tiwai Sep 29, 2021
eb67662
ALSA: hda/realtek: Enable 4-speaker output for Dell Precision 5560 la…
johnliu55tw Sep 30, 2021
1f8763c
ALSA: seq: Fix a potential UAF by wrong private_free call order
tiwai Sep 30, 2021
2b987fe
ALSA: hda - Enable headphone mic on Dell Latitude laptops with ALC3254
mschiu77 Oct 1, 2021
1f8d398
ALSA: hda/realtek: Complete partial device name to avoid ambiguity
tuxedo-wse Oct 1, 2021
cc03069
ALSA: hda/realtek: Add quirk for Clevo X170KM-G
tuxedo-wse Oct 1, 2021
5963e52
ALSA: usb-audio: Enable rate validation for Scarlett devices
tiwai Oct 4, 2021
5aec989
ALSA: hda/realtek - ALC236 headset MIC recording issue
KailangYang Oct 5, 2021
dd6dd6e
ALSA: hda/realtek: Add quirk for TongFang PHxTxX1
tuxedo-wse Oct 6, 2021
c0f1886
ALSA: hda: intel: Allow repeatedly probing on codec configuration errors
tiwai Oct 6, 2021
023a062
ALSA: hda/realtek: Fix for quirk to enable speaker output on the Leno…
cberkenpas Oct 10, 2021
228af5a
ALSA: pcm: Workaround for a wrong offset in SYNC_PTR compat ioctl
tiwai Oct 10, 2021
a3fd1a9
ALSA: hda/realtek: Fix the mic type detection issue for ASUS G551JW
jason77-wang Oct 12, 2021
b37a151
ALSA: hda: avoid write to STATESTS if controller is in reset
kv2019i Oct 12, 2021
48827e1
ALSA: usb-audio: Add quirk for VF0770
hahnjo Oct 12, 2021
1626d9a
Merge tag 'sound-5.15-rc6' of git://git.kernel.org/pub/scm/linux/kern…
torvalds Oct 14, 2021
26d6574
MAINTAINERS: Update entry for the Stratix10 firmware
Oct 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -9629,7 +9629,7 @@ F: include/uapi/linux/isst_if.h
F: tools/power/x86/intel-speed-select/

INTEL STRATIX10 FIRMWARE DRIVERS
M: Richard Gong <richard.gong@linux.intel.com>
M: Dinh Nguyen <dinguyen@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
Expand Down
1 change: 1 addition & 0 deletions include/sound/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ struct hda_codec {
#endif

/* misc flags */
unsigned int configured:1; /* codec was configured */
unsigned int in_freeing:1; /* being released */
unsigned int registered:1; /* codec was registered */
unsigned int display_power_control:1; /* needs display power */
Expand Down
72 changes: 71 additions & 1 deletion sound/core/pcm_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,76 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
}
#endif /* CONFIG_X86_X32 */

#ifdef __BIG_ENDIAN
typedef char __pad_before_u32[4];
typedef char __pad_after_u32[0];
#else
typedef char __pad_before_u32[0];
typedef char __pad_after_u32[4];
#endif

/* PCM 2.0.15 API definition had a bug in mmap control; it puts the avail_min
* at the wrong offset due to a typo in padding type.
* The bug hits only 32bit.
* A workaround for incorrect read/write is needed only in 32bit compat mode.
*/
struct __snd_pcm_mmap_control64_buggy {
__pad_before_u32 __pad1;
__u32 appl_ptr;
__pad_before_u32 __pad2; /* SiC! here is the bug */
__pad_before_u32 __pad3;
__u32 avail_min;
__pad_after_uframe __pad4;
};

static int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream,
struct snd_pcm_sync_ptr __user *_sync_ptr)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_sync_ptr sync_ptr;
struct __snd_pcm_mmap_control64_buggy *sync_cp;
volatile struct snd_pcm_mmap_status *status;
volatile struct snd_pcm_mmap_control *control;
int err;

memset(&sync_ptr, 0, sizeof(sync_ptr));
sync_cp = (struct __snd_pcm_mmap_control64_buggy *)&sync_ptr.c.control;
if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
return -EFAULT;
if (copy_from_user(sync_cp, &(_sync_ptr->c.control), sizeof(*sync_cp)))
return -EFAULT;
status = runtime->status;
control = runtime->control;
if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
err = snd_pcm_hwsync(substream);
if (err < 0)
return err;
}
snd_pcm_stream_lock_irq(substream);
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr);
if (err < 0) {
snd_pcm_stream_unlock_irq(substream);
return err;
}
} else {
sync_cp->appl_ptr = control->appl_ptr;
}
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
control->avail_min = sync_cp->avail_min;
else
sync_cp->avail_min = control->avail_min;
sync_ptr.s.status.state = status->state;
sync_ptr.s.status.hw_ptr = status->hw_ptr;
sync_ptr.s.status.tstamp = status->tstamp;
sync_ptr.s.status.suspended_state = status->suspended_state;
sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
snd_pcm_stream_unlock_irq(substream);
if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
return -EFAULT;
return 0;
}

/*
*/
enum {
Expand Down Expand Up @@ -537,7 +607,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
if (in_x32_syscall())
return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
#endif /* CONFIG_X86_X32 */
return snd_pcm_common_ioctl(file, substream, cmd, argp);
return snd_pcm_ioctl_sync_ptr_buggy(substream, argp);
case SNDRV_PCM_IOCTL_HW_REFINE32:
return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
case SNDRV_PCM_IOCTL_HW_PARAMS32:
Expand Down
8 changes: 3 additions & 5 deletions sound/core/seq_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ static int snd_seq_device_dev_free(struct snd_device *device)
struct snd_seq_device *dev = device->device_data;

cancel_autoload_drivers();
if (dev->private_free)
dev->private_free(dev);
put_device(&dev->dev);
return 0;
}
Expand Down Expand Up @@ -183,11 +185,7 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device)

static void snd_seq_dev_release(struct device *dev)
{
struct snd_seq_device *sdev = to_seq_dev(dev);

if (sdev->private_free)
sdev->private_free(sdev);
kfree(sdev);
kfree(to_seq_dev(dev));
}

/*
Expand Down
5 changes: 3 additions & 2 deletions sound/hda/hdac_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,9 @@ int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset)
if (!full_reset)
goto skip_reset;

/* clear STATESTS */
snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
/* clear STATESTS if not in reset */
if (snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)
snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);

/* reset controller */
snd_hdac_bus_enter_link_reset(bus);
Expand Down
20 changes: 11 additions & 9 deletions sound/pci/hda/hda_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,29 +298,31 @@ int snd_hda_codec_configure(struct hda_codec *codec)
{
int err;

if (codec->configured)
return 0;

if (is_generic_config(codec))
codec->probe_id = HDA_CODEC_ID_GENERIC;
else
codec->probe_id = 0;

err = snd_hdac_device_register(&codec->core);
if (err < 0)
return err;
if (!device_is_registered(&codec->core.dev)) {
err = snd_hdac_device_register(&codec->core);
if (err < 0)
return err;
}

if (!codec->preset)
codec_bind_module(codec);
if (!codec->preset) {
err = codec_bind_generic(codec);
if (err < 0) {
codec_err(codec, "Unable to bind the codec\n");
goto error;
codec_dbg(codec, "Unable to bind the codec\n");
return err;
}
}

codec->configured = 1;
return 0;

error:
snd_hdac_device_unregister(&codec->core);
return err;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
1 change: 1 addition & 0 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
snd_array_free(&codec->nids);
remove_conn_list(codec);
snd_hdac_regmap_exit(&codec->core);
codec->configured = 0;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind);

Expand Down
24 changes: 16 additions & 8 deletions sound/pci/hda/hda_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <sound/core.h>
#include <sound/initval.h>
#include "hda_controller.h"
#include "hda_local.h"

#define CREATE_TRACE_POINTS
#include "hda_controller_trace.h"
Expand Down Expand Up @@ -1248,17 +1249,24 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs);
int azx_codec_configure(struct azx *chip)
{
struct hda_codec *codec, *next;
int success = 0;

/* use _safe version here since snd_hda_codec_configure() deregisters
* the device upon error and deletes itself from the bus list.
*/
list_for_each_codec_safe(codec, next, &chip->bus) {
snd_hda_codec_configure(codec);
list_for_each_codec(codec, &chip->bus) {
if (!snd_hda_codec_configure(codec))
success++;
}

if (!azx_bus(chip)->num_codecs)
return -ENODEV;
return 0;
if (success) {
/* unregister failed codecs if any codec has been probed */
list_for_each_codec_safe(codec, next, &chip->bus) {
if (!codec->configured) {
codec_err(codec, "Unable to configure, disabling\n");
snd_hdac_device_unregister(&codec->core);
}
}
}

return success ? 0 : -ENODEV;
}
EXPORT_SYMBOL_GPL(azx_codec_configure);

Expand Down
2 changes: 1 addition & 1 deletion sound/pci/hda/hda_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
/* 24 unused */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
/* 27 unused */
#define AZX_DCAPS_RETRY_PROBE (1 << 27) /* retry probe if no codec is configured */
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */
#define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */
#define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */
Expand Down
29 changes: 23 additions & 6 deletions sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ enum {
/* quirks for AMD SB */
#define AZX_DCAPS_PRESET_AMD_SB \
(AZX_DCAPS_NO_TCSEL | AZX_DCAPS_AMD_WORKAROUND |\
AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME)
AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME |\
AZX_DCAPS_RETRY_PROBE)

/* quirks for Nvidia */
#define AZX_DCAPS_PRESET_NVIDIA \
Expand Down Expand Up @@ -1723,7 +1724,7 @@ static void azx_check_snoop_available(struct azx *chip)

static void azx_probe_work(struct work_struct *work)
{
struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
struct hda_intel *hda = container_of(work, struct hda_intel, probe_work.work);
azx_probe_continue(&hda->chip);
}

Expand Down Expand Up @@ -1828,7 +1829,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
}

/* continue probing in work context as may trigger request module */
INIT_WORK(&hda->probe_work, azx_probe_work);
INIT_DELAYED_WORK(&hda->probe_work, azx_probe_work);

*rchip = chip;

Expand Down Expand Up @@ -2142,7 +2143,7 @@ static int azx_probe(struct pci_dev *pci,
#endif

if (schedule_probe)
schedule_work(&hda->probe_work);
schedule_delayed_work(&hda->probe_work, 0);

dev++;
if (chip->disabled)
Expand Down Expand Up @@ -2228,6 +2229,11 @@ static int azx_probe_continue(struct azx *chip)
int dev = chip->dev_index;
int err;

if (chip->disabled || hda->init_failed)
return -EIO;
if (hda->probe_retry)
goto probe_retry;

to_hda_bus(bus)->bus_probing = 1;
hda->probe_continued = 1;

Expand Down Expand Up @@ -2289,10 +2295,20 @@ static int azx_probe_continue(struct azx *chip)
#endif
}
#endif

probe_retry:
if (bus->codec_mask && !(probe_only[dev] & 1)) {
err = azx_codec_configure(chip);
if (err < 0)
if (err) {
if ((chip->driver_caps & AZX_DCAPS_RETRY_PROBE) &&
++hda->probe_retry < 60) {
schedule_delayed_work(&hda->probe_work,
msecs_to_jiffies(1000));
return 0; /* keep things up */
}
dev_err(chip->card->dev, "Cannot probe codecs, giving up\n");
goto out_free;
}
}

err = snd_card_register(chip->card);
Expand Down Expand Up @@ -2322,6 +2338,7 @@ static int azx_probe_continue(struct azx *chip)
display_power(chip, false);
complete_all(&hda->probe_wait);
to_hda_bus(bus)->bus_probing = 0;
hda->probe_retry = 0;
return 0;
}

Expand All @@ -2347,7 +2364,7 @@ static void azx_remove(struct pci_dev *pci)
* device during cancel_work_sync() call.
*/
device_unlock(&pci->dev);
cancel_work_sync(&hda->probe_work);
cancel_delayed_work_sync(&hda->probe_work);
device_lock(&pci->dev);

snd_card_free(card);
Expand Down
4 changes: 3 additions & 1 deletion sound/pci/hda/hda_intel.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct hda_intel {

/* sync probing */
struct completion probe_wait;
struct work_struct probe_work;
struct delayed_work probe_work;

/* card list (for power_save trigger) */
struct list_head list;
Expand All @@ -30,6 +30,8 @@ struct hda_intel {
unsigned int freed:1; /* resources already released */

bool need_i915_power:1; /* the hda controller needs i915 power */

int probe_retry; /* being probe-retry */
};

#endif
Loading