Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfbab3fa authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "Two type of fixes:

   - The usual stuff, a handful HD-audio quirks for various machines

   - Further hardening against ALSA sequencer ioctl/write races that are
     triggered by fuzzer"

* tag 'sound-4.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda: add dock and led support for HP ProBook 640 G2
  ALSA: hda: add dock and led support for HP EliteBook 820 G3
  ALSA: hda/realtek - Make dock sound work on ThinkPad L570
  ALSA: seq: Remove superfluous snd_seq_queue_client_leave_cells() call
  ALSA: seq: More protection for concurrent write and ioctl races
  ALSA: seq: Don't allow resizing pool in use
  ALSA: hda/realtek - Fix dock line-out volume on Dell Precision 7520
  ALSA: hda/realtek: Limit mic boost on T480
  ALSA: hda/realtek - Add headset mode support for Dell laptop
  ALSA: hda/realtek - Add support headset mode for DELL WYSE
  ALSA: hda - Fix a wrong FIXUP for alc289 on Dell machines
parents 719ea861 099fd6ca
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -910,7 +910,8 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
					struct snd_seq_event *event,
					struct file *file, int blocking,
					int atomic, int hop)
					int atomic, int hop,
					struct mutex *mutexp)
{
	struct snd_seq_event_cell *cell;
	int err;
@@ -948,7 +949,8 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
		return -ENXIO; /* queue is not allocated */

	/* allocate an event cell */
	err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic, file);
	err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic,
				file, mutexp);
	if (err < 0)
		return err;

@@ -1017,12 +1019,11 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
		return -ENXIO;

	/* allocate the pool now if the pool is not allocated yet */ 
	if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) {
	mutex_lock(&client->ioctl_mutex);
	if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) {
		err = snd_seq_pool_init(client->pool);
		mutex_unlock(&client->ioctl_mutex);
		if (err < 0)
			return -ENOMEM;
			goto out;
	}

	/* only process whole events */
@@ -1073,7 +1074,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
		/* ok, enqueue it */
		err = snd_seq_client_enqueue_event(client, &event, file,
						   !(file->f_flags & O_NONBLOCK),
						   0, 0);
						   0, 0, &client->ioctl_mutex);
		if (err < 0)
			break;

@@ -1084,6 +1085,8 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
		written += len;
	}

 out:
	mutex_unlock(&client->ioctl_mutex);
	return written ? written : err;
}

@@ -1838,9 +1841,11 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
	    (! snd_seq_write_pool_allocated(client) ||
	     info->output_pool != client->pool->size)) {
		if (snd_seq_write_pool_allocated(client)) {
			/* is the pool in use? */
			if (atomic_read(&client->pool->counter))
				return -EBUSY;
			/* remove all existing cells */
			snd_seq_pool_mark_closing(client->pool);
			snd_seq_queue_client_leave_cells(client->number);
			snd_seq_pool_done(client->pool);
		}
		client->pool->size = info->output_pool;
@@ -2260,7 +2265,8 @@ static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
	if (! cptr->accept_output)
		result = -EPERM;
	else /* send it */
		result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, atomic, hop);
		result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
						      atomic, hop, NULL);

	snd_seq_client_unlock(cptr);
	return result;
+1 −1
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
		return -EINVAL;

	snd_use_lock_use(&f->use_lock);
	err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */
	err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL, NULL); /* always non-blocking */
	if (err < 0) {
		if ((err == -ENOMEM) || (err == -EAGAIN))
			atomic_inc(&f->overflow);
+10 −4
Original line number Diff line number Diff line
@@ -220,7 +220,8 @@ void snd_seq_cell_free(struct snd_seq_event_cell * cell)
 */
static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
			      struct snd_seq_event_cell **cellp,
			      int nonblock, struct file *file)
			      int nonblock, struct file *file,
			      struct mutex *mutexp)
{
	struct snd_seq_event_cell *cell;
	unsigned long flags;
@@ -244,7 +245,11 @@ static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
		set_current_state(TASK_INTERRUPTIBLE);
		add_wait_queue(&pool->output_sleep, &wait);
		spin_unlock_irq(&pool->lock);
		if (mutexp)
			mutex_unlock(mutexp);
		schedule();
		if (mutexp)
			mutex_lock(mutexp);
		spin_lock_irq(&pool->lock);
		remove_wait_queue(&pool->output_sleep, &wait);
		/* interrupted? */
@@ -287,7 +292,7 @@ static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
 */
int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
		      struct snd_seq_event_cell **cellp, int nonblock,
		      struct file *file)
		      struct file *file, struct mutex *mutexp)
{
	int ncells, err;
	unsigned int extlen;
@@ -304,7 +309,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
	if (ncells >= pool->total_elements)
		return -ENOMEM;

	err = snd_seq_cell_alloc(pool, &cell, nonblock, file);
	err = snd_seq_cell_alloc(pool, &cell, nonblock, file, mutexp);
	if (err < 0)
		return err;

@@ -330,7 +335,8 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
			int size = sizeof(struct snd_seq_event);
			if (len < size)
				size = len;
			err = snd_seq_cell_alloc(pool, &tmp, nonblock, file);
			err = snd_seq_cell_alloc(pool, &tmp, nonblock, file,
						 mutexp);
			if (err < 0)
				goto __error;
			if (cell->event.data.ext.ptr == NULL)
+2 −1
Original line number Diff line number Diff line
@@ -66,7 +66,8 @@ struct snd_seq_pool {
void snd_seq_cell_free(struct snd_seq_event_cell *cell);

int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
		      struct snd_seq_event_cell **cellp, int nonblock, struct file *file);
		      struct snd_seq_event_cell **cellp, int nonblock,
		      struct file *file, struct mutex *mutexp);

/* return number of unused (free) cells */
static inline int snd_seq_unused_cells(struct snd_seq_pool *pool)
+2 −0
Original line number Diff line number Diff line
@@ -957,6 +957,8 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
	SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
	SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
	SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
	SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
	SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
	SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
	SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
	SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
Loading