Am Montag, 21. November 2011, 05:53:15 schrieb Amit Nagal: > Thank you for sharing very useful insights . > Actually in my embedded target , usb audio modules after probe is > finished , gets unbind . > when i investigated , the reason is usb reset . > i am debugging now to know whether this usb reset has come from > userspace or from some other driver . Well, that is not productive. The reset may be issued for a perfectly valid reason and be necessary. It would be far better if the audio driver handled a reset correctly. Could you test this patch? Regards Oliver >From 4bf7335b3fb573846f8662ed5050fee8502d5da5 Mon Sep 17 00:00:00 2001 From: Oliver Neukum <oliver@xxxxxxxxxx> Date: Mon, 21 Nov 2011 08:31:23 +0100 Subject: [PATCH] usb-audio: Add reset handler This is needed on system which share audio interfaces and other interfaces whose drivers use reset in error handling. Signed-off-by: Oliver Neukum <oneukum@xxxxxxx> --- sound/usb/card.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 53 insertions(+), 9 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 0f6dc0d..f38efc0 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -604,6 +604,21 @@ static void usb_audio_disconnect(struct usb_interface *intf) usb_get_intfdata(intf)); } +static void suspend_interfaces(struct snd_usb_audio *chip) +{ + struct list_head *p; + struct snd_usb_stream *as; + + snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); + if (!chip->num_suspended_intf++) { + list_for_each(p, &chip->pcm_list) { + as = list_entry(p, struct snd_usb_stream, list); + snd_pcm_suspend_all(as->pcm); + } + } +} + + #ifdef CONFIG_PM int snd_usb_autoresume(struct snd_usb_audio *chip) @@ -625,21 +640,13 @@ void snd_usb_autosuspend(struct snd_usb_audio *chip) static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) { struct snd_usb_audio *chip = usb_get_intfdata(intf); - struct list_head *p; - struct snd_usb_stream *as; struct usb_mixer_interface *mixer; if (chip == (void *)-1L) return 0; if (!PMSG_IS_AUTO(message)) { - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - if (!chip->num_suspended_intf++) { - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - snd_pcm_suspend_all(as->pcm); - } - } + suspend_interfaces(chip); } else { /* * otherwise we keep the rest of the system in the dark @@ -695,6 +702,41 @@ static struct usb_device_id usb_audio_ids [] = { { } /* Terminating entry */ }; +static int usb_audo_pre_reset(struct usb_interface *intf) +{ + struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct usb_mixer_interface *mixer; + + if (chip == (void *)-1L) + return 0; + + list_for_each_entry(mixer, &chip->mixer_list, list) + snd_usb_mixer_inactivate(mixer); + return 0; +} + +static int usb_audio_post_reset(struct usb_interface *intf) +{ + struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct usb_mixer_interface *mixer; + int err; + + if (chip == (void *)-1L) + return 0; + + list_for_each_entry(mixer, &chip->mixer_list, list) { + err = snd_usb_mixer_activate(mixer); + if (err < 0) + goto err_out; + } + snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); + + return 0; + +err_out: + return -EIO; +} + MODULE_DEVICE_TABLE (usb, usb_audio_ids); /* @@ -707,6 +749,8 @@ static struct usb_driver usb_audio_driver = { .disconnect = usb_audio_disconnect, .suspend = usb_audio_suspend, .resume = usb_audio_resume, + .pre_reset = usb_audo_pre_reset, + .post_reset = usb_audio_post_reset, .id_table = usb_audio_ids, .supports_autosuspend = 1, }; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html