diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/card.c | 6 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 13 | ||||
-rw-r--r-- | sound/usb/endpoint.h | 1 | ||||
-rw-r--r-- | sound/usb/midi.c | 8 | ||||
-rw-r--r-- | sound/usb/pcm.c | 5 |
5 files changed, 27 insertions, 6 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 282f0fc9fed1..dbf7999d18b4 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
559 | return; | 559 | return; |
560 | 560 | ||
561 | card = chip->card; | 561 | card = chip->card; |
562 | mutex_lock(®ister_mutex); | ||
563 | down_write(&chip->shutdown_rwsem); | 562 | down_write(&chip->shutdown_rwsem); |
564 | chip->shutdown = 1; | 563 | chip->shutdown = 1; |
564 | up_write(&chip->shutdown_rwsem); | ||
565 | |||
566 | mutex_lock(®ister_mutex); | ||
565 | chip->num_interfaces--; | 567 | chip->num_interfaces--; |
566 | if (chip->num_interfaces <= 0) { | 568 | if (chip->num_interfaces <= 0) { |
567 | snd_card_disconnect(card); | 569 | snd_card_disconnect(card); |
@@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
582 | snd_usb_mixer_disconnect(p); | 584 | snd_usb_mixer_disconnect(p); |
583 | } | 585 | } |
584 | usb_chip[chip->index] = NULL; | 586 | usb_chip[chip->index] = NULL; |
585 | up_write(&chip->shutdown_rwsem); | ||
586 | mutex_unlock(®ister_mutex); | 587 | mutex_unlock(®ister_mutex); |
587 | snd_card_free_when_closed(card); | 588 | snd_card_free_when_closed(card); |
588 | } else { | 589 | } else { |
589 | up_write(&chip->shutdown_rwsem); | ||
590 | mutex_unlock(®ister_mutex); | 590 | mutex_unlock(®ister_mutex); |
591 | } | 591 | } |
592 | } | 592 | } |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7f78c6d782b0..34de6f2faf61 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #define EP_FLAG_ACTIVATED 0 | 36 | #define EP_FLAG_ACTIVATED 0 |
37 | #define EP_FLAG_RUNNING 1 | 37 | #define EP_FLAG_RUNNING 1 |
38 | #define EP_FLAG_STOPPING 2 | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * snd_usb_endpoint is a model that abstracts everything related to an | 41 | * snd_usb_endpoint is a model that abstracts everything related to an |
@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) | |||
502 | if (alive) | 503 | if (alive) |
503 | snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", | 504 | snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", |
504 | alive, ep->ep_num); | 505 | alive, ep->ep_num); |
506 | clear_bit(EP_FLAG_STOPPING, &ep->flags); | ||
505 | 507 | ||
506 | return 0; | 508 | return 0; |
507 | } | 509 | } |
508 | 510 | ||
511 | /* sync the pending stop operation; | ||
512 | * this function itself doesn't trigger the stop operation | ||
513 | */ | ||
514 | void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) | ||
515 | { | ||
516 | if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) | ||
517 | wait_clear_urbs(ep); | ||
518 | } | ||
519 | |||
509 | /* | 520 | /* |
510 | * unlink active urbs. | 521 | * unlink active urbs. |
511 | */ | 522 | */ |
@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
918 | 929 | ||
919 | if (wait) | 930 | if (wait) |
920 | wait_clear_urbs(ep); | 931 | wait_clear_urbs(ep); |
932 | else | ||
933 | set_bit(EP_FLAG_STOPPING, &ep->flags); | ||
921 | } | 934 | } |
922 | } | 935 | } |
923 | 936 | ||
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 6376ccf10fd4..3d4c9705041f 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h | |||
@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | |||
19 | int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); | 19 | int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); |
20 | void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | 20 | void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, |
21 | int force, int can_sleep, int wait); | 21 | int force, int can_sleep, int wait); |
22 | void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); | ||
22 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); | 23 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); |
23 | int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); | 24 | int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); |
24 | void snd_usb_endpoint_free(struct list_head *head); | 25 | void snd_usb_endpoint_free(struct list_head *head); |
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c83f6143c0eb..eeefbce3873c 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint { | |||
148 | struct snd_usb_midi_out_endpoint* ep; | 148 | struct snd_usb_midi_out_endpoint* ep; |
149 | struct snd_rawmidi_substream *substream; | 149 | struct snd_rawmidi_substream *substream; |
150 | int active; | 150 | int active; |
151 | bool autopm_reference; | ||
151 | uint8_t cable; /* cable number << 4 */ | 152 | uint8_t cable; /* cable number << 4 */ |
152 | uint8_t state; | 153 | uint8_t state; |
153 | #define STATE_UNKNOWN 0 | 154 | #define STATE_UNKNOWN 0 |
@@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) | |||
1076 | return -ENXIO; | 1077 | return -ENXIO; |
1077 | } | 1078 | } |
1078 | err = usb_autopm_get_interface(umidi->iface); | 1079 | err = usb_autopm_get_interface(umidi->iface); |
1079 | if (err < 0) | 1080 | port->autopm_reference = err >= 0; |
1081 | if (err < 0 && err != -EACCES) | ||
1080 | return -EIO; | 1082 | return -EIO; |
1081 | substream->runtime->private_data = port; | 1083 | substream->runtime->private_data = port; |
1082 | port->state = STATE_UNKNOWN; | 1084 | port->state = STATE_UNKNOWN; |
@@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) | |||
1087 | static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) | 1089 | static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) |
1088 | { | 1090 | { |
1089 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | 1091 | struct snd_usb_midi* umidi = substream->rmidi->private_data; |
1092 | struct usbmidi_out_port *port = substream->runtime->private_data; | ||
1090 | 1093 | ||
1091 | substream_open(substream, 0); | 1094 | substream_open(substream, 0); |
1092 | usb_autopm_put_interface(umidi->iface); | 1095 | if (port->autopm_reference) |
1096 | usb_autopm_put_interface(umidi->iface); | ||
1093 | return 0; | 1097 | return 0; |
1094 | } | 1098 | } |
1095 | 1099 | ||
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 37428f74dbb6..ef6fa24fc473 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -459,7 +459,7 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
459 | return ret; | 459 | return ret; |
460 | 460 | ||
461 | if (subs->sync_endpoint) | 461 | if (subs->sync_endpoint) |
462 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | 462 | ret = snd_usb_endpoint_set_params(subs->sync_endpoint, |
463 | subs->pcm_format, | 463 | subs->pcm_format, |
464 | subs->channels, | 464 | subs->channels, |
465 | subs->period_bytes, | 465 | subs->period_bytes, |
@@ -568,6 +568,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
568 | goto unlock; | 568 | goto unlock; |
569 | } | 569 | } |
570 | 570 | ||
571 | snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); | ||
572 | snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); | ||
573 | |||
571 | ret = set_format(subs, subs->cur_audiofmt); | 574 | ret = set_format(subs, subs->cur_audiofmt); |
572 | if (ret < 0) | 575 | if (ret < 0) |
573 | goto unlock; | 576 | goto unlock; |