lkml.org 
[lkml]   [2008]   [Aug]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 30/33] ALSA: Fix Oops with usb-audio reconnection
    2.6.25-stable review patch.  If anyone has any objections, please let us
    know.

    ------------------

    From: Takashi Iwai <tiwai@suse.de>

    Backport fixes for usb-audio Oops at reconnection.

    9eb70e6... [ALSA] usb-audio - Fix race in reconnection
    f18638d... [ALSA] Clean up snd_card_free*()
    73d38b1... [ALSA] Fix the race of card instance unregistration

    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    sound/core/init.c | 36 ++++++++++--------------
    sound/usb/usbaudio.c | 35 +++++++++++++++++------
    sound/usb/usbquirks.h | 75 +++++++++++++++++++++++++-------------------------
    3 files changed, 79 insertions(+), 67 deletions(-)

    --- a/sound/core/init.c
    +++ b/sound/core/init.c
    @@ -311,6 +311,9 @@ int snd_card_disconnect(struct snd_card
    struct file *file;
    int err;

    + if (!card)
    + return -EINVAL;
    +
    spin_lock(&card->files_lock);
    if (card->shutdown) {
    spin_unlock(&card->files_lock);
    @@ -322,6 +325,7 @@ int snd_card_disconnect(struct snd_card
    /* phase 1: disable fops (user space) operations for ALSA API */
    mutex_lock(&snd_card_mutex);
    snd_cards[card->number] = NULL;
    + snd_cards_lock &= ~(1 << card->number);
    mutex_unlock(&snd_card_mutex);

    /* phase 2: replace file->f_op with special dummy operations */
    @@ -360,6 +364,15 @@ int snd_card_disconnect(struct snd_card
    snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);

    snd_info_card_disconnect(card);
    +#ifndef CONFIG_SYSFS_DEPRECATED
    + if (card->card_dev) {
    + device_unregister(card->card_dev);
    + card->card_dev = NULL;
    + }
    +#endif
    +#ifdef CONFIG_PM
    + wake_up(&card->power_sleep);
    +#endif
    return 0;
    }

    @@ -401,33 +414,14 @@ static int snd_card_do_free(struct snd_c
    snd_printk(KERN_WARNING "unable to free card info\n");
    /* Not fatal error */
    }
    -#ifndef CONFIG_SYSFS_DEPRECATED
    - if (card->card_dev)
    - device_unregister(card->card_dev);
    -#endif
    kfree(card);
    return 0;
    }

    -static int snd_card_free_prepare(struct snd_card *card)
    -{
    - if (card == NULL)
    - return -EINVAL;
    - (void) snd_card_disconnect(card);
    - mutex_lock(&snd_card_mutex);
    - snd_cards[card->number] = NULL;
    - snd_cards_lock &= ~(1 << card->number);
    - mutex_unlock(&snd_card_mutex);
    -#ifdef CONFIG_PM
    - wake_up(&card->power_sleep);
    -#endif
    - return 0;
    -}
    -
    int snd_card_free_when_closed(struct snd_card *card)
    {
    int free_now = 0;
    - int ret = snd_card_free_prepare(card);
    + int ret = snd_card_disconnect(card);
    if (ret)
    return ret;

    @@ -447,7 +441,7 @@ EXPORT_SYMBOL(snd_card_free_when_closed)

    int snd_card_free(struct snd_card *card)
    {
    - int ret = snd_card_free_prepare(card);
    + int ret = snd_card_disconnect(card);
    if (ret)
    return ret;

    --- a/sound/usb/usbaudio.c
    +++ b/sound/usb/usbaudio.c
    @@ -1762,8 +1762,10 @@ static int check_hw_params_convention(st

    channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
    rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
    - if (!channels || !rates)
    + if (!channels || !rates) {
    + err = -ENOMEM;
    goto __out;
    + }

    list_for_each(p, &subs->fmt_list) {
    struct audioformat *f;
    @@ -1916,7 +1918,10 @@ static int setup_hw_info(struct snd_pcm_
    1000 * MIN_PACKS_URB,
    /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);

    - if (check_hw_params_convention(subs)) {
    + err = check_hw_params_convention(subs);
    + if (err < 0)
    + return err;
    + else if (err) {
    hwc_debug("setting extra hw constraints...\n");
    if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
    hw_rule_rate, subs,
    @@ -2463,11 +2468,12 @@ static int parse_audio_format_i_type(str
    }
    break;
    case USB_AUDIO_FORMAT_PCM8:
    - /* Dallas DS4201 workaround */
    + pcm_format = SNDRV_PCM_FORMAT_U8;
    +
    + /* Dallas DS4201 workaround: it advertises U8 format, but really
    + supports S8. */
    if (chip->usb_id == USB_ID(0x04fa, 0x4201))
    pcm_format = SNDRV_PCM_FORMAT_S8;
    - else
    - pcm_format = SNDRV_PCM_FORMAT_U8;
    break;
    case USB_AUDIO_FORMAT_IEEE_FLOAT:
    pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
    @@ -2671,12 +2677,23 @@ static int parse_audio_endpoints(struct
    int format;
    struct audioformat *fp;
    unsigned char *fmt, *csep;
    + int num;

    dev = chip->dev;

    /* parse the interface's altsettings */
    iface = usb_ifnum_to_if(dev, iface_no);
    - for (i = 0; i < iface->num_altsetting; i++) {
    +
    + num = iface->num_altsetting;
    +
    + /*
    + * Dallas DS4201 workaround: It presents 5 altsettings, but the last
    + * one misses syncpipe, and does not produce any sound.
    + */
    + if (chip->usb_id == USB_ID(0x04fa, 0x4201))
    + num = 4;
    +
    + for (i = 0; i < num; i++) {
    alts = &iface->altsetting[i];
    altsd = get_iface_desc(alts);
    /* skip invalid one */
    @@ -3406,7 +3423,6 @@ static void snd_usb_audio_create_proc(st

    static int snd_usb_audio_free(struct snd_usb_audio *chip)
    {
    - usb_chip[chip->index] = NULL;
    kfree(chip);
    return 0;
    }
    @@ -3600,8 +3616,8 @@ static void *snd_usb_audio_probe(struct
    snd_card_set_dev(chip->card, &intf->dev);
    break;
    }
    - if (! chip) {
    - snd_printk(KERN_ERR "no available usb audio device\n");
    + if (!chip) {
    + printk(KERN_ERR "no available usb audio device\n");
    goto __error;
    }
    }
    @@ -3671,6 +3687,7 @@ static void snd_usb_audio_disconnect(str
    list_for_each(p, &chip->mixer_list) {
    snd_usb_mixer_disconnect(p);
    }
    + usb_chip[chip->index] = NULL;
    mutex_unlock(&register_mutex);
    snd_card_free_when_closed(card);
    } else {
    --- a/sound/usb/usbquirks.h
    +++ b/sound/usb/usbquirks.h
    @@ -39,6 +39,30 @@
    .idProduct = prod, \
    .bInterfaceClass = USB_CLASS_VENDOR_SPEC

    +/* Creative/E-Mu devices */
    +{
    + USB_DEVICE(0x041e, 0x3010),
    + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
    + .vendor_name = "Creative Labs",
    + .product_name = "Sound Blaster MP3+",
    + .ifnum = QUIRK_NO_INTERFACE
    + }
    +},
    +{
    + /* E-Mu 0202 USB */
    + .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
    + .idVendor = 0x041e,
    + .idProduct = 0x3f02,
    + .bInterfaceClass = USB_CLASS_AUDIO,
    +},
    +{
    + /* E-Mu 0404 USB */
    + .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
    + .idVendor = 0x041e,
    + .idProduct = 0x3f04,
    + .bInterfaceClass = USB_CLASS_AUDIO,
    +},
    +
    /*
    * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
    * class matches do not take effect without an explicit ID match.
    @@ -97,19 +121,7 @@
    .bInterfaceClass = USB_CLASS_AUDIO,
    .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
    },
    -/* E-Mu devices */
    -{
    - .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
    - .idVendor = 0x041e,
    - .idProduct = 0x3f02,
    - .bInterfaceClass = USB_CLASS_AUDIO,
    -},
    -{
    - .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
    - .idVendor = 0x041e,
    - .idProduct = 0x3f04,
    - .bInterfaceClass = USB_CLASS_AUDIO,
    -},
    +
    /*
    * Yamaha devices
    */
    @@ -1165,19 +1177,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
    }
    }
    },
    -{
    - USB_DEVICE(0x582, 0x00a6),
    - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
    - .vendor_name = "Roland",
    - .product_name = "Juno-G",
    - .ifnum = 0,
    - .type = QUIRK_MIDI_FIXED_ENDPOINT,
    - .data = & (const struct snd_usb_midi_endpoint_info) {
    - .out_cables = 0x0001,
    - .in_cables = 0x0001
    - }
    - }
    -},
    { /*
    * This quirk is for the "Advanced" modes of the Edirol UA-25.
    * If the switch is not in an advanced setting, the UA-25 has
    @@ -1336,6 +1335,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
    },
    /* TODO: add Edirol MD-P1 support */
    {
    + USB_DEVICE(0x582, 0x00a6),
    + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
    + .vendor_name = "Roland",
    + .product_name = "Juno-G",
    + .ifnum = 0,
    + .type = QUIRK_MIDI_FIXED_ENDPOINT,
    + .data = & (const struct snd_usb_midi_endpoint_info) {
    + .out_cables = 0x0001,
    + .in_cables = 0x0001
    + }
    + }
    +},
    +{
    /* Roland SH-201 */
    USB_DEVICE(0x0582, 0x00ad),
    .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
    @@ -1719,17 +1731,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
    }
    },

    -{
    - /* Creative Sound Blaster MP3+ */
    - USB_DEVICE(0x041e, 0x3010),
    - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
    - .vendor_name = "Creative Labs",
    - .product_name = "Sound Blaster MP3+",
    - .ifnum = QUIRK_NO_INTERFACE
    - }
    -
    -},
    -
    /* Emagic devices */
    {
    USB_DEVICE(0x086a, 0x0001),
    --


    \
     
     \ /
      Last update: 2008-08-04 22:35    [W:0.045 / U:31.288 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site