diff --git a/src/arch/xtensa/Makefile.am b/src/arch/xtensa/Makefile.am index c55d4e1d3..2023ef12a 100644 --- a/src/arch/xtensa/Makefile.am +++ b/src/arch/xtensa/Makefile.am @@ -54,6 +54,7 @@ sof_SOURCES += \ smp/xtos/_vectors.S \ smp/cpu.c \ smp/init.c \ + smp/notifier.c \ smp/schedule.c \ smp/task.c \ smp/work.c @@ -63,6 +64,7 @@ sof_SOURCES += \ up/xtos/_vectors.S \ up/cpu.c \ up/init.c \ + up/notifier.c \ up/schedule.c \ up/task.c \ up/work.c diff --git a/src/arch/xtensa/smp/cpu.c b/src/arch/xtensa/smp/cpu.c index 8ea47e13d..35b56db8e 100644 --- a/src/arch/xtensa/smp/cpu.c +++ b/src/arch/xtensa/smp/cpu.c @@ -107,6 +107,8 @@ void cpu_power_down_core(void) free_system_workq(); + free_system_notify(); + /* free entire sys heap, an instance dedicated for this core */ free_heap(RZONE_SYS); diff --git a/src/arch/xtensa/smp/notifier.c b/src/arch/xtensa/smp/notifier.c new file mode 100644 index 000000000..4b947e7ed --- /dev/null +++ b/src/arch/xtensa/smp/notifier.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/notifier.c + * \brief Xtensa SMP notifier implementation file + * \authors Tomasz Lauda + */ + +#include +#include +#include + +struct notify **arch_notify_get(void) +{ + struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); + + return &ctx->notify; +} diff --git a/src/arch/xtensa/smp/xtos/xtos-structs.h b/src/arch/xtensa/smp/xtos/xtos-structs.h index e700e6d72..a17a7d6ed 100644 --- a/src/arch/xtensa/smp/xtos/xtos-structs.h +++ b/src/arch/xtensa/smp/xtos/xtos-structs.h @@ -35,6 +35,7 @@ struct idc; struct irq_task; +struct notify; struct schedule_data; struct work_queue; @@ -59,6 +60,7 @@ struct core_context { struct irq_task *irq_high_task; struct schedule_data *sch; struct work_queue *queue; + struct notify *notify; struct idc *idc; }; diff --git a/src/arch/xtensa/up/notifier.c b/src/arch/xtensa/up/notifier.c new file mode 100644 index 000000000..2a0ed7419 --- /dev/null +++ b/src/arch/xtensa/up/notifier.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/notifier.c + * \brief Xtensa UP notifier implementation file + * \authors Tomasz Lauda + */ + +#include + +/** \brief Notify data pointer. */ +static struct notify *notify; + +struct notify **arch_notify_get(void) +{ + return ¬ify; +} diff --git a/src/include/sof/notifier.h b/src/include/sof/notifier.h index 82086c9e2..e8de8ad71 100644 --- a/src/include/sof/notifier.h +++ b/src/include/sof/notifier.h @@ -33,6 +33,7 @@ #include #include +#include struct sof; @@ -40,6 +41,11 @@ struct sof; #define NOTIFIER_ID_CPU_FREQ 0 #define NOTIFIER_ID_SSP_FREQ 1 +struct notify { + spinlock_t lock; /* notifier lock */ + struct list_item list; /* list of notifiers */ +}; + struct notifier { uint32_t id; struct list_item list; @@ -47,6 +53,8 @@ struct notifier { void (*cb)(int message, void *cb_data, void *event_data); }; +struct notify **arch_notify_get(void); + void notifier_register(struct notifier *notifier); void notifier_unregister(struct notifier *notifier); @@ -54,4 +62,6 @@ void notifier_event(int id, int message, void *event_data); void init_system_notify(struct sof *sof); +void free_system_notify(void); + #endif diff --git a/src/init/init.c b/src/init/init.c index 8d25982a4..c3a37693e 100644 --- a/src/init/init.c +++ b/src/init/init.c @@ -100,6 +100,9 @@ int slave_core_init(struct sof *sof) if (err < 0) panic(SOF_IPC_PANIC_ARCH); + trace_point(TRACE_BOOT_SYS_NOTE); + init_system_notify(sof); + trace_point(TRACE_BOOT_SYS_SCHED); scheduler_init(sof); diff --git a/src/lib/notifier.c b/src/lib/notifier.c index 8a8068b21..e724f61b5 100644 --- a/src/lib/notifier.c +++ b/src/lib/notifier.c @@ -30,44 +30,40 @@ #include #include -#include #include - -/* General purpose notifiers */ - -struct notify { - spinlock_t lock; - struct list_item list; /* list of notifiers */ -}; - -static struct notify _notify; +#include void notifier_register(struct notifier *notifier) { - spin_lock(&_notify.lock); - list_item_prepend(¬ifier->list, &_notify.list); - spin_unlock(&_notify.lock); + struct notify *notify = *arch_notify_get(); + + spin_lock(¬ify->lock); + list_item_prepend(¬ifier->list, ¬ify->list); + spin_unlock(¬ify->lock); } void notifier_unregister(struct notifier *notifier) { - spin_lock(&_notify.lock); + struct notify *notify = *arch_notify_get(); + + spin_lock(¬ify->lock); list_item_del(¬ifier->list); - spin_unlock(&_notify.lock); + spin_unlock(¬ify->lock); } void notifier_event(int id, int message, void *event_data) { + struct notify *notify = *arch_notify_get(); struct list_item *wlist; struct notifier *n; - spin_lock(&_notify.lock); + spin_lock(¬ify->lock); - if (list_is_empty(&_notify.list)) + if (list_is_empty(¬ify->list)) goto out; /* iterate through notifiers and send event to interested clients */ - list_for_item(wlist, &_notify.list) { + list_for_item(wlist, ¬ify->list) { n = container_of(wlist, struct notifier, list); if (n->id == id) @@ -75,11 +71,23 @@ void notifier_event(int id, int message, void *event_data) } out: - spin_unlock(&_notify.lock); + spin_unlock(¬ify->lock); } void init_system_notify(struct sof *sof) { - list_init(&_notify.list); - spinlock_init(&_notify.lock); + struct notify **notify = arch_notify_get(); + *notify = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**notify)); + + list_init(&(*notify)->list); + spinlock_init(&(*notify)->lock); +} + +void free_system_notify(void) +{ + struct notify *notify = *arch_notify_get(); + + spin_lock(¬ify->lock); + list_item_del(¬ify->list); + spin_unlock(¬ify->lock); } diff --git a/src/lib/work.c b/src/lib/work.c index 4e547dedc..e60ea11d2 100644 --- a/src/lib/work.c +++ b/src/lib/work.c @@ -501,13 +501,11 @@ struct work_queue *work_new_queue(struct work_queue_timesource *ts) /* TODO: configurable through IPC */ queue->timeout = PLATFORM_WORKQ_DEFAULT_TIMEOUT; - if (cpu_get_id() == PLATFORM_MASTER_CORE_ID) { - /* notification of clk changes */ - queue->notifier.cb = work_notify; - queue->notifier.cb_data = queue; - queue->notifier.id = ts->notifier; - notifier_register(&queue->notifier); - } + /* notification of clk changes */ + queue->notifier.cb = work_notify; + queue->notifier.cb_data = queue; + queue->notifier.id = ts->notifier; + notifier_register(&queue->notifier); /* register system timer */ timer_register(&queue->ts->timer, queue_run, queue); @@ -539,8 +537,7 @@ void free_system_workq(void) timer_unregister(&(*queue)->ts->timer); - if (cpu_get_id() == PLATFORM_MASTER_CORE_ID) - notifier_unregister(&(*queue)->notifier); + notifier_unregister(&(*queue)->notifier); list_item_del(&(*queue)->work);