if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
                        diff += runtime->boundary;
                if (diff < 0)
-                       return -EINVAL;
+                       return -EPIPE;
                rec->sw_ready += (int)frames_to_bytes(runtime, diff);
                rec->appl_ptr = appl_ptr;
        }
                                  struct snd_pcm_indirect *rec, unsigned int ptr)
 {
        int bytes = ptr - rec->hw_io;
+       int err;
+
        if (bytes < 0)
                bytes += rec->hw_buffer_size;
        rec->hw_io = ptr;
        rec->sw_io += bytes;
        if (rec->sw_io >= rec->sw_buffer_size)
                rec->sw_io -= rec->sw_buffer_size;
-       if (substream->ops->ack)
-               substream->ops->ack(substream);
+       if (substream->ops->ack) {
+               err = substream->ops->ack(substream);
+               if (err == -EPIPE)
+                       return SNDRV_PCM_POS_XRUN;
+       }
        return bytes_to_frames(substream->runtime, rec->sw_io);
 }
 
                if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
                        diff += runtime->boundary;
                if (diff < 0)
-                       return -EINVAL;
+                       return -EPIPE;
                rec->sw_ready -= frames_to_bytes(runtime, diff);
                rec->appl_ptr = appl_ptr;
        }
 {
        int qsize;
        int bytes = ptr - rec->hw_io;
+       int err;
+
        if (bytes < 0)
                bytes += rec->hw_buffer_size;
        rec->hw_io = ptr;
        rec->sw_io += bytes;
        if (rec->sw_io >= rec->sw_buffer_size)
                rec->sw_io -= rec->sw_buffer_size;
-       if (substream->ops->ack)
-               substream->ops->ack(substream);
+       if (substream->ops->ack) {
+               err = substream->ops->ack(substream);
+               if (err == -EPIPE)
+                       return SNDRV_PCM_POS_XRUN;
+       }
        return bytes_to_frames(substream->runtime, rec->sw_io);
 }