--- x/sound/usb/pcm.c +++ y/sound/usb/pcm.c @@ -1470,6 +1470,21 @@ static void fill_playback_urb_dsd_bitrev urb_ctx_queue_advance(subs, urb, bytes); } +static int copy_to_urb_prepare(struct snd_usb_substream *subs, struct urb *urb, + int offset, int stride, unsigned int bytes) +{ + if (subs->hwptr_done + bytes > subs->buffer_bytes) { + ; + } else { + struct snd_urb_ctx *ctx = urb->context; + + if (bytes > ctx->buffer_size || + offset > ctx->buffer_size - bytes) + return -EAGAIN; + } + return 0; +} + static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, int offset, int stride, unsigned int bytes) { @@ -1607,9 +1622,12 @@ static int prepare_playback_urb(struct s fill_playback_urb_dsd_bitrev(subs, urb, bytes); } else { /* usual PCM */ - if (!subs->tx_length_quirk) + if (!subs->tx_length_quirk) { + int ret = copy_to_urb_prepare(subs, urb, 0, stride, bytes); + if (ret) + return ret; copy_to_urb(subs, urb, 0, stride, bytes); - else + } else bytes = copy_to_urb_quirk(subs, urb, stride, bytes); /* bytes is now amount of outgoing data */ }