Skip to content

Commit d16addf

Browse files
committed
notifier: support for multicore notifications
Adds support for multicore notifications: - IDC that needs to be sent to slave cores. - Flag which tells notifier, which cores should be notified. Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
1 parent cc3fb1e commit d16addf

7 files changed

Lines changed: 87 additions & 20 deletions

File tree

src/arch/xtensa/smp/include/arch/idc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <sof/idc.h>
4646
#include <sof/ipc.h>
4747
#include <sof/lock.h>
48+
#include <sof/notifier.h>
4849

4950
extern struct ipc *_ipc;
5051
extern void cpu_power_down_core(void);
@@ -256,6 +257,9 @@ static inline void idc_cmd(struct idc_msg *msg)
256257
case iTS(IDC_MSG_COMP_CMD):
257258
idc_component_command(msg->extension);
258259
break;
260+
case iTS(IDC_MSG_NOTIFY):
261+
notifier_notify();
262+
break;
259263
default:
260264
trace_idc_error("eTc");
261265
trace_error_value(msg->header);

src/include/sof/idc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@
9494
#define IDC_MSG_COMP_CMD IDC_TYPE(0x4)
9595
#define IDC_MSG_COMP_CMD_EXT(x) IDC_EXTENSION(x)
9696

97+
/** \brief IDC notify message. */
98+
#define IDC_MSG_NOTIFY IDC_TYPE(0x5)
99+
#define IDC_MSG_NOTIFY_EXT IDC_EXTENSION(0x0)
100+
97101
/** \brief Decodes IDC message type. */
98102
#define iTS(x) (((x) >> IDC_TYPE_SHIFT) & IDC_TYPE_MASK)
99103

src/include/sof/notifier.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,23 @@ struct sof;
4141
#define NOTIFIER_ID_CPU_FREQ 0
4242
#define NOTIFIER_ID_SSP_FREQ 1
4343

44+
/* notifier target core masks */
45+
#define NOTIFIER_TARGET_CORE_MASK(x) (1 << x)
46+
#define NOTIFIER_TARGET_CORE_ALL_MASK 0xFFFFFFFF
47+
4448
struct notify {
4549
spinlock_t lock; /* notifier lock */
4650
struct list_item list; /* list of notifiers */
4751
};
4852

