@@ -160,7 +160,19 @@ static void devicelist_reset(struct device_list *devlist, bool remove_items);
160160
161161static uint64_t kpb_task_deadline (void * data )
162162{
163+ #ifndef __ZEPHYR__
163164 return SOF_TASK_DEADLINE_ALMOST_IDLE ;
165+ #else
166+ struct draining_data * dd = (struct draining_data * )data ;
167+ uint64_t now ;
168+
169+ if (dd -> next_copy_time == 0 )
170+ return 0 ; /* run immediately */
171+
172+ now = sof_cycle_get_64 ();
173+ return dd -> next_copy_time > now ?
174+ k_uptime_ticks () + k_cyc_to_ticks_near64 (dd -> next_copy_time - now ) : 0 ;
175+ #endif
164176}
165177
166178#if CONFIG_AMS
@@ -1684,9 +1696,13 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli)
16841696 kpb -> draining_task_data .sink = kpb -> host_sink ;
16851697 kpb -> draining_task_data .hb = buff ;
16861698 kpb -> draining_task_data .drain_req = drain_req ;
1699+ kpb -> draining_task_data .drained = 0 ;
16871700 kpb -> draining_task_data .sample_width = sample_width ;
16881701 kpb -> draining_task_data .drain_interval = drain_interval ;
1702+ kpb -> draining_task_data .period_copy_start = 0 ;
16891703 kpb -> draining_task_data .pb_limit = period_bytes_limit ;
1704+ kpb -> draining_task_data .period_bytes = 0 ;
1705+ kpb -> draining_task_data .next_copy_time = 0 ;
16901706 kpb -> draining_task_data .dev = dev ;
16911707 kpb -> draining_task_data .sync_mode_on = kpb -> sync_draining_mode ;
16921708
@@ -1701,6 +1717,16 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli)
17011717 /* Pause selector copy. */
17021718 comp_buffer_get_sink_component (kpb -> sel_sink )-> state = COMP_STATE_PAUSED ;
17031719
1720+ if (!pm_runtime_is_active (PM_RUNTIME_DSP , PLATFORM_PRIMARY_CORE_ID ))
1721+ pm_runtime_disable (PM_RUNTIME_DSP , PLATFORM_PRIMARY_CORE_ID );
1722+
1723+ comp_info (dev , "Scheduling draining task" );
1724+
1725+ /* Change KPB internal state to DRAINING */
1726+ kpb_change_state (kpb , KPB_STATE_DRAINING );
1727+
1728+ kpb -> draining_task_data .draining_time_start = sof_cycle_get_64 ();
1729+
17041730 /* Schedule draining task */
17051731 schedule_task (& kpb -> draining_task , 0 , 0 );
17061732 }
@@ -1719,23 +1745,16 @@ static enum task_state kpb_draining_task(void *arg)
17191745 struct draining_data * draining_data = (struct draining_data * )arg ;
17201746 struct comp_buffer * sink = draining_data -> sink ;
17211747 struct history_buffer * buff = draining_data -> hb ;
1722- size_t drain_req = draining_data -> drain_req ;
17231748 size_t sample_width = draining_data -> sample_width ;
17241749 size_t avail ;
17251750 size_t size_to_copy ;
1726- uint32_t drained = 0 ;
1727- uint64_t draining_time_start ;
17281751 uint64_t draining_time_end ;
17291752 uint64_t draining_time_ms ;
17301753 uint64_t drain_interval = draining_data -> drain_interval ;
1731- uint64_t next_copy_time = 0 ;
1732- size_t period_bytes = 0 ;
17331754 size_t period_bytes_limit = draining_data -> pb_limit ;
1734- uint64_t period_copy_start ;
17351755 size_t * rt_stream_update = & draining_data -> buffered_while_draining ;
17361756 struct comp_data * kpb = comp_get_drvdata (draining_data -> dev );
17371757 bool sync_mode_on = draining_data -> sync_mode_on ;
1738- bool pm_is_active ;
17391758
17401759 /*
17411760 * WORKAROUND: The code below accesses KPB sink buffer and calls comp_copy() on
@@ -1748,66 +1767,53 @@ static enum task_state kpb_draining_task(void *arg)
17481767 k_sched_lock ();
17491768#endif
17501769
1751- comp_cl_info (& comp_kpb , "kpb_draining_task(), start." );
1752-
1753- pm_is_active = pm_runtime_is_active (PM_RUNTIME_DSP , PLATFORM_PRIMARY_CORE_ID );
1754-
1755- if (!pm_is_active )
1756- pm_runtime_disable (PM_RUNTIME_DSP , PLATFORM_PRIMARY_CORE_ID );
1757-
1758- /* Change KPB internal state to DRAINING */
1759- kpb_change_state (kpb , KPB_STATE_DRAINING );
1770+ comp_cl_dbg (& comp_kpb , "kpb_draining_task()" );
17601771
1761- draining_time_start = sof_cycle_get_64 ();
1762- period_copy_start = draining_time_start ;
1772+ /* Have we received reset request? */
1773+ if (kpb -> state == KPB_STATE_RESETTING ) {
1774+ kpb_change_state (kpb , KPB_STATE_RESET_FINISHING );
1775+ kpb_reset (draining_data -> dev );
1776+ draining_data -> drain_req = 0 ;
1777+ goto out ;
1778+ }
17631779
1764- while (drain_req > 0 ) {
1765- /*
1766- * Draining task usually runs for quite a lot of time (could be few seconds).
1767- * LL should not be blocked for such a long time.
1780+ if (draining_data -> drain_req > 0 ) {
1781+ /* Are we ready to drain further or host still need some time
1782+ * to read the data already provided?
17681783 */
1784+ if (sync_mode_on && draining_data -> next_copy_time > sof_cycle_get_64 ()) {
1785+ /* Restore original EDF thread priority */
17691786#ifdef __ZEPHYR__
1770- k_sched_unlock ();
1771- k_yield ();
1772- k_sched_lock ();
1787+ k_sched_unlock ();
17731788#endif
1774-
1775- /* Have we received reset request? */
1776- if (kpb -> state == KPB_STATE_RESETTING ) {
1777- kpb_change_state (kpb , KPB_STATE_RESET_FINISHING );
1778- kpb_reset (draining_data -> dev );
1779- goto out ;
1789+ return SOF_TASK_STATE_RESCHEDULE ;
17801790 }
1781- /* Are we ready to drain further or host still need some time
1782- * to read the data already provided?
1783- */
1784- if (sync_mode_on &&
1785- next_copy_time > sof_cycle_get_64 ()) {
1786- period_bytes = 0 ;
1787- period_copy_start = sof_cycle_get_64 ();
1788- continue ;
1789- } else if (next_copy_time == 0 ) {
1790- period_copy_start = sof_cycle_get_64 ();
1791+
1792+ if (draining_data -> period_copy_start == 0 ) {
1793+ /* starting new draining period */
1794+ draining_data -> period_copy_start = sof_cycle_get_64 ();
1795+ draining_data -> period_bytes = 0 ;
17911796 }
17921797
17931798 avail = (uintptr_t )buff -> end_addr - (uintptr_t )buff -> r_ptr ;
17941799 size_to_copy = MIN (avail ,
1795- MIN (drain_req , audio_stream_get_free_bytes (& sink -> stream )));
1800+ MIN (draining_data -> drain_req ,
1801+ audio_stream_get_free_bytes (& sink -> stream )));
17961802
17971803 kpb_drain_samples (buff -> r_ptr , & sink -> stream , size_to_copy ,
17981804 sample_width );
17991805
18001806 buff -> r_ptr = (char * )buff -> r_ptr + (uint32_t )size_to_copy ;
1801- drain_req -= size_to_copy ;
1802- drained += size_to_copy ;
1803- period_bytes += size_to_copy ;
1807+ draining_data -> drain_req -= size_to_copy ;
1808+ draining_data -> drained += size_to_copy ;
1809+ draining_data -> period_bytes += size_to_copy ;
18041810 kpb -> hd .free += MIN (kpb -> hd .buffer_size -
18051811 kpb -> hd .free , size_to_copy );
18061812
18071813 /* no data left in the current buffer -- switch to the next buffer */
18081814 if (size_to_copy == avail ) {
18091815 buff -> r_ptr = buff -> start_addr ;
1810- buff = buff -> next ;
1816+ draining_data -> hb = buff -> next ;
18111817 }
18121818
18131819 if (size_to_copy ) {
@@ -1821,20 +1827,25 @@ static enum task_state kpb_draining_task(void *arg)
18211827 comp_copy (comp_buffer_get_sink_component (sink ));
18221828 }
18231829
1824- if (sync_mode_on && period_bytes >= period_bytes_limit )
1825- next_copy_time = period_copy_start + drain_interval ;
1830+ if (sync_mode_on && draining_data -> period_bytes >= period_bytes_limit ) {
1831+ draining_data -> next_copy_time = draining_data -> period_copy_start +
1832+ drain_interval ;
1833+ draining_data -> period_copy_start = 0 ;
1834+ } else {
1835+ draining_data -> next_copy_time = 0 ;
1836+ }
18261837
1827- if (drain_req == 0 ) {
1838+ if (draining_data -> drain_req == 0 ) {
18281839 /* We have finished draining of requested data however
18291840 * while we were draining real time stream could provided
18301841 * new data which needs to be copy to host.
18311842 */
18321843 comp_cl_info (& comp_kpb , "kpb: update drain_req by %zu" ,
18331844 * rt_stream_update );
18341845 kpb_lock (kpb );
1835- drain_req += * rt_stream_update ;
1846+ draining_data -> drain_req += * rt_stream_update ;
18361847 * rt_stream_update = 0 ;
1837- if (!drain_req && kpb -> state == KPB_STATE_DRAINING ) {
1848+ if (!draining_data -> drain_req && kpb -> state == KPB_STATE_DRAINING ) {
18381849 /* Draining is done. Now switch KPB to copy real time
18391850 * stream to client's sink. This state is called
18401851 * "draining on demand"
@@ -1848,6 +1859,17 @@ static enum task_state kpb_draining_task(void *arg)
18481859 }
18491860
18501861out :
1862+ if (draining_data -> drain_req > 0 ) {
1863+ /* Restore original EDF thread priority */
1864+ #ifdef __ZEPHYR__
1865+ k_sched_unlock ();
1866+ #endif
1867+
1868+ /* continue drainig on next task iteration */
1869+ return SOF_TASK_STATE_RESCHEDULE ;
1870+ }
1871+
1872+ /* finished drainig */
18511873 draining_time_end = sof_cycle_get_64 ();
18521874
18531875 /* Reset host-sink copy mode back to its pre-draining value.
@@ -1860,13 +1882,14 @@ static enum task_state kpb_draining_task(void *arg)
18601882 else
18611883 comp_cl_err (& comp_kpb , "Failed to restore host copy mode!" );
18621884
1863- draining_time_ms = k_cyc_to_ms_near64 (draining_time_end - draining_time_start );
1885+ draining_time_ms = k_cyc_to_ms_near64 (draining_time_end -
1886+ draining_data -> draining_time_start );
18641887 if (draining_time_ms <= UINT_MAX )
1865- comp_cl_info (& comp_kpb , "KPB: kpb_draining_task(), done. %u drained in %u ms" ,
1866- drained , (unsigned int )draining_time_ms );
1888+ comp_cl_info (& comp_kpb , "KPB: kpb_draining_task(), done. %zu drained in %u ms" ,
1889+ draining_data -> drained , (unsigned int )draining_time_ms );
18671890 else
1868- comp_cl_info (& comp_kpb , "KPB: kpb_draining_task(), done. %u drained in > %u ms" ,
1869- drained , UINT_MAX );
1891+ comp_cl_info (& comp_kpb , "KPB: kpb_draining_task(), done. %zu drained in > %u ms" ,
1892+ draining_data -> drained , UINT_MAX );
18701893
18711894 /* Restore original EDF thread priority */
18721895#ifdef __ZEPHYR__
0 commit comments