Commit f240406babfe1526998e10583ea5eccc2676a433

Authored by Jaroslav Kysela
1 parent 4d96eb255c

ALSA: pcm_lib - cleanup & merge hw_ptr update functions

Do general cleanup in snd_pcm_update_hw_ptr*() routines and merge them.
The main change is hw_ptr_interrupt variable removal to simplify code
logic. This variable can be computed directly from hw_ptr.

Ensure that updated hw_ptr is not lower than previous one (it was possible
with old code in some obscure situations when interrupt was delayed or
the lowlevel driver returns wrong ring buffer position value).

Signed-off-by: Jaroslav Kysela <perex@perex.cz>

Showing 5 changed files with 121 additions and 195 deletions Side-by-side Diff

... ... @@ -271,7 +271,6 @@
271 271 int overrange;
272 272 snd_pcm_uframes_t avail_max;
273 273 snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
274   - snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
275 274 unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
276 275 snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
277 276  
include/sound/pcm_oss.h
... ... @@ -61,7 +61,7 @@
61 61 struct snd_pcm_plugin *plugin_first;
62 62 struct snd_pcm_plugin *plugin_last;
63 63 #endif
64   - unsigned int prev_hw_ptr_interrupt;
  64 + unsigned int prev_hw_ptr_period;
65 65 };
66 66  
67 67 struct snd_pcm_oss_file {
sound/core/oss/pcm_oss.c
... ... @@ -632,6 +632,13 @@
632 632 return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
633 633 }
634 634  
  635 +static inline
  636 +snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
  637 +{
  638 + snd_pcm_uframes_t ptr = runtime->status->hw_ptr;
  639 + return ptr - (ptr % runtime->period_size);
  640 +}
  641 +
635 642 /* define extended formats in the recent OSS versions (if any) */
636 643 /* linear formats */
637 644 #define AFMT_S32_LE 0x00001000
... ... @@ -1102,7 +1109,7 @@
1102 1109 return err;
1103 1110 }
1104 1111 runtime->oss.prepare = 0;
1105   - runtime->oss.prev_hw_ptr_interrupt = 0;
  1112 + runtime->oss.prev_hw_ptr_period = 0;
1106 1113 runtime->oss.period_ptr = 0;
1107 1114 runtime->oss.buffer_used = 0;
1108 1115  
... ... @@ -1950,7 +1957,8 @@
1950 1957 return result;
1951 1958 }
1952 1959  
1953   -static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr)
  1960 +static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream,
  1961 + snd_pcm_uframes_t hw_ptr)
1954 1962 {
1955 1963 struct snd_pcm_runtime *runtime = substream->runtime;
1956 1964 snd_pcm_uframes_t appl_ptr;
... ... @@ -1986,7 +1994,8 @@
1986 1994 if (runtime->oss.trigger)
1987 1995 goto _skip1;
1988 1996 if (atomic_read(&psubstream->mmap_count))
1989   - snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);
  1997 + snd_pcm_oss_simulate_fill(psubstream,
  1998 + get_hw_ptr_period(runtime));
1990 1999 runtime->oss.trigger = 1;
1991 2000 runtime->start_threshold = 1;
1992 2001 cmd = SNDRV_PCM_IOCTL_START;
1993 2002  
... ... @@ -2105,11 +2114,12 @@
2105 2114 info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
2106 2115 if (atomic_read(&substream->mmap_count)) {
2107 2116 snd_pcm_sframes_t n;
2108   - n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;
  2117 + delay = get_hw_ptr_period(runtime);
  2118 + n = delay - runtime->oss.prev_hw_ptr_period;
2109 2119 if (n < 0)
2110 2120 n += runtime->boundary;
2111 2121 info.blocks = n / runtime->period_size;
2112   - runtime->oss.prev_hw_ptr_interrupt = delay;
  2122 + runtime->oss.prev_hw_ptr_period = delay;
2113 2123 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2114 2124 snd_pcm_oss_simulate_fill(substream, delay);
2115 2125 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
2116 2126  
2117 2127  
2118 2128  
... ... @@ -2673,18 +2683,22 @@
2673 2683 {
2674 2684 struct snd_pcm_runtime *runtime = substream->runtime;
2675 2685 if (atomic_read(&substream->mmap_count))
2676   - return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
  2686 + return runtime->oss.prev_hw_ptr_period !=
  2687 + get_hw_ptr_period(runtime);
2677 2688 else
2678   - return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
  2689 + return snd_pcm_playback_avail(runtime) >=
  2690 + runtime->oss.period_frames;
2679 2691 }
2680 2692  
2681 2693 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
2682 2694 {
2683 2695 struct snd_pcm_runtime *runtime = substream->runtime;
2684 2696 if (atomic_read(&substream->mmap_count))
2685   - return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
  2697 + return runtime->oss.prev_hw_ptr_period !=
  2698 + get_hw_ptr_period(runtime);
2686 2699 else
2687   - return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
  2700 + return snd_pcm_capture_avail(runtime) >=
  2701 + runtime->oss.period_frames;
2688 2702 }
2689 2703  
2690 2704 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
sound/core/pcm_lib.c
... ... @@ -172,6 +172,7 @@
172 172 #define hw_ptr_error(substream, fmt, args...) \
173 173 do { \
174 174 if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \
  175 + xrun_log_show(substream); \
175 176 if (printk_ratelimit()) { \
176 177 snd_printd("PCM: " fmt, ##args); \
177 178 } \
... ... @@ -188,7 +189,6 @@
188 189 snd_pcm_uframes_t buffer_size;
189 190 snd_pcm_uframes_t old_hw_ptr;
190 191 snd_pcm_uframes_t hw_ptr_base;
191   - snd_pcm_uframes_t hw_ptr_interrupt;
192 192 };
193 193  
194 194 struct snd_pcm_hwptr_log {
... ... @@ -220,7 +220,6 @@
220 220 entry->buffer_size = runtime->buffer_size;;
221 221 entry->old_hw_ptr = runtime->status->hw_ptr;
222 222 entry->hw_ptr_base = runtime->hw_ptr_base;
223   - entry->hw_ptr_interrupt = runtime->hw_ptr_interrupt;;
224 223 log->idx = (log->idx + 1) % XRUN_LOG_CNT;
225 224 }
226 225  
227 226  
... ... @@ -241,14 +240,13 @@
241 240 entry = &log->entries[idx];
242 241 if (entry->period_size == 0)
243 242 break;
244   - snd_printd("hwptr log: %s: j=%lu, pos=0x%lx/0x%lx/0x%lx, "
245   - "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
  243 + snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, "
  244 + "hwptr=%ld/%ld\n",
246 245 name, entry->jiffies, (unsigned long)entry->pos,
247 246 (unsigned long)entry->period_size,
248 247 (unsigned long)entry->buffer_size,
249 248 (unsigned long)entry->old_hw_ptr,
250   - (unsigned long)entry->hw_ptr_base,
251   - (unsigned long)entry->hw_ptr_interrupt);
  249 + (unsigned long)entry->hw_ptr_base);
252 250 idx++;
253 251 idx %= XRUN_LOG_CNT;
254 252 }
... ... @@ -265,33 +263,6 @@
265 263  
266 264 #endif
267 265  
268   -static snd_pcm_uframes_t
269   -snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
270   - struct snd_pcm_runtime *runtime)
271   -{
272   - snd_pcm_uframes_t pos;
273   -
274   - pos = substream->ops->pointer(substream);
275   - if (pos == SNDRV_PCM_POS_XRUN)
276   - return pos; /* XRUN */
277   - if (pos >= runtime->buffer_size) {
278   - if (printk_ratelimit()) {
279   - char name[16];
280   - pcm_debug_name(substream, name, sizeof(name));
281   - xrun_log_show(substream);
282   - snd_printd(KERN_ERR "BUG: %s, pos = 0x%lx, "
283   - "buffer size = 0x%lx, period size = 0x%lx\n",
284   - name, pos, runtime->buffer_size,
285   - runtime->period_size);
286   - }
287   - pos = 0;
288   - }
289   - pos -= pos % runtime->min_align;
290   - if (xrun_debug(substream, XRUN_DEBUG_LOG))
291   - xrun_log(substream, pos);
292   - return pos;
293   -}
294   -
295 266 static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
296 267 struct snd_pcm_runtime *runtime)
297 268 {
298 269  
299 270  
300 271  
301 272  
302 273  
303 274  
304 275  
... ... @@ -319,72 +290,88 @@
319 290 return 0;
320 291 }
321 292  
322   -static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
  293 +static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
  294 + unsigned int in_interrupt)
323 295 {
324 296 struct snd_pcm_runtime *runtime = substream->runtime;
325 297 snd_pcm_uframes_t pos;
326   - snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base;
  298 + snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
327 299 snd_pcm_sframes_t hdelta, delta;
328 300 unsigned long jdelta;
329 301  
330 302 old_hw_ptr = runtime->status->hw_ptr;
331   - pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
  303 + pos = substream->ops->pointer(substream);
332 304 if (pos == SNDRV_PCM_POS_XRUN) {
333 305 xrun(substream);
334 306 return -EPIPE;
335 307 }
336   - if (xrun_debug(substream, XRUN_DEBUG_PERIODUPDATE)) {
337   - char name[16];
338   - pcm_debug_name(substream, name, sizeof(name));
339   - snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
340   - "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
341   - name, (unsigned int)pos,
342   - (unsigned int)runtime->period_size,
343   - (unsigned int)runtime->buffer_size,
344   - (unsigned long)old_hw_ptr,
345   - (unsigned long)runtime->hw_ptr_base,
346   - (unsigned long)runtime->hw_ptr_interrupt);
  308 + if (pos >= runtime->buffer_size) {
  309 + if (printk_ratelimit()) {
  310 + char name[16];
  311 + pcm_debug_name(substream, name, sizeof(name));
  312 + xrun_log_show(substream);
  313 + snd_printd(KERN_ERR "BUG: %s, pos = %ld, "
  314 + "buffer size = %ld, period size = %ld\n",
  315 + name, pos, runtime->buffer_size,
  316 + runtime->period_size);
  317 + }
  318 + pos = 0;
347 319 }
  320 + pos -= pos % runtime->min_align;
  321 + if (xrun_debug(substream, XRUN_DEBUG_LOG))
  322 + xrun_log(substream, pos);
348 323 hw_base = runtime->hw_ptr_base;
349 324 new_hw_ptr = hw_base + pos;
350   - hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
351   - delta = new_hw_ptr - hw_ptr_interrupt;
352   - if (hw_ptr_interrupt >= runtime->boundary) {
353   - hw_ptr_interrupt -= runtime->boundary;
354   - if (hw_base < runtime->boundary / 2)
355   - /* hw_base was already lapped; recalc delta */
356   - delta = new_hw_ptr - hw_ptr_interrupt;
357   - }
358   - if (delta < 0) {
359   - if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
360   - delta += runtime->buffer_size;
361   - if (delta < 0) {
362   - xrun_log_show(substream);
363   - hw_ptr_error(substream,
364   - "Unexpected hw_pointer value "
365   - "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
366   - substream->stream, (long)pos,
367   - (long)hw_ptr_interrupt);
368   -#if 1
369   - /* simply skipping the hwptr update seems more
370   - * robust in some cases, e.g. on VMware with
371   - * inaccurate timer source
372   - */
373   - return 0; /* skip this update */
374   -#else
375   - /* rebase to interrupt position */
376   - hw_base = new_hw_ptr = hw_ptr_interrupt;
377   - /* align hw_base to buffer_size */
378   - hw_base -= hw_base % runtime->buffer_size;
379   - delta = 0;
380   -#endif
381   - } else {
  325 + if (in_interrupt) {
  326 + /* we know that one period was processed */
  327 + /* delta = "expected next hw_ptr" for in_interrupt != 0 */
  328 + delta = old_hw_ptr - (old_hw_ptr % runtime->period_size)
  329 + + runtime->period_size;
  330 + if (delta > new_hw_ptr) {
382 331 hw_base += runtime->buffer_size;
383 332 if (hw_base >= runtime->boundary)
384 333 hw_base = 0;
385 334 new_hw_ptr = hw_base + pos;
  335 + goto __delta;
386 336 }
387 337 }
  338 + /* new_hw_ptr might be lower than old_hw_ptr in case when */
  339 + /* pointer crosses the end of the ring buffer */
  340 + if (new_hw_ptr < old_hw_ptr) {
  341 + hw_base += runtime->buffer_size;
  342 + if (hw_base >= runtime->boundary)
  343 + hw_base = 0;
  344 + new_hw_ptr = hw_base + pos;
  345 + }
  346 + __delta:
  347 + delta = (new_hw_ptr - old_hw_ptr) % runtime->boundary;
  348 + if (xrun_debug(substream, in_interrupt ?
  349 + XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
  350 + char name[16];
  351 + pcm_debug_name(substream, name, sizeof(name));
  352 + snd_printd("%s_update: %s: pos=%u/%u/%u, "
  353 + "hwptr=%ld/%ld/%ld/%ld\n",
  354 + in_interrupt ? "period" : "hwptr",
  355 + name,
  356 + (unsigned int)pos,
  357 + (unsigned int)runtime->period_size,
  358 + (unsigned int)runtime->buffer_size,
  359 + (unsigned long)delta,
  360 + (unsigned long)old_hw_ptr,
  361 + (unsigned long)new_hw_ptr,
  362 + (unsigned long)runtime->hw_ptr_base);
  363 + }
  364 + /* something must be really wrong */
  365 + if (delta >= runtime->buffer_size) {
  366 + hw_ptr_error(substream,
  367 + "Unexpected hw_pointer value %s"
  368 + "(stream=%i, pos=%ld, new_hw_ptr=%ld, "
  369 + "old_hw_ptr=%ld)\n",
  370 + in_interrupt ? "[Q] " : "[P]",
  371 + substream->stream, (long)pos,
  372 + (long)new_hw_ptr, (long)old_hw_ptr);
  373 + return 0;
  374 + }
388 375  
389 376 /* Do jiffies check only in xrun_debug mode */
390 377 if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK))
... ... @@ -396,7 +383,7 @@
396 383 */
397 384 if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
398 385 goto no_jiffies_check;
399   - hdelta = new_hw_ptr - old_hw_ptr;
  386 + hdelta = delta;
400 387 if (hdelta < runtime->delay)
401 388 goto no_jiffies_check;
402 389 hdelta -= runtime->delay;
403 390  
404 391  
405 392  
406 393  
407 394  
408 395  
409 396  
410 397  
411 398  
... ... @@ -405,45 +392,49 @@
405 392 delta = jdelta /
406 393 (((runtime->period_size * HZ) / runtime->rate)
407 394 + HZ/100);
408   - xrun_log_show(substream);
  395 + /* move new_hw_ptr according jiffies not pos variable */
  396 + new_hw_ptr = old_hw_ptr;
  397 + /* use loop to avoid checks for delta overflows */
  398 + /* the delta value is small or zero in most cases */
  399 + while (delta > 0) {
  400 + new_hw_ptr += runtime->period_size;
  401 + if (new_hw_ptr >= runtime->boundary)
  402 + new_hw_ptr -= runtime->boundary;
  403 + delta--;
  404 + }
  405 + /* align hw_base to buffer_size */
  406 + hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size);
  407 + delta = 0;
409 408 hw_ptr_error(substream,
410   - "hw_ptr skipping! [Q] "
  409 + "hw_ptr skipping! %s"
411 410 "(pos=%ld, delta=%ld, period=%ld, "
412   - "jdelta=%lu/%lu/%lu)\n",
  411 + "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n",
  412 + in_interrupt ? "[Q] " : "",
413 413 (long)pos, (long)hdelta,
414 414 (long)runtime->period_size, jdelta,
415   - ((hdelta * HZ) / runtime->rate), delta);
416   - hw_ptr_interrupt = runtime->hw_ptr_interrupt +
417   - runtime->period_size * delta;
418   - if (hw_ptr_interrupt >= runtime->boundary)
419   - hw_ptr_interrupt -= runtime->boundary;
420   - /* rebase to interrupt position */
421   - hw_base = new_hw_ptr = hw_ptr_interrupt;
422   - /* align hw_base to buffer_size */
423   - hw_base -= hw_base % runtime->buffer_size;
424   - delta = 0;
  415 + ((hdelta * HZ) / runtime->rate), delta,
  416 + (unsigned long)old_hw_ptr,
  417 + (unsigned long)new_hw_ptr);
425 418 }
426 419 no_jiffies_check:
427 420 if (delta > runtime->period_size + runtime->period_size / 2) {
428   - xrun_log_show(substream);
429 421 hw_ptr_error(substream,
430   - "Lost interrupts? "
431   - "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
  422 + "Lost interrupts? %s"
  423 + "(stream=%i, delta=%ld, new_hw_ptr=%ld, "
  424 + "old_hw_ptr=%ld)\n",
  425 + in_interrupt ? "[Q] " : "",
432 426 substream->stream, (long)delta,
433   - (long)hw_ptr_interrupt);
434   - /* rebase hw_ptr_interrupt */
435   - hw_ptr_interrupt =
436   - new_hw_ptr - new_hw_ptr % runtime->period_size;
  427 + (long)new_hw_ptr,
  428 + (long)old_hw_ptr);
437 429 }
438   - runtime->hw_ptr_interrupt = hw_ptr_interrupt;
439 430  
  431 + if (runtime->status->hw_ptr == new_hw_ptr)
  432 + return 0;
  433 +
440 434 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
441 435 runtime->silence_size > 0)
442 436 snd_pcm_playback_silence(substream, new_hw_ptr);
443 437  
444   - if (runtime->status->hw_ptr == new_hw_ptr)
445   - return 0;
446   -
447 438 runtime->hw_ptr_base = hw_base;
448 439 runtime->status->hw_ptr = new_hw_ptr;
449 440 runtime->hw_ptr_jiffies = jiffies;
... ... @@ -456,83 +447,7 @@
456 447 /* CAUTION: call it with irq disabled */
457 448 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
458 449 {
459   - struct snd_pcm_runtime *runtime = substream->runtime;
460   - snd_pcm_uframes_t pos;
461   - snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
462   - snd_pcm_sframes_t delta;
463   - unsigned long jdelta;
464   -
465   - old_hw_ptr = runtime->status->hw_ptr;
466   - pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
467   - if (pos == SNDRV_PCM_POS_XRUN) {
468   - xrun(substream);
469   - return -EPIPE;
470   - }
471   - if (xrun_debug(substream, XRUN_DEBUG_HWPTRUPDATE)) {
472   - char name[16];
473   - pcm_debug_name(substream, name, sizeof(name));
474   - snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
475   - "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
476   - name, (unsigned int)pos,
477   - (unsigned int)runtime->period_size,
478   - (unsigned int)runtime->buffer_size,
479   - (unsigned long)old_hw_ptr,
480   - (unsigned long)runtime->hw_ptr_base,
481   - (unsigned long)runtime->hw_ptr_interrupt);
482   - }
483   -
484   - hw_base = runtime->hw_ptr_base;
485   - new_hw_ptr = hw_base + pos;
486   -
487   - delta = new_hw_ptr - old_hw_ptr;
488   - jdelta = jiffies - runtime->hw_ptr_jiffies;
489   - if (delta < 0) {
490   - delta += runtime->buffer_size;
491   - if (delta < 0) {
492   - xrun_log_show(substream);
493   - hw_ptr_error(substream,
494   - "Unexpected hw_pointer value [2] "
495   - "(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n",
496   - substream->stream, (long)pos,
497   - (long)old_hw_ptr, jdelta);
498   - return 0;
499   - }
500   - hw_base += runtime->buffer_size;
501   - if (hw_base >= runtime->boundary)
502   - hw_base = 0;
503   - new_hw_ptr = hw_base + pos;
504   - }
505   - /* Do jiffies check only in xrun_debug mode */
506   - if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK))
507   - goto no_jiffies_check;
508   - if (delta < runtime->delay)
509   - goto no_jiffies_check;
510   - delta -= runtime->delay;
511   - if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
512   - xrun_log_show(substream);
513   - hw_ptr_error(substream,
514   - "hw_ptr skipping! "
515   - "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
516   - (long)pos, (long)delta,
517   - (long)runtime->period_size, jdelta,
518   - ((delta * HZ) / runtime->rate));
519   - return 0;
520   - }
521   - no_jiffies_check:
522   - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
523   - runtime->silence_size > 0)
524   - snd_pcm_playback_silence(substream, new_hw_ptr);
525   -
526   - if (runtime->status->hw_ptr == new_hw_ptr)
527   - return 0;
528   -
529   - runtime->hw_ptr_base = hw_base;
530   - runtime->status->hw_ptr = new_hw_ptr;
531   - runtime->hw_ptr_jiffies = jiffies;
532   - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
533   - snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
534   -
535   - return snd_pcm_update_hw_ptr_post(substream, runtime);
  450 + return snd_pcm_update_hw_ptr0(substream, 0);
536 451 }
537 452  
538 453 /**
... ... @@ -1744,7 +1659,7 @@
1744 1659  
1745 1660 snd_pcm_stream_lock_irqsave(substream, flags);
1746 1661 if (!snd_pcm_running(substream) ||
1747   - snd_pcm_update_hw_ptr_interrupt(substream) < 0)
  1662 + snd_pcm_update_hw_ptr0(substream, 1) < 0)
1748 1663 goto _end;
1749 1664  
1750 1665 if (substream->timer_running)
sound/core/pcm_native.c
... ... @@ -1247,8 +1247,6 @@
1247 1247 if (err < 0)
1248 1248 return err;
1249 1249 runtime->hw_ptr_base = 0;
1250   - runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
1251   - runtime->status->hw_ptr % runtime->period_size;
1252 1250 runtime->silence_start = runtime->status->hw_ptr;
1253 1251 runtime->silence_filled = 0;
1254 1252 return 0;