diff options
Diffstat (limited to 'sound/usb/endpoint.c')
| -rw-r--r-- | sound/usb/endpoint.c | 43 | 
1 files changed, 18 insertions, 25 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 419302e2057e..a385e85c4650 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -455,8 +455,8 @@ static void push_back_to_ready_list(struct snd_usb_endpoint *ep,   * This function is used both for implicit feedback endpoints and in low-   * latency playback mode.   */ -void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, -				       bool in_stream_lock) +int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, +				      bool in_stream_lock)  {  	bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep); @@ -480,7 +480,7 @@ void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,  		spin_unlock_irqrestore(&ep->lock, flags);  		if (ctx == NULL) -			return; +			break;  		/* copy over the length information */  		if (implicit_fb) { @@ -495,11 +495,14 @@ void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,  			break;  		if (err < 0) {  			/* push back to ready list again for -EAGAIN */ -			if (err == -EAGAIN) +			if (err == -EAGAIN) {  				push_back_to_ready_list(ep, ctx); -			else +				break; +			} + +			if (!in_stream_lock)  				notify_xrun(ep); -			return; +			return -EPIPE;  		}  		err = usb_submit_urb(ctx->urb, GFP_ATOMIC); @@ -507,13 +510,16 @@ void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,  			usb_audio_err(ep->chip,  				      "Unable to submit urb #%d: %d at %s\n",  				      ctx->index, err, __func__); -			notify_xrun(ep); -			return; +			if (!in_stream_lock) +				notify_xrun(ep); +			return -EPIPE;  		}  		set_bit(ctx->index, &ep->active_mask);  		atomic_inc(&ep->submitted_urbs);  	} + +	return 0;  }  /* @@ -910,8 +916,9 @@ static int endpoint_set_interface(struct snd_usb_audio *chip,  		      ep->iface, altset, ep->ep_num);  	err = usb_set_interface(chip->dev, ep->iface, altset);  	if (err < 0) { -		usb_audio_err(chip, "%d:%d: usb_set_interface failed (%d)\n", -			      ep->iface, altset, err); +		usb_audio_err_ratelimited( +			chip, "%d:%d: usb_set_interface failed (%d)\n", +			ep->iface, altset, err);  		return err;  	} @@ -1173,22 +1180,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)  	 */  	if (usb_pipein(ep->pipe) || ep->implicit_fb_sync) { -		urb_packs = packs_per_ms; -		/* -		 * Wireless devices can poll at a max rate of once per 4ms. -		 * For dataintervals less than 5, increase the packet count to -		 * allow the host controller to use bursting to fill in the -		 * gaps. -		 */ -		if (snd_usb_get_speed(chip->dev) == USB_SPEED_WIRELESS) { -			int interval = ep->datainterval; -			while (interval < 5) { -				urb_packs <<= 1; -				++interval; -			} -		}  		/* make capture URBs <= 1 ms and smaller than a period */ -		urb_packs = min(max_packs_per_urb, urb_packs); +		urb_packs = min(max_packs_per_urb, packs_per_ms);  		while (urb_packs > 1 && urb_packs * maxsize >= ep->cur_period_bytes)  			urb_packs >>= 1;  		ep->nurbs = MAX_URBS;  |