Skip to content

Commit

Permalink
Merge pull request #482 from tlauda/topic/idc-notify
Browse files Browse the repository at this point in the history
notifier: support for multicore notifications
  • Loading branch information
lgirdwood authored Oct 14, 2018
2 parents 36db3de + d16addf commit 1024e94
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 20 deletions.
4 changes: 4 additions & 0 deletions src/arch/xtensa/smp/include/arch/idc.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <sof/idc.h>
#include <sof/ipc.h>
#include <sof/lock.h>
#include <sof/notifier.h>

extern struct ipc *_ipc;
extern void cpu_power_down_core(void);
Expand Down Expand Up @@ -256,6 +257,9 @@ static inline void idc_cmd(struct idc_msg *msg)
case iTS(IDC_MSG_COMP_CMD):
idc_component_command(msg->extension);
break;
case iTS(IDC_MSG_NOTIFY):
notifier_notify();
break;
default:
trace_idc_error("eTc");
trace_error_value(msg->header);
Expand Down
4 changes: 4 additions & 0 deletions src/include/sof/idc.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
#define IDC_MSG_COMP_CMD IDC_TYPE(0x4)
#define IDC_MSG_COMP_CMD_EXT(x) IDC_EXTENSION(x)

/** \brief IDC notify message. */
#define IDC_MSG_NOTIFY IDC_TYPE(0x5)
#define IDC_MSG_NOTIFY_EXT IDC_EXTENSION(0x0)

/** \brief Decodes IDC message type. */
#define iTS(x) (((x) >> IDC_TYPE_SHIFT) & IDC_TYPE_MASK)

Expand Down
15 changes: 14 additions & 1 deletion src/include/sof/notifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,23 @@ struct sof;
#define NOTIFIER_ID_CPU_FREQ 0
#define NOTIFIER_ID_SSP_FREQ 1

/* notifier target core masks */
#define NOTIFIER_TARGET_CORE_MASK(x) (1 << x)
#define NOTIFIER_TARGET_CORE_ALL_MASK 0xFFFFFFFF

struct notify {
spinlock_t lock; /* notifier lock */
struct list_item list; /* list of notifiers */
};

struct notify_data {
uint32_t id;
uint32_t message;
uint32_t target_core_mask;
uint32_t data_size;
void *data;
};

struct notifier {
uint32_t id;
struct list_item list;
Expand All @@ -58,7 +70,8 @@ struct notify **arch_notify_get(void);
void notifier_register(struct notifier *notifier);
void notifier_unregister(struct notifier *notifier);

void notifier_event(int id, int message, void *event_data);
void notifier_notify(void);
void notifier_event(struct notify_data *notify_data);

void init_system_notify(struct sof *sof);

Expand Down
28 changes: 19 additions & 9 deletions src/lib/clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <sof/alloc.h>
#include <sof/lock.h>
#include <sof/notifier.h>
#include <sof/cpu.h>
#include <platform/clk.h>
#include <platform/clk-map.h>
#include <platform/platcfg.h>
Expand Down Expand Up @@ -76,16 +77,20 @@ static inline uint32_t clock_get_freq(const struct freq_table *table,

uint32_t clock_set_freq(int clock, uint32_t hz)
{
struct clock_notify_data notify_data;
struct notify_data notify_data;
struct clock_notify_data clk_notify_data;
set_frequency set_freq = NULL;
const struct freq_table *freq_table = NULL;
uint32_t freq_table_size = 0;
uint32_t notifier_id = 0;
uint32_t idx;
uint32_t flags;

notify_data.old_freq = clk_pdata->clk[clock].freq;
notify_data.old_ticks_per_msec = clk_pdata->clk[clock].ticks_per_msec;
notify_data.data_size = sizeof(clk_notify_data);
notify_data.data = &clk_notify_data;

clk_notify_data.old_freq = clk_pdata->clk[clock].freq;
clk_notify_data.old_ticks_per_msec =
clk_pdata->clk[clock].ticks_per_msec;

/* atomic context for changing clocks */
spin_lock_irq(&clk_pdata->clk[clock].lock, flags);
Expand All @@ -95,24 +100,28 @@ uint32_t clock_set_freq(int clock, uint32_t hz)
set_freq = &clock_platform_set_cpu_freq;
freq_table = cpu_freq;
freq_table_size = ARRAY_SIZE(cpu_freq);
notifier_id = NOTIFIER_ID_CPU_FREQ;
notify_data.id = NOTIFIER_ID_CPU_FREQ;
notify_data.target_core_mask =
NOTIFIER_TARGET_CORE_MASK(cpu_get_id());
break;
case CLK_SSP:
set_freq = &clock_platform_set_ssp_freq;
freq_table = ssp_freq;
freq_table_size = ARRAY_SIZE(ssp_freq);
notifier_id = NOTIFIER_ID_SSP_FREQ;
notify_data.id = NOTIFIER_ID_SSP_FREQ;
notify_data.target_core_mask = NOTIFIER_TARGET_CORE_ALL_MASK;
break;
default:
break;
}

/* get nearest frequency that is >= requested Hz */
idx = clock_get_freq(freq_table, freq_table_size, hz);
notify_data.freq = freq_table[idx].freq;
clk_notify_data.freq = freq_table[idx].freq;

/* tell anyone interested we are about to change freq */
notifier_event(notifier_id, CLOCK_NOTIFY_PRE, &notify_data);
notify_data.message = CLOCK_NOTIFY_PRE;
notifier_event(&notify_data);

if (set_freq(freq_table[idx].enc) == 0) {
/* update clock frequency */
Expand All @@ -122,7 +131,8 @@ uint32_t clock_set_freq(int clock, uint32_t hz)
}

/* tell anyone interested we have now changed freq */
notifier_event(notifier_id, CLOCK_NOTIFY_POST, &notify_data);
notify_data.message = CLOCK_NOTIFY_POST;
notifier_event(&notify_data);

spin_unlock_irq(&clk_pdata->clk[clock].lock, flags);

Expand Down
52 changes: 42 additions & 10 deletions src/lib/notifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
#include <sof/sof.h>
#include <sof/list.h>
#include <sof/alloc.h>
#include <sof/cpu.h>
#include <sof/idc.h>
#include <platform/idc.h>

static struct notify_data _notify_data;

void notifier_register(struct notifier *notifier)
{
Expand All @@ -51,26 +56,53 @@ void notifier_unregister(struct notifier *notifier)
spin_unlock(&notify->lock);
}

void notifier_event(int id, int message, void *event_data)
void notifier_notify(void)
{
struct notify *notify = *arch_notify_get();
struct list_item *wlist;
struct notifier *n;

spin_lock(&notify->lock);
if (!list_is_empty(&notify->list)) {
dcache_invalidate_region(&_notify_data, sizeof(_notify_data));
dcache_invalidate_region(_notify_data.data,
_notify_data.data_size);

/* iterate through notifiers and send event to
* interested clients
*/
list_for_item(wlist, &notify->list) {
n = container_of(wlist, struct notifier, list);
if (n->id == _notify_data.id)
n->cb(_notify_data.message, n->cb_data,
_notify_data.data);
}
}
}

if (list_is_empty(&notify->list))
goto out;
void notifier_event(struct notify_data *notify_data)
{
struct notify *notify = *arch_notify_get();
struct idc_msg notify_msg = { IDC_MSG_NOTIFY, IDC_MSG_NOTIFY_EXT };
int i = 0;

spin_lock(&notify->lock);

/* iterate through notifiers and send event to interested clients */
list_for_item(wlist, &notify->list) {
_notify_data = *notify_data;
dcache_writeback_region(_notify_data.data, _notify_data.data_size);
dcache_writeback_region(&_notify_data, sizeof(_notify_data));

n = container_of(wlist, struct notifier, list);
if (n->id == id)
n->cb(message, n->cb_data, event_data);
/* notify selected targets */
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
if (_notify_data.target_core_mask & (1 << i)) {
if (i == cpu_get_id()) {
notifier_notify();
} else if (cpu_is_core_enabled(i)) {
notify_msg.core = i;
idc_send_msg(&notify_msg, IDC_BLOCKING);
}
}
}

out:
spin_unlock(&notify->lock);
}

Expand Down
2 changes: 2 additions & 0 deletions test/cmocka/src/audio/pipeline/pipeline_mocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ int arch_cpu_is_core_enabled(int id)

void cpu_power_down_core(void) { }

void notifier_notify(void) { }

struct ipc_comp_dev *ipc_get_comp(struct ipc *ipc, uint32_t id)
{
(void)ipc;
Expand Down
2 changes: 2 additions & 0 deletions test/cmocka/src/audio/pipeline/pipeline_mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ void cpu_power_down_core(void);

struct ipc_comp_dev *ipc_get_comp(struct ipc *ipc, uint32_t id);

void notifier_notify(void);

struct pipeline_new_setup_data {
struct sof_ipc_pipe_new ipc_data;
struct comp_dev *comp_data;
Expand Down

0 comments on commit 1024e94

Please sign in to comment.