Commit e4eaa6be authored by Jaroslav Kysela's avatar Jaroslav Kysela

[PATCH] ALSA fixes

  - save_flags/cli/restore_flags removal
  - updated USB code for 2.5
  - fixed SPARC configuration
  - fixed spinlock/sleep race in PCM midlevel
parent d175a2f8
......@@ -1048,7 +1048,7 @@ int isapnp_cfg_begin(int csn, int logdev)
isapnp_wait();
isapnp_key();
isapnp_wake(csn);
#if 1
#if 0
/* to avoid malfunction when the isapnptools package is used */
/* we must set RDP to our value again */
/* it is possible to set RDP only in the isolation phase */
......
......@@ -91,8 +91,9 @@ struct _snd_wavefront {
int samples_used; /* how many */
char interrupts_are_midi; /* h/w MPU interrupts enabled ? */
char rom_samples_rdonly; /* can we write on ROM samples */
spinlock_t irq_lock;
wait_queue_head_t interrupt_sleeper;
snd_wavefront_midi_t midi; /* ICS2115 MIDI interface */
snd_wavefront_midi_t midi; /* ICS2115 MIDI interface */
};
struct _snd_wavefront_card {
......
......@@ -36,11 +36,10 @@ fi
if [ "$CONFIG_SND" != "n" -a "$CONFIG_USB" != "n" ]; then
source sound/usb/Config.in
fi
if [ "$CONFIG_SND" != "n" -a "$CONFIG_SPARC32" = "y" ]; then
source sound/sparc/Config.in
fi
if [ "$CONFIG_SND" != "n" -a "$CONFIG_SPARC64" = "y" ]; then
source sound/sparc/Config.in
if [ "$CONFIG_SND" != "n" ]; then
if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then
source sound/sparc/Config.in
fi
fi
endmenu
......@@ -1851,8 +1851,8 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
mask = 0;
if (psubstream != NULL) {
snd_pcm_runtime_t *runtime = psubstream->runtime;
spin_lock_irq(&runtime->lock);
poll_wait(file, &runtime->sleep, wait);
spin_lock_irq(&runtime->lock);
if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
(runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_playback_ready(psubstream)))
......@@ -1861,8 +1861,8 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
}
if (csubstream != NULL) {
snd_pcm_runtime_t *runtime = csubstream->runtime;
spin_lock_irq(&runtime->lock);
poll_wait(file, &runtime->sleep, wait);
spin_lock_irq(&runtime->lock);
if (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_capture_ready(csubstream))
mask |= POLLIN | POLLRDNORM;
......
......@@ -947,7 +947,10 @@ static inline void snd_pcm_post_reset(snd_pcm_substream_t * substream, int state
static int snd_pcm_reset(snd_pcm_substream_t *substream)
{
int res;
spin_lock_irq(&substream->runtime->lock);
_SND_PCM_ACTION(reset, substream, 0, res, 0);
spin_unlock_irq(&substream->runtime->lock);
return res;
}
......@@ -984,6 +987,7 @@ int snd_pcm_prepare(snd_pcm_substream_t *substream)
{
int res;
snd_card_t *card = substream->pcm->card;
snd_power_lock(card);
while (snd_power_get_state(card) != SNDRV_CTL_POWER_D0) {
if (substream->ffile->f_flags & O_NONBLOCK) {
......@@ -993,7 +997,9 @@ int snd_pcm_prepare(snd_pcm_substream_t *substream)
snd_power_wait(card);
}
spin_lock_irq(&substream->runtime->lock);
_SND_PCM_ACTION(prepare, substream, 0, res, 0);
spin_unlock_irq(&substream->runtime->lock);
_power_unlock:
snd_power_unlock(card);
......@@ -2051,21 +2057,9 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
case SNDRV_PCM_IOCTL_CHANNEL_INFO:
return snd_pcm_channel_info(substream, (snd_pcm_channel_info_t *) arg);
case SNDRV_PCM_IOCTL_PREPARE:
{
int res;
spin_lock_irq(&substream->runtime->lock);
res = snd_pcm_prepare(substream);
spin_unlock_irq(&substream->runtime->lock);
return res;
}
return snd_pcm_prepare(substream);
case SNDRV_PCM_IOCTL_RESET:
{
int res;
spin_lock_irq(&substream->runtime->lock);
res = snd_pcm_reset(substream);
spin_unlock_irq(&substream->runtime->lock);
return res;
}
return snd_pcm_reset(substream);
case SNDRV_PCM_IOCTL_START:
{
int res;
......
......@@ -495,6 +495,7 @@ snd_wavefront_probe (int dev)
}
acard = (snd_wavefront_card_t *)card->private_data;
acard->wavefront.irq = -1;
spin_lock_init(&acard->wavefront.irq_lock);
init_waitqueue_head(&acard->wavefront.interrupt_sleeper);
spin_lock_init(&acard->wavefront.midi.open);
spin_lock_init(&acard->wavefront.midi.virtual);
......
......@@ -1705,9 +1705,11 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
return;
}
spin_lock(&dev->irq_lock);
dev->irq_ok = 1;
dev->irq_cnt++;
wake_up_interruptible (&dev->interrupt_sleeper);
spin_unlock(&dev->irq_lock);
wake_up(&dev->interrupt_sleeper);
}
/* STATUS REGISTER
......@@ -1755,14 +1757,20 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
int val, int port, int timeout)
{
unsigned long flags;
wait_queue_t wait;
save_flags (flags);
cli();
init_waitqueue_entry(&wait, current);
spin_lock_irq(&dev->irq_lock);
add_wait_queue(&dev->interrupt_sleeper, &wait);
dev->irq_ok = 0;
outb (val,port);
interruptible_sleep_on_timeout (&dev->interrupt_sleeper, timeout);
restore_flags (flags);
spin_unlock_irq(&dev->irq_lock);
while (1) {
if ((timeout = schedule_timeout(timeout)) == 0)
return;
if (dev->irq_ok)
return;
}
}
static int __init
......
......@@ -1871,7 +1871,6 @@ static void snd_ali_suspend(struct pci_dev *dev)
ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return);
#endif
ali_image_t *im;
unsigned long flags;
int i, j;
im = chip->image;
......@@ -1882,8 +1881,7 @@ static void snd_ali_suspend(struct pci_dev *dev)
return;
#endif
save_flags(flags);
cli();
spin_lock_irq(&chip->reg_lock);
im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT));
// im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START));
......@@ -1907,7 +1905,7 @@ static void snd_ali_suspend(struct pci_dev *dev)
// stop all HW channel
outl(0xffffffff, ALI_REG(chip, ALI_STOP));
restore_flags(flags);
spin_unlock_irq(&chip->reg_lock);
#ifndef PCI_OLD_SUSPEND
return 0;
#endif
......@@ -1925,7 +1923,6 @@ static void snd_ali_resume(struct pci_dev *dev)
ali_t *chip = snd_magic_cast(ali_t, pci_get_drvdata(dev), return);
#endif
ali_image_t *im;
unsigned long flags;
int i, j;
im = chip->image;
......@@ -1938,8 +1935,7 @@ static void snd_ali_resume(struct pci_dev *dev)
pci_enable_device(chip->pci);
save_flags(flags);
cli();
spin_lock_irq(&chip->reg_lock);
for (i = 0; i < ALI_CHANNELS; i++) {
outb(i, ALI_REG(chip, ALI_GC_CIR));
......@@ -1960,7 +1956,7 @@ static void snd_ali_resume(struct pci_dev *dev)
// restore IRQ enable bits
outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT));
restore_flags(flags);
spin_unlock_irq(&chip->reg_lock);
#ifndef PCI_OLD_SUSPEND
return 0;
#endif
......
......@@ -1595,8 +1595,7 @@ int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
ins->spdif_in_src,
SCB_ON_PARENT_SUBLIST_SCB);
save_flags(flags);
cli();
spin_lock_irq(&chip->reg_lock);
/* reset SPDIF input sample buffer pointer */
snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2,
......@@ -1609,7 +1608,7 @@ int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
/* restore SPDIF input volume */
snd_cs46xx_poke(chip, (ASYNCRX_SCB_ADDR + 0xE) << 2, ins->spdif_input_volume);
snd_cs46xx_poke(chip, (ASYNCRX_SCB_ADDR + 0xF) << 2, ins->spdif_input_volume);
restore_flags(flags);
spin_unlock_irq(&chip->reg_lock);
/* set SPDIF input sample rate and unmute
NOTE: only 48khz support for SPDIF input this time */
......
......@@ -1426,14 +1426,10 @@ int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src)
src->parent_scb_ptr = parent_scb;
/* update entry in DSP RAM */
spin_lock_irqsave(&chip->reg_lock, flags);
snd_cs46xx_poke(chip,
(parent_scb->address + SCBsubListPtr) << 2,
(parent_scb->sub_list_ptr->address << 0x10) |
(parent_scb->next_scb_ptr->address));
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}
......@@ -1292,9 +1292,15 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
* entry point for linux usb interface
*/
static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
#ifndef OLD_USB
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void usb_audio_disconnect(struct usb_interface *intf);
#else
static void * usb_audio_probe(usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id);
static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
#endif
static struct usb_device_id usb_audio_ids [] = {
#include "usbquirks.h"
......@@ -1310,7 +1316,9 @@ static struct usb_driver usb_audio_driver = {
.name = "snd-usb-audio",
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,
#ifdef OLD_USB
.driver_list = LIST_HEAD_INIT(usb_audio_driver.driver_list),
#endif
.id_table = usb_audio_ids,
};
......@@ -2042,9 +2050,18 @@ static int alloc_desc_buffer(struct usb_device *dev, int index, unsigned char **
* only at the first time. the successive calls of this function will
* append the pcm interface to the corresponding card.
*/
#ifndef OLD_USB
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *id)
#else
static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
#endif
{
#ifndef OLD_USB
struct usb_device *dev = interface_to_usbdev(intf);
int ifnum = intf->altsetting->bInterfaceNumber;
#endif
struct usb_config_descriptor *config = dev->actconfig;
const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)id->driver_info;
unsigned char *buffer;
......@@ -2054,17 +2071,17 @@ static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
snd_usb_audio_t *chip;
if (quirk && ifnum != quirk->ifnum)
return NULL;
goto __err_val;
if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", config->bConfigurationValue);
return NULL;
goto __err_val;
}
index = dev->actconfig - config;
buflen = alloc_desc_buffer(dev, index, &buffer);
if (buflen <= 0)
return NULL;
goto __err_val;
/*
* found a config. now register to ALSA
......@@ -2126,12 +2143,21 @@ static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
chip->num_interfaces++;
up(&register_mutex);
kfree(buffer);
#ifndef OLD_USB
return 0;
#else
return chip;
#endif
__error:
up(&register_mutex);
kfree(buffer);
__err_val:
#ifndef OLD_USB
return -EIO;
#else
return NULL;
#endif
}
......@@ -2139,8 +2165,15 @@ static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
* we need to take care of counter, since disconnection can be called also
* many times as well as usb_audio_probe().
*/
#ifndef OLD_USB
static void usb_audio_disconnect(struct usb_interface *intf)
#else
static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
#endif
{
#ifndef OLD_USB
void *ptr = dev_get_drvdata(&intf->dev);
#endif
snd_usb_audio_t *chip;
if (ptr == (void *)-1)
......
......@@ -479,6 +479,22 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
snd_magic_kfree(ep);
}
#ifndef OLD_USB
/* this code is not exported from USB core anymore */
struct usb_interface *local_usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
{
int i;
for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)
return &dev->actconfig->interface[i];
return NULL;
}
#else
#define local_usb_ifnum_to_if usb_ifnum_to_if
#endif
/*
* For Roland devices, use the alternate setting which uses interrupt
* transfers for input.
......@@ -491,7 +507,7 @@ static usb_endpoint_descriptor_t* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi,
if (umidi->chip->dev->descriptor.idVendor != 0x0582)
return NULL;
intf = usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum);
intf = local_usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum);
if (!intf || intf->num_altsetting != 2)
return NULL;
......@@ -803,7 +819,7 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
memset(endpoints, 0, sizeof(*endpoints) * MIDI_MAX_ENDPOINTS);
intf = usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum);
intf = local_usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum);
if (!intf)
return -ENXIO;
intfd = &intf->altsetting[0];
......@@ -862,7 +878,7 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
usb_endpoint_descriptor_t* epd;
if (endpoint->epnum == -1) {
intf = usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum);
intf = local_usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum);
if (!intf || intf->num_altsetting < 1)
return -ENOENT;
intfd = intf->altsetting;
......
......@@ -60,7 +60,7 @@ struct usb_mixer_build {
unsigned char *buffer;
unsigned int buflen;
unsigned int ctrlif;
unsigned long unitbitmap[32/sizeof(unsigned long)];
DECLARE_BITMAP(unitbitmap, 32*32);
usb_audio_term_t oterm;
};
......@@ -1252,7 +1252,7 @@ static int parse_audio_unit(mixer_build_t *state, int unitid)
{
unsigned char *p1;
if (test_and_set_bit(unitid, &state->unitbitmap))
if (test_and_set_bit(unitid, state->unitbitmap))
return 0; /* the unit already visited */
p1 = find_audio_control_unit(state, unitid);
......@@ -1302,7 +1302,7 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif, unsigned char *buffe
while ((desc = snd_usb_find_csint_desc(buffer, buflen, desc, OUTPUT_TERMINAL, ctrlif, -1)) != NULL) {
if (desc[0] < 9)
continue; /* invalid descriptor? */
set_bit(desc[3], &state.unitbitmap); /* mark terminal ID as visited */
set_bit(desc[3], state.unitbitmap); /* mark terminal ID as visited */
state.oterm.id = desc[3];
state.oterm.type = combine_word(&desc[4]);
state.oterm.name = desc[8];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment