Repository navigation
Commit f28036f
committed
fixup! ASoC: SOF: sof-audio: harden recursive widget free walk
Revert the sink-path traversal changes, keeping only the NULL spipe /
pipe_widget checks in sof_widget_free_unlocked().
path->walking is DFS stack state: it means "this edge is currently being
walked", and it has to be unwound by whoever set it. Not clearing it
after the recursive call makes it a permanent 'visited' mark, so the FREE
walk traverses a different set of edges than the SETUP walk, which
unbalances swidget->use_count:
- sof_walk_widgets_in_order() starts a walk from every aif_in (playback)
or every dai_out/output (capture) widget in the list. With aggregated
DAIs the branches reconverge on the shared widgets towards the FE.
SETUP walks and increments them once per branch, but on FREE the first
branch leaves the shared edges marked and the second branch skips them
entirely, so use_count never reaches 0. The widget_free IPC is then
never sent, the cores are never put and spipe->complete is never
cleared: the DSP side leaks and the next stream reuses a widget that
was never re-configured.
- The same happens within a single walk whenever two branches of the
list reconverge, as the shared edge below the merge point must be
walked once per incoming branch.
Clearing the flags after the loop cannot fix either case, and doing it
for both directions of every widget in the list is unsafe on its own:
walking is owned by the walk in progress, and the free walk does not hold
the DAPM mutex, so a concurrent dapm_power_widgets() may have those same
edges on its stack.
The rest of the traversal churn is not needed either. FREE only sends
IPC, it never removes DAPM paths, so the _safe iterator has nothing to
protect against here - and against a concurrent topology teardown it
would not help, as next_p is read before the recursion. p->sink cannot be
NULL for a linked path, and the list can never be NULL as
sof_widget_list_free() already checks it.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
=== everything below is dropped by 'git rebase --autosquash' ===
Once squashed, the only thing left of the original commit are the three
hunks in sof_widget_free_unlocked(); the traversal is byte identical to
the pre-2712ab5d30d6 state. The original subject no longer describes the
patch, so use this message for the squashed commit:
ASoC: SOF: sof-audio: do not dereference swidget->spipe unconditionally on free
sof_widget_free_unlocked() dereferences swidget->spipe without checking
it for two things: swidget->spipe->complete for a scheduler widget, and
swidget->spipe->pipe_widget for the recursive free of the pipeline's
scheduler widget. Both can be reached with spipe or pipe_widget not
set, which oopses in the free path - where there is nothing left to
bail out to.
Check both before use and cache swidget->spipe in the local spipe
variable that is already there. A widget with no pipeline has nothing
to put or complete, and no scheduler widget to free, so skipping is the
correct behaviour.
No functional change for a widget that was successfully set up:
sof_widget_setup_unlocked() already rejects a dynamic pipeline widget
with no spipe or no spipe->pipe_widget with -EINVAL.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Two things to resolve before sending it out:
- The oops was most likely hit via the compress free path
(ipc4-compress.c sof_widget_list_free()), but the details were not
recovered. Replace "can be reached with spipe or pipe_widget not set"
with the actual path and add a Fixes: tag once known.
- If it cannot be reproduced, drop the patch instead: as the last
paragraph shows, the guards are unreachable for any widget that went
through sof_widget_setup_unlocked().1 parent 9f82f2a commit f28036f
1 file changed
Lines changed: 7 additions & 46 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
547 | 547 | | |
548 | 548 | | |
549 | 549 | | |
550 | | - | |
551 | | - | |
552 | | - | |
553 | | - | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
554 | 553 | | |
| 554 | + | |
555 | 555 | | |
556 | 556 | | |
557 | | - | |
558 | 557 | | |
559 | 558 | | |
560 | 559 | | |
561 | | - | |
562 | | - | |
563 | | - | |
564 | 560 | | |
565 | 561 | | |
566 | 562 | | |
| |||
580 | 576 | | |
581 | 577 | | |
582 | 578 | | |
583 | | - | |
| 579 | + | |
584 | 580 | | |
585 | | - | |
586 | | - | |
587 | | - | |
588 | 581 | | |
589 | 582 | | |
590 | 583 | | |
591 | 584 | | |
592 | 585 | | |
593 | | - | |
594 | | - | |
| 586 | + | |
595 | 587 | | |
596 | 588 | | |
| 589 | + | |
597 | 590 | | |
598 | 591 | | |
599 | 592 | | |
600 | 593 | | |
601 | 594 | | |
602 | 595 | | |
603 | | - | |
604 | | - | |
605 | | - | |
606 | | - | |
607 | | - | |
608 | | - | |
609 | | - | |
610 | | - | |
611 | | - | |
612 | | - | |
613 | | - | |
614 | | - | |
615 | | - | |
616 | | - | |
617 | | - | |
618 | | - | |
619 | | - | |
620 | | - | |
621 | | - | |
622 | | - | |
623 | | - | |
624 | | - | |
625 | | - | |
626 | | - | |
627 | | - | |
628 | | - | |
629 | 596 | | |
630 | 597 | | |
631 | 598 | | |
| |||
760 | 727 | | |
761 | 728 | | |
762 | 729 | | |
763 | | - | |
764 | | - | |
765 | | - | |
766 | 730 | | |
767 | 731 | | |
768 | 732 | | |
769 | 733 | | |
770 | 734 | | |
771 | | - | |
772 | | - | |
773 | | - | |
774 | 735 | | |
775 | 736 | | |
776 | 737 | | |
| |||
0 commit comments