53+
struct notify_data {
54+
uint32_t id;
55+
uint32_t message;
56+
uint32_t target_core_mask;
57+
uint32_t data_size;
58+
void *data;
59+
};
60+
4961
struct notifier {
5062
uint32_t id;
5163
struct list_item list;
@@ -58,7 +70,8 @@ struct notify **arch_notify_get(void);
5870
void notifier_register(struct notifier *notifier);
5971
void notifier_unregister(struct notifier *notifier);
6072

61-
void notifier_event(int id, int message, void *event_data);
73+
void notifier_notify(void);
74+
void notifier_event(struct notify_data *notify_data);
6275

6376
void init_system_notify(struct sof *sof);
6477

src/lib/clk.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <sof/alloc.h>
3737
#include <sof/lock.h>
3838
#include <sof/notifier.h>
39+
#include <sof/cpu.h>
3940
#include <platform/clk.h>
4041
#include <platform/clk-map.h>
4142
#include <platform/platcfg.h>
@@ -76,16 +77,20 @@ static inline uint32_t clock_get_freq(const struct freq_table *table,
7677

7778
uint32_t clock_set_freq(int clock, uint32_t hz)
7879
{
79-
struct clock_notify_data notify_data;
80+
struct notify_data notify_data;
81+
struct clock_notify_data clk_notify_data;
8082
set_frequency set_freq = NULL;
8183
const struct freq_table *freq_table = NULL;
8284
uint32_t freq_table_size = 0;
83-
uint32_t notifier_id = 0;
8485
uint32_t idx;
8586
uint32_t flags;
8687

87-
notify_data.old_freq = clk_pdata->clk[clock].freq;
88-
notify_data.old_ticks_per_msec = clk_pdata->clk[clock].ticks_per_msec;
88+
notify_data.data_size = sizeof(clk_notify_data);
89+
notify_data.data = &clk_notify_data;
90+
91+
clk_notify_data.old_freq = clk_pdata->clk[clock].freq;
92+
clk_notify_data.old_ticks_per_msec =
93+
clk_pdata->clk[clock].ticks_per_msec;
8994

9095
/* atomic context for changing clocks */
9196
spin_lock_irq(&clk_pdata->clk[clock].lock, flags);
@@ -95,24 +100,28 @@ uint32_t clock_set_freq(int clock, uint32_t hz)
95100
set_freq = &clock_platform_set_cpu_freq;
96101
freq_table = cpu_freq;
97102
freq_table_size = ARRAY_SIZE(cpu_freq);
98-
notifier_id = NOTIFIER_ID_CPU_FREQ;
103+
notify_data.id = NOTIFIER_ID_CPU_FREQ;
104+
notify_data.target_core_mask =
105+
NOTIFIER_TARGET_CORE_MASK(cpu_get_id());
99106
break;
100107
case CLK_SSP:
101108
set_freq = &clock_platform_set_ssp_freq;
102109
freq_table = ssp_freq;
103110
freq_table_size = ARRAY_SIZE(ssp_freq);
104-
notifier_id = NOTIFIER_ID_SSP_FREQ;
111+
notify_data.id = NOTIFIER_ID_SSP_FREQ;
112+
notify_data.target_core_mask = NOTIFIER_TARGET_CORE_ALL_MASK;
105113
break;
106114
default:
107115
break;
108116
}
109117

110118
/* get nearest frequency that is >= requested Hz */
111119
idx = clock_get_freq(freq_table, freq_table_size, hz);
112-
notify_data.freq = freq_table[idx].freq;
120+
clk_notify_data.freq = freq_table[idx].freq;
113121

114122
/* tell anyone interested we are about to change freq */
115-
notifier_event(notifier_id, CLOCK_NOTIFY_PRE, &notify_data);
123+
notify_data.message = CLOCK_NOTIFY_PRE;
124+
notifier_event(&notify_data);
116125

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

124133
/* tell anyone interested we have now changed freq */
125-
notifier_event(notifier_id, CLOCK_NOTIFY_POST, &notify_data);
134+
notify_data.message = CLOCK_NOTIFY_POST;
135+
notifier_event(&notify_data);
126136

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

src/lib/notifier.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
#include <sof/sof.h>
3333
#include <sof/list.h>
3434
#include <sof/alloc.h>
35+
#include <sof/cpu.h>
36+
#include <sof/idc.h>
37+
#include <platform/idc.h>
38+
39+
static struct notify_data _notify_data;
3540

3641
void notifier_register(struct notifier *notifier)
3742
{
@@ -51,26 +56,53 @@ void notifier_unregister(struct notifier *notifier)
5156
spin_unlock(&notify->lock);
5257
}
5358

54-
void notifier_event(int id, int message, void *event_data)
59+
void notifier_notify(void)
5560
{
5661
struct notify *notify = *arch_notify_get();
5762
struct list_item *wlist;
5863
struct notifier *n;
5964

60-
spin_lock(&notify->lock);
65+
if (!list_is_empty(&notify->list)) {
66+
dcache_invalidate_region(&_notify_data, sizeof(_notify_data));
67+
dcache_invalidate_region(_notify_data.data,
68+
_notify_data.data_size);
69+
70+
/* iterate through notifiers and send event to
71+
* interested clients
72+
*/
73+
list_for_item(wlist, &notify->list) {
74+
n = container_of(wlist, struct notifier, list);
75+
if (n->id == _notify_data.id)
76+
n->cb(_notify_data.message, n->cb_data,
77+
_notify_data.data);
78+
}
79+
}
80+
}
6181

62-
if (list_is_empty(&notify->list))
63-
goto out;
82+
void notifier_event(struct notify_data *notify_data)
83+
{
84+
struct notify *notify = *arch_notify_get();
85+
struct idc_msg notify_msg = { IDC_MSG_NOTIFY, IDC_MSG_NOTIFY_EXT };
86+
int i = 0;
87+
88+
spin_lock(&notify->lock);
6489

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

68-
n = container_of(wlist, struct notifier, list);
69-
if (n->id == id)
70-
n->cb(message, n->cb_data, event_data);
94+
/* notify selected targets */
95+
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
96+
if (_notify_data.target_core_mask & (1 << i)) {
97+
if (i == cpu_get_id()) {
98+
notifier_notify();
99+
} else if (cpu_is_core_enabled(i)) {
100+
notify_msg.core = i;
101+
idc_send_msg(&notify_msg, IDC_BLOCKING);
102+
}
103+
}
71104
}
72105

73-
out:
74106
spin_unlock(&notify->lock);
75107
}
76108

test/cmocka/src/audio/pipeline/pipeline_mocks.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ int arch_cpu_is_core_enabled(int id)
9999

100100
void cpu_power_down_core(void) { }
101101

102+
void notifier_notify(void) { }
103+
102104
struct ipc_comp_dev *ipc_get_comp(struct ipc *ipc, uint32_t id)
103105
{
104106
(void)ipc;

test/cmocka/src/audio/pipeline/pipeline_mocks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ void cpu_power_down_core(void);
4646

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

49+
void notifier_notify(void);
50+
4951
struct pipeline_new_setup_data {
5052
struct sof_ipc_pipe_new ipc_data;
5153
struct comp_dev *comp_data;

0 commit comments

Comments
 (0)