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
This commit is contained in:
commit
20ebba6509
|
@ -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 {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
/* 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)"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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!");
|
||||
mfile->disconnected_f_op = mfile->file->f_op;
|
||||
|
||||
f_ops = &s_f_ops->f_ops;
|
||||
spin_lock(&shutdown_lock);
|
||||
list_add(&mfile->shutdown_list, &shutdown_files);
|
||||
spin_unlock(&shutdown_lock);
|
||||
|
||||
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;
|
||||
|
||||
f_ops = fops_get(f_ops);
|
||||
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -530,7 +530,7 @@ AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
|
|||
AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
|
||||
|
||||
AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
|
||||
AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
|
||||
AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
|
||||
AC97_ENUM("Out3 Mux", wm9711_enum[2]),
|
||||
AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
|
||||
AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
|
||||
|
@ -575,13 +575,14 @@ AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
|
|||
|
||||
AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
|
||||
AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
|
||||
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 1),
|
||||
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
|
||||
AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
|
||||
|
||||
AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
|
||||
AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
|
||||
AC97_ENUM("Mic Select Source", wm9711_enum[7]),
|
||||
AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 32, 1),
|
||||
AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
|
||||
AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
|
||||
AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
|
||||
|
||||
AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
|
||||
|
|
|
@ -128,6 +128,7 @@ static int snd_vortex_dev_free(struct snd_device *device)
|
|||
// Take down PCI interface.
|
||||
synchronize_irq(vortex->irq);
|
||||
free_irq(vortex->irq, vortex);
|
||||
iounmap(vortex->mmio);
|
||||
pci_release_regions(vortex->pci_dev);
|
||||
pci_disable_device(vortex->pci_dev);
|
||||
kfree(vortex);
|
||||
|
|
|
@ -1461,8 +1461,8 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
|
|||
|
||||
/* resore for spdif */
|
||||
if (emu->audigy)
|
||||
outl(emu->port + A_IOCFG, emu->saved_a_iocfg);
|
||||
outl(emu->port + HCFG, emu->saved_hcfg);
|
||||
outl(emu->saved_a_iocfg, emu->port + A_IOCFG);
|
||||
outl(emu->saved_hcfg, emu->port + HCFG);
|
||||
|
||||
val = emu->saved_ptr;
|
||||
for (reg = saved_regs; *reg != 0xff; reg++)
|
||||
|
|
|
@ -1682,6 +1682,7 @@ static struct pci_device_id azx_ids[] = {
|
|||
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
|
||||
{ 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */
|
||||
{ 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */
|
||||
{ 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 03f0 */
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, azx_ids);
|
||||
|
|
|
@ -5076,6 +5076,10 @@ static struct hda_board_config alc883_cfg_tbl[] = {
|
|||
{ .modelname = "acer", .config = ALC883_ACER },
|
||||
{ .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/,
|
||||
.config = ALC883_ACER },
|
||||
{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0102,
|
||||
.config = ALC883_ACER },
|
||||
{ .pci_subvendor = 0x1025, .pci_subdevice = 0x009f,
|
||||
.config = ALC883_ACER },
|
||||
{ .modelname = "auto", .config = ALC883_AUTO },
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -297,8 +297,13 @@ static int patch_si3054(struct hda_codec *codec)
|
|||
struct hda_codec_preset snd_hda_preset_si3054[] = {
|
||||
{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x11c11040, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x11c13055, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x11c13155, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
|
||||
{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ static void i_usX2Y_urb_complete(struct urb *urb)
|
|||
usX2Y_error_urb_status(usX2Y, subs, urb);
|
||||
return;
|
||||
}
|
||||
if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame))
|
||||
if (likely(urb->start_frame == usX2Y->wait_iso_frame))
|
||||
subs->completed_urb = urb;
|
||||
else {
|
||||
usX2Y_error_sequence(usX2Y, subs, urb);
|
||||
|
@ -335,13 +335,9 @@ static void i_usX2Y_urb_complete(struct urb *urb)
|
|||
atomic_read(&capsubs->state) >= state_PREPARED &&
|
||||
(playbacksubs->completed_urb ||
|
||||
atomic_read(&playbacksubs->state) < state_PREPARED)) {
|
||||
if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) {
|
||||
if (nr_of_packs() <= urb->start_frame &&
|
||||
urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci
|
||||
usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
|
||||
else
|
||||
usX2Y->wait_iso_frame += nr_of_packs();
|
||||
} else {
|
||||
if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame))
|
||||
usX2Y->wait_iso_frame += nr_of_packs();
|
||||
else {
|
||||
snd_printdd("\n");
|
||||
usX2Y_clients_stop(usX2Y);
|
||||
}
|
||||
|
@ -495,7 +491,6 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
|
|||
if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
|
||||
goto start;
|
||||
}
|
||||
usX2Y->wait_iso_frame = -1;
|
||||
|
||||
start:
|
||||
usX2Y_subs_startup(subs);
|
||||
|
@ -516,10 +511,9 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
|
|||
snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
|
||||
err = -EPIPE;
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (0 > usX2Y->wait_iso_frame)
|
||||
} else
|
||||
if (i == 0)
|
||||
usX2Y->wait_iso_frame = urb->start_frame;
|
||||
}
|
||||
urb->transfer_flags = 0;
|
||||
} else {
|
||||
atomic_set(&subs->state, state_STARTING1);
|
||||
|
|
|
@ -243,7 +243,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
|
|||
usX2Y_error_urb_status(usX2Y, subs, urb);
|
||||
return;
|
||||
}
|
||||
if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame))
|
||||
if (likely(urb->start_frame == usX2Y->wait_iso_frame))
|
||||
subs->completed_urb = urb;
|
||||
else {
|
||||
usX2Y_error_sequence(usX2Y, subs, urb);
|
||||
|
@ -256,13 +256,9 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
|
|||
if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
|
||||
(NULL == capsubs2 || capsubs2->completed_urb) &&
|
||||
(playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
|
||||
if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) {
|
||||
if (nr_of_packs() <= urb->start_frame &&
|
||||
urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci
|
||||
usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
|
||||
else
|
||||
usX2Y->wait_iso_frame += nr_of_packs();
|
||||
} else {
|
||||
if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame))
|
||||
usX2Y->wait_iso_frame += nr_of_packs();
|
||||
else {
|
||||
snd_printdd("\n");
|
||||
usX2Y_clients_stop(usX2Y);
|
||||
}
|
||||
|
@ -433,7 +429,6 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
|
|||
if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
|
||||
goto start;
|
||||
}
|
||||
usX2Y->wait_iso_frame = -1;
|
||||
|
||||
start:
|
||||
usX2Y_usbpcm_subs_startup(subs);
|
||||
|
@ -459,7 +454,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
|
|||
goto cleanup;
|
||||
} else {
|
||||
snd_printdd("%i\n", urb->start_frame);
|
||||
if (0 > usX2Y->wait_iso_frame)
|
||||
if (u == 0)
|
||||
usX2Y->wait_iso_frame = urb->start_frame;
|
||||
}
|
||||
urb->transfer_flags = 0;
|
||||
|
@ -632,7 +627,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card)
|
|||
for (s = 0; s < 2; ++s) {
|
||||
struct snd_pcm_substream *substream;
|
||||
substream = pcm->streams[s].substream;
|
||||
if (SUBSTREAM_BUSY(substream))
|
||||
if (substream && SUBSTREAM_BUSY(substream))
|
||||
err = -EBUSY;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue