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

Commit 20ebba65 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa

* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa:
  [ALSA] version 1.0.13
  [ALSA] sound/pci/au88x0/au88x0.c: ioremap balanced with iounmap
  [ALSA] Handle file operations during snd_card disconnects using static file->f_op
  [ALSA] emu10k1: Fix outl() in snd_emu10k1_resume_regs()
  [ALSA] Repair snd-usb-usx2y for usb 2.6.18
  [ALSA] Fix bug in snd-usb-usx2y's usX2Y_pcms_lock_check()
  [ALSA] Dereference after free in snd_hwdep_release()
  [ALSA] Fix memory leak in sound/isa/es18xx.c
  [ALSA] hda-intel - New pci id for Nvidia MCP61
  [ALSA] Add new subdevice ids for hda-intel
  [ALSA] WM9712 fixes for ac97_patch.c
  [ALSA] hda/patch_si3054: new codec vendor IDs
parents 815a965b 5a078351
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -89,10 +89,10 @@ struct snd_device {
struct snd_monitor_file {
	struct file *file;
	struct snd_monitor_file *next;
	const struct file_operations *disconnected_f_op;
	struct list_head shutdown_list;
};

struct snd_shutdown_f_ops;	/* define it later in init.c */

/* main structure for soundcard */

struct snd_card {
+3 −3
Original line number Diff line number Diff line
/* include/version.h.  Generated by configure.  */
#define CONFIG_SND_VERSION "1.0.12rc1"
#define CONFIG_SND_DATE " (Thu Jun 22 13:55:50 2006 UTC)"
/* include/version.h.  Generated by alsa/ksync script.  */
#define CONFIG_SND_VERSION "1.0.13"
#define CONFIG_SND_DATE " (Fri Oct 06 18:28:19 2006 UTC)"
+2 −1
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
{
	int err = -ENXIO;
	struct snd_hwdep *hw = file->private_data;
	struct module *mod = hw->card->module;
	mutex_lock(&hw->open_mutex);
	if (hw->ops.release) {
		err = hw->ops.release(hw, file);
@@ -167,7 +168,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
		hw->used--;
	snd_card_file_remove(hw->card, file);
	mutex_unlock(&hw->open_mutex);
	module_put(hw->card->module);
	module_put(mod);
	return err;
}

+52 −40
Original line number Diff line number Diff line
@@ -33,10 +33,10 @@
#include <sound/control.h>
#include <sound/info.h>

struct snd_shutdown_f_ops {
	struct file_operations f_ops;
	struct snd_shutdown_f_ops *next;
};
static DEFINE_SPINLOCK(shutdown_lock);
static LIST_HEAD(shutdown_files);

static struct file_operations snd_shutdown_f_ops;

static unsigned int snd_cards_lock;	/* locked for registering/using */
struct snd_card *snd_cards[SNDRV_CARDS];
@@ -198,6 +198,25 @@ static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
	return -ENODEV;
}

static int snd_disconnect_release(struct inode *inode, struct file *file)
{
	struct snd_monitor_file *df = NULL, *_df;

	spin_lock(&shutdown_lock);
	list_for_each_entry(_df, &shutdown_files, shutdown_list) {
		if (_df->file == file) {
			df = _df;
			break;
		}
	}
	spin_unlock(&shutdown_lock);

	if (likely(df))
		return df->disconnected_f_op->release(inode, file);

	panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
}

static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
{
	return POLLERR | POLLNVAL;
@@ -219,6 +238,22 @@ static int snd_disconnect_fasync(int fd, struct file *file, int on)
	return -ENODEV;
}

static struct file_operations snd_shutdown_f_ops =
{
	.owner = 	THIS_MODULE,
	.llseek =	snd_disconnect_llseek,
	.read = 	snd_disconnect_read,
	.write =	snd_disconnect_write,
	.release =	snd_disconnect_release,
	.poll =		snd_disconnect_poll,
	.unlocked_ioctl = snd_disconnect_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = snd_disconnect_ioctl,
#endif
	.mmap =		snd_disconnect_mmap,
	.fasync =	snd_disconnect_fasync
};

/**
 *  snd_card_disconnect - disconnect all APIs from the file-operations (user space)
 *  @card: soundcard structure
@@ -234,9 +269,6 @@ int snd_card_disconnect(struct snd_card *card)
{
	struct snd_monitor_file *mfile;
	struct file *file;
	struct snd_shutdown_f_ops *s_f_ops;
	struct file_operations *f_ops;
	const struct file_operations *old_f_ops;
	int err;

	spin_lock(&card->files_lock);
@@ -261,34 +293,14 @@ int snd_card_disconnect(struct snd_card *card)

		/* it's critical part, use endless loop */
		/* we have no room to fail */
		s_f_ops = kmalloc(sizeof(struct snd_shutdown_f_ops), GFP_ATOMIC);
		if (s_f_ops == NULL)
			panic("Atomic allocation failed for snd_shutdown_f_ops!");

		f_ops = &s_f_ops->f_ops;

		memset(f_ops, 0, sizeof(*f_ops));
		f_ops->owner = file->f_op->owner;
		f_ops->release = file->f_op->release;
		f_ops->llseek = snd_disconnect_llseek;
		f_ops->read = snd_disconnect_read;
		f_ops->write = snd_disconnect_write;
		f_ops->poll = snd_disconnect_poll;
		f_ops->unlocked_ioctl = snd_disconnect_ioctl;
#ifdef CONFIG_COMPAT
		f_ops->compat_ioctl = snd_disconnect_ioctl;
#endif
		f_ops->mmap = snd_disconnect_mmap;
		f_ops->fasync = snd_disconnect_fasync;

		s_f_ops->next = card->s_f_ops;
		card->s_f_ops = s_f_ops;
		mfile->disconnected_f_op = mfile->file->f_op;

		f_ops = fops_get(f_ops);
		spin_lock(&shutdown_lock);
		list_add(&mfile->shutdown_list, &shutdown_files);
		spin_unlock(&shutdown_lock);

		old_f_ops = file->f_op;
		file->f_op = f_ops;	/* must be atomic */
		fops_put(old_f_ops);
		fops_get(&snd_shutdown_f_ops);
		mfile->file->f_op = &snd_shutdown_f_ops;
		
		mfile = mfile->next;
	}
@@ -326,8 +338,6 @@ EXPORT_SYMBOL(snd_card_disconnect);
 */
static int snd_card_do_free(struct snd_card *card)
{
	struct snd_shutdown_f_ops *s_f_ops;

#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
	if (snd_mixer_oss_notify_callback)
		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -351,11 +361,6 @@ static int snd_card_do_free(struct snd_card *card)
		snd_printk(KERN_WARNING "unable to free card info\n");
		/* Not fatal error */
	}
	while (card->s_f_ops) {
		s_f_ops = card->s_f_ops;
		card->s_f_ops = s_f_ops->next;
		kfree(s_f_ops);
	}
	kfree(card);
	return 0;
}
@@ -670,6 +675,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
	if (mfile == NULL)
		return -ENOMEM;
	mfile->file = file;
	mfile->disconnected_f_op = NULL;
	mfile->next = NULL;
	spin_lock(&card->files_lock);
	if (card->shutdown) {
@@ -716,6 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
		pfile = mfile;
		mfile = mfile->next;
	}
	if (mfile && mfile->disconnected_f_op) {
		fops_put(mfile->disconnected_f_op);
		spin_lock(&shutdown_lock);
		list_del(&mfile->shutdown_list);
		spin_unlock(&shutdown_lock);
	}
	if (card->files == NULL)
		last_close = 1;
	spin_unlock(&card->files_lock);
+1 −0
Original line number Diff line number Diff line
@@ -2154,6 +2154,7 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
	}
	/* Control port initialization */
	if (pnp_activate_dev(acard->devc) < 0) {
		kfree(cfg);
		snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
		return -EAGAIN;
	}
Loading