From 060c71e953a8a9c2fc65fa94a32440c426ffe44b Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Mon, 20 Aug 2018 14:23:55 +0200 Subject: [PATCH] work: add work_queue to core_context Implements work_queue per core by adding it to core_context. Signed-off-by: Tomasz Lauda --- src/arch/xtensa/Makefile.am | 6 ++-- src/arch/xtensa/smp/cpu.c | 2 ++ src/arch/xtensa/smp/work.c | 47 +++++++++++++++++++++++++ src/arch/xtensa/smp/xtos/xtos-structs.h | 2 ++ src/arch/xtensa/up/work.c | 46 ++++++++++++++++++++++++ src/include/sof/work.h | 5 +++ src/lib/work.c | 35 ++++++++++++------ 7 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 src/arch/xtensa/smp/work.c create mode 100644 src/arch/xtensa/up/work.c diff --git a/src/arch/xtensa/Makefile.am b/src/arch/xtensa/Makefile.am index ffe3791976f6..0c3474e699c8 100644 --- a/src/arch/xtensa/Makefile.am +++ b/src/arch/xtensa/Makefile.am @@ -55,7 +55,8 @@ sof_SOURCES += \ smp/cpu.c \ smp/init.c \ smp/schedule.c \ - smp/task.c + smp/task.c \ + smp/work.c else sof_SOURCES += \ up/xtos/crt1-boards.S \ @@ -63,7 +64,8 @@ sof_SOURCES += \ up/cpu.c \ up/init.c \ up/schedule.c \ - up/task.c + up/task.c \ + up/work.c endif if BUILD_BOOTLOADER diff --git a/src/arch/xtensa/smp/cpu.c b/src/arch/xtensa/smp/cpu.c index 411725f51961..93a8c384915c 100644 --- a/src/arch/xtensa/smp/cpu.c +++ b/src/arch/xtensa/smp/cpu.c @@ -99,6 +99,8 @@ void cpu_power_down_core(void) scheduler_free(); + free_system_workq(); + free_core_context(arch_cpu_get_id()); dcache_writeback_invalidate_all(); diff --git a/src/arch/xtensa/smp/work.c b/src/arch/xtensa/smp/work.c new file mode 100644 index 000000000000..41e2f2eac642 --- /dev/null +++ b/src/arch/xtensa/smp/work.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Tomasz Lauda + * + */ + +/** + * \file arch/xtensa/smp/work.c + * \brief Xtensa SMP work queue implementation file + * \authors Tomasz Lauda + */ + +#include +#include +#include + +struct work_queue **arch_work_queue_get(void) +{ + struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); + + return &ctx->queue; +} diff --git a/src/arch/xtensa/smp/xtos/xtos-structs.h b/src/arch/xtensa/smp/xtos/xtos-structs.h index 11d49e0dc7a9..e700e6d72726 100644 --- a/src/arch/xtensa/smp/xtos/xtos-structs.h +++ b/src/arch/xtensa/smp/xtos/xtos-structs.h @@ -36,6 +36,7 @@ struct idc; struct irq_task; struct schedule_data; +struct work_queue; struct thread_data { xtos_structures_pointers xtos_ptrs; @@ -57,6 +58,7 @@ struct core_context { struct irq_task *irq_med_task; struct irq_task *irq_high_task; struct schedule_data *sch; + struct work_queue *queue; struct idc *idc; }; diff --git a/src/arch/xtensa/up/work.c b/src/arch/xtensa/up/work.c new file mode 100644 index 000000000000..f5d4e90d0322 --- /dev/null +++ b/src/arch/xtensa/up/work.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Tomasz Lauda + * + */ + +/** + * \file arch/xtensa/up/work.c + * \brief Xtensa UP work queue implementation file + * \authors Tomasz Lauda + */ + +#include + +/** \brief Generic system work queue. */ +static struct work_queue *queue; + +struct work_queue **arch_work_queue_get(void) +{ + return &queue; +} diff --git a/src/include/sof/work.h b/src/include/sof/work.h index a4493a789f95..83ac4f388d27 100644 --- a/src/include/sof/work.h +++ b/src/include/sof/work.h @@ -68,6 +68,8 @@ struct work_queue_timesource { (w)->cb_data = xd; \ (w)->flags = xflags; +struct work_queue **arch_work_queue_get(void); + /* schedule/cancel work on work queue */ void work_schedule(struct work_queue *queue, struct work *w, uint64_t timeout); void work_reschedule(struct work_queue *queue, struct work *w, uint64_t timeout); @@ -85,4 +87,7 @@ struct work_queue *work_new_queue(struct work_queue_timesource *ts); /* init system workq */ void init_system_workq(struct work_queue_timesource *ts); +/* free system workq */ +void free_system_workq(void); + #endif diff --git a/src/lib/work.c b/src/lib/work.c index 6b628b5bb9cd..a5024efd8518 100644 --- a/src/lib/work.c +++ b/src/lib/work.c @@ -70,9 +70,6 @@ struct work_queue { uint64_t run_ticks; /* ticks when last run */ }; -/* generic system work queue */ -static struct work_queue *queue_; - static inline int work_set_timer(struct work_queue *queue, uint64_t ticks) { int ret; @@ -363,7 +360,7 @@ void work_schedule(struct work_queue *queue, struct work *w, uint64_t timeout) void work_schedule_default(struct work *w, uint64_t timeout) { - work_schedule(queue_, w, timeout); + work_schedule(*arch_work_queue_get(), w, timeout); } static void reschedule(struct work_queue *queue, struct work *w, uint64_t time) @@ -406,17 +403,18 @@ void work_reschedule(struct work_queue *queue, struct work *w, uint64_t timeout) void work_reschedule_default(struct work *w, uint64_t timeout) { + struct work_queue *queue = *arch_work_queue_get(); uint64_t time; /* convert timeout micro seconds to CPU clock ticks */ - time = queue_->ticks_per_usec * timeout + work_get_timer(queue_); + time = queue->ticks_per_usec * timeout + work_get_timer(queue); - reschedule(queue_, w, time); + reschedule(queue, w, time); } void work_reschedule_default_at(struct work *w, uint64_t time) { - reschedule(queue_, w, time); + reschedule(*arch_work_queue_get(), w, time); } void work_cancel(struct work_queue *queue, struct work *w) @@ -436,7 +434,7 @@ void work_cancel(struct work_queue *queue, struct work *w) void work_cancel_default(struct work *w) { - work_cancel(queue_, w); + work_cancel(*arch_work_queue_get(), w); } struct work_queue *work_new_queue(struct work_queue_timesource *ts) @@ -444,7 +442,7 @@ struct work_queue *work_new_queue(struct work_queue_timesource *ts) struct work_queue *queue; /* init work queue */ - queue = rmalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*queue_)); + queue = rmalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, sizeof(*queue)); list_init(&queue->work); spinlock_init(&queue->lock); @@ -466,5 +464,22 @@ struct work_queue *work_new_queue(struct work_queue_timesource *ts) void init_system_workq(struct work_queue_timesource *ts) { - queue_ = work_new_queue(ts); + struct work_queue **queue = arch_work_queue_get(); + *queue = work_new_queue(ts); +} + +void free_system_workq(void) +{ + struct work_queue **queue = arch_work_queue_get(); + uint32_t flags; + + spin_lock_irq(&(*queue)->lock, flags); + + timer_unregister(&(*queue)->ts->timer); + notifier_unregister(&(*queue)->notifier); + list_item_del(&(*queue)->work); + + spin_unlock_irq(&(*queue)->lock, flags); + + rfree(*queue); }