Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
79d4ea1
interrupt: introduce a separate struct for cascading interrupts
lyakh Feb 11, 2019
b1306e8
interrupt: add a parameter to interrupt_unregister()
lyakh Feb 14, 2019
0a4cbc3
xtensa: only enable interrupts after allocating context
lyakh Feb 18, 2019
d4cd20a
byt, hsw: call arch_interrupt_clear() directly
lyakh Feb 19, 2019
e8aea53
cavs: don't call known dummy function
lyakh Feb 19, 2019
1fdb3a0
interrupt: unify interrupt_clear() and interrupt_set() functions
lyakh Feb 19, 2019
7b2bb57
interrupt: remove an unused function parameter
lyakh Feb 21, 2019
7a29d5e
interrupt: add a macro to distinguish DSP interrupts
lyakh Mar 18, 2019
6f27cbe
interrupt: introduce a list of interrupt controllers
lyakh Feb 21, 2019
e7873b6
cavs: optimise the interrupt handler
lyakh Feb 26, 2019
1a002f8
cavs: fix wrong interrupt masking
lyakh Jul 12, 2019
b6198cd
cavs: eliminate per-core interrupt controller descriptors
lyakh Feb 12, 2019
5aa0cc0
interrupt: add controller mask and unmask operations
lyakh Feb 21, 2019
0af63ec
interrupt: add a cpu argument to interrupt_(un)mask()
lyakh Feb 22, 2019
30c7bf9
interrupt: stop using SOF_IRQ_CPU()
lyakh Apr 30, 2019
0468e75
interrupt: SOF_IRQ_NUMBER() for DSP interrupts is not needed
lyakh Feb 22, 2019
7d00840
interrupt: use the parent IRQ instead of SOF_IRQ_NUMBER()
lyakh Feb 22, 2019
ef7a83e
schedule: add an irq private data member
lyakh Feb 22, 2019
aa3255a
idc: add an irq private data member
lyakh Feb 22, 2019
2af8e79
spi: remove the unused irq field
lyakh Feb 26, 2019
ed1aff4
interrupt: call the interrupt handler only for enabled descriptors
lyakh Feb 25, 2019
a9c4309
interrupt: switch from bitfields to dynamic interrupt mapping
lyakh Feb 26, 2019
df67a0e
interrupt: support arbitrary interrupt controller cascading
lyakh Feb 26, 2019
1e3ea00
interrupt: reduce the use of the container_of() macro
lyakh Mar 6, 2019
01c6818
interrupt: add doxygen documentation for struct irq_desc
lyakh Mar 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/arch/xtensa/drivers/idc.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ static struct idc **idc_get(void)
*/
void idc_enable_interrupts(int target_core, int source_core)
{
struct idc *idc = *idc_get();

idc_write(IPC_IDCCTL, target_core,
IPC_IDCCTL_IDCTBIE(source_core));
platform_interrupt_unmask(PLATFORM_IDC_INTERRUPT(target_core), 0);
interrupt_unmask(idc->irq, target_core);
}

/**
Expand Down Expand Up @@ -347,11 +349,15 @@ int arch_idc_init(void)
SOF_TASK_PRI_IDC, idc_do_cmd, *idc, core, 0);

/* configure interrupt */
ret = interrupt_register(PLATFORM_IDC_INTERRUPT(core), IRQ_AUTO_UNMASK,
idc_irq_handler, *idc);
(*idc)->irq = interrupt_get_irq(PLATFORM_IDC_INTERRUPT,
PLATFORM_IDC_INTERRUPT_NAME);
if ((*idc)->irq < 0)
return (*idc)->irq;
ret = interrupt_register((*idc)->irq, IRQ_AUTO_UNMASK, idc_irq_handler,
*idc);
if (ret < 0)
return ret;
interrupt_enable(PLATFORM_IDC_INTERRUPT(core));
interrupt_enable((*idc)->irq, *idc);

/* enable BUSY and DONE (only for master core) interrupts */
idc_write(IPC_IDCCTL, core,
Expand All @@ -373,8 +379,8 @@ void idc_free(void)
trace_idc("idc_free()");

/* disable and unregister interrupt */
interrupt_disable(PLATFORM_IDC_INTERRUPT(core));
interrupt_unregister(PLATFORM_IDC_INTERRUPT(core));
interrupt_disable(idc->irq, idc);
interrupt_unregister(idc->irq, idc);

/* clear BUSY bits */
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
Expand Down
10 changes: 5 additions & 5 deletions src/arch/xtensa/include/arch/drivers/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,26 @@
#ifndef __ARCH_DRIVERS_INTERRUPT_H__
#define __ARCH_DRIVERS_INTERRUPT_H__

#include <sof/drivers/interrupt-map.h>
#include <xtensa/hal.h>
#include <xtensa/xtruntime.h>
#include <stddef.h>
#include <stdint.h>

extern char irq_name_level2[];
extern char irq_name_level3[];
extern char irq_name_level4[];
extern char irq_name_level5[];

static inline int arch_interrupt_register(int irq,
void (*handler)(void *arg), void *arg)
{
irq = SOF_IRQ_NUMBER(irq);
xthal_set_intclear(0x1 << irq);
_xtos_set_interrupt_handler_arg(irq, handler, arg);
return 0;
}

static inline void arch_interrupt_unregister(int irq)
{
irq = SOF_IRQ_NUMBER(irq);
_xtos_set_interrupt_handler_arg(irq, NULL, NULL);
}

Expand All @@ -53,13 +55,11 @@ static inline uint32_t arch_interrupt_get_level(void)

static inline void arch_interrupt_set(int irq)
{
irq = SOF_IRQ_NUMBER(irq);
xthal_set_intset(0x1 << irq);
}

static inline void arch_interrupt_clear(int irq)
{
irq = SOF_IRQ_NUMBER(irq);
xthal_set_intclear(0x1 << irq);
}

Expand Down
10 changes: 9 additions & 1 deletion src/arch/xtensa/include/arch/drivers/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@
#include <sof/drivers/interrupt.h>
#include <stdint.h>

struct timer_irq {
int logical_irq;
void *irq_arg;
};

struct timer {
uint32_t id;
uint32_t irq;
int irq;
const char *irq_name;
unsigned int core;
void *timer_data; /* used by core */
struct timer_irq *tirq; /* dynamic non-cacheable IRQ data */
uint32_t hitime; /* high end of 64bit timer */
uint32_t hitimeout;
uint32_t lowtimeout;
Expand Down
8 changes: 1 addition & 7 deletions src/arch/xtensa/include/arch/schedule/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@

#include <sof/list.h>
#include <sof/spinlock.h>
#include <stdint.h>

/** \brief IRQ task data. */
struct irq_task {
spinlock_t lock; /**< lock */
struct list_item list; /**< list of tasks */
uint32_t irq; /**< IRQ level */
Comment thread
tlauda marked this conversation as resolved.
Outdated
int irq; /**< IRQ level */
};

struct task;
Expand Down Expand Up @@ -63,11 +62,6 @@ int arch_allocate_tasks(void);
*/
void arch_free_tasks(void);

/**
* \brief Assigns IRQ tasks to interrupts.
*/
int arch_assign_tasks(void);

#endif /* __ARCH_SCHEDULE_TASK_H__ */

#else
Expand Down
1 change: 0 additions & 1 deletion src/arch/xtensa/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ int arch_init(struct sof *sof)
{
initialize_pointers_per_core();
register_exceptions();
arch_assign_tasks();
return 0;
}

Expand Down
145 changes: 63 additions & 82 deletions src/arch/xtensa/schedule/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,32 @@ struct irq_task **task_irq_high_get(void)
return &ctx->irq_high_task;
}

/**
* \brief Retrieves task IRQ level.
* \param[in,out] task Task data.
* \return IRQ level.
*/
static uint32_t task_get_irq(struct task *task)
static struct irq_task *task_get_irq_task(struct task *task)
{
uint32_t irq;

switch (task->priority) {
#ifdef CONFIG_TASK_HAVE_PRIORITY_MEDIUM
case SOF_TASK_PRI_MED + 1 ... SOF_TASK_PRI_LOW:
irq = PLATFORM_IRQ_TASK_LOW;
break;
return *task_irq_low_get();
case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1:
irq = PLATFORM_IRQ_TASK_HIGH;
break;
return *task_irq_high_get();
case SOF_TASK_PRI_MED:
return *task_irq_med_get();
#elif CONFIG_TASK_HAVE_PRIORITY_LOW
case SOF_TASK_PRI_MED ... SOF_TASK_PRI_LOW:
return *task_irq_low_get();
case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1:
return *task_irq_high_get();
#else
case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_LOW:
return *task_irq_high_get();
#endif
default:
irq = PLATFORM_IRQ_TASK_MED;
break;
trace_error(TRACE_CLASS_IRQ,
"task_get_irq_task() error: task priority %d",
task->priority);
}

return irq;
return NULL;
}

/**
Expand All @@ -79,39 +82,12 @@ static uint32_t task_get_irq(struct task *task)
*/
static int task_set_data(struct task *task)
{
struct list_item *dst = NULL;
struct irq_task *irq_task;
uint32_t flags;
struct irq_task *irq_task = task_get_irq_task(task);
struct list_item *dst;
unsigned long flags;

switch (task->priority) {
#if CONFIG_TASK_HAVE_PRIORITY_MEDIUM
case SOF_TASK_PRI_MED + 1 ... SOF_TASK_PRI_LOW:
irq_task = *task_irq_low_get();
break;
case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1:
irq_task = *task_irq_high_get();
break;
case SOF_TASK_PRI_MED:
irq_task = *task_irq_med_get();
break;
#elif CONFIG_TASK_HAVE_PRIORITY_LOW
case SOF_TASK_PRI_MED ... SOF_TASK_PRI_LOW:
irq_task = *task_irq_low_get();
break;
case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1:
irq_task = *task_irq_high_get();
break;
#else
case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_LOW:
irq_task = *task_irq_high_get();
break;
#endif
default:
trace_error(TRACE_CLASS_IRQ,
"task_set_data() error: task priority %d",
task->priority);
if (!irq_task)
return -EINVAL;
}

dst = &irq_task->list;
spin_lock_irq(&irq_task->lock, flags);
Expand Down Expand Up @@ -165,30 +141,42 @@ static void _irq_task(void *arg)

int arch_run_task(struct task *task)
{
uint32_t irq;
struct irq_task *irq_task = task_get_irq_task(task);
int ret;

if (!irq_task)
return -EINVAL;

ret = task_set_data(task);

if (ret < 0)
return ret;

irq = task_get_irq(task);
interrupt_set(irq);
interrupt_set(irq_task->irq);

return 0;
}

int arch_allocate_tasks(void)
{
int ret;

#if CONFIG_TASK_HAVE_PRIORITY_LOW
/* irq low */
struct irq_task **low = task_irq_low_get();
*low = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**low));

list_init(&((*low)->list));
spinlock_init(&((*low)->lock));
(*low)->irq = PLATFORM_IRQ_TASK_LOW;
(*low)->irq = interrupt_get_irq(PLATFORM_IRQ_TASK_LOW,
PLATFORM_IRQ_TASK_LOW_NAME);
if ((*low)->irq < 0)
return (*low)->irq;

ret = interrupt_register((*low)->irq, IRQ_AUTO_UNMASK, _irq_task, low);
if (ret < 0)
return ret;
interrupt_enable((*low)->irq, low);
#endif

#if CONFIG_TASK_HAVE_PRIORITY_MEDIUM
Expand All @@ -198,7 +186,15 @@ int arch_allocate_tasks(void)

list_init(&((*med)->list));
spinlock_init(&((*med)->lock));
(*med)->irq = PLATFORM_IRQ_TASK_MED;
(*med)->irq = interrupt_get_irq(PLATFORM_IRQ_TASK_MED,
PLATFORM_IRQ_TASK_MED_NAME);
if ((*med)->irq < 0)
return (*med)->irq;

ret = interrupt_register((*med)->irq, IRQ_AUTO_UNMASK, _irq_task, med);
if (ret < 0)
return ret;
interrupt_enable((*med)->irq, med);
#endif

/* irq high */
Expand All @@ -207,7 +203,16 @@ int arch_allocate_tasks(void)

list_init(&((*high)->list));
spinlock_init(&((*high)->lock));
(*high)->irq = PLATFORM_IRQ_TASK_HIGH;
(*high)->irq = interrupt_get_irq(PLATFORM_IRQ_TASK_HIGH,
PLATFORM_IRQ_TASK_HIGH_NAME);
if ((*high)->irq < 0)
return (*high)->irq;

ret = interrupt_register((*high)->irq, IRQ_AUTO_UNMASK, _irq_task,
high);
if (ret < 0)
return ret;
interrupt_enable((*high)->irq, high);

return 0;
}
Expand All @@ -222,8 +227,8 @@ void arch_free_tasks(void)
struct irq_task **low = task_irq_low_get();

spin_lock_irq(&(*low)->lock, flags);
interrupt_disable(PLATFORM_IRQ_TASK_LOW);
interrupt_unregister(PLATFORM_IRQ_TASK_LOW);
interrupt_disable((*low)->irq, low);
interrupt_unregister((*low)->irq, low);
list_item_del(&(*low)->list);
spin_unlock_irq(&(*low)->lock, flags);
#endif
Expand All @@ -233,8 +238,8 @@ void arch_free_tasks(void)
struct irq_task **med = task_irq_med_get();

spin_lock_irq(&(*med)->lock, flags);
interrupt_disable(PLATFORM_IRQ_TASK_MED);
interrupt_unregister(PLATFORM_IRQ_TASK_MED);
interrupt_disable((*med)->irq, med);
interrupt_unregister((*med)->irq, med);
list_item_del(&(*med)->list);
spin_unlock_irq(&(*med)->lock, flags);
#endif
Expand All @@ -243,32 +248,8 @@ void arch_free_tasks(void)
struct irq_task **high = task_irq_high_get();

spin_lock_irq(&(*high)->lock, flags);
interrupt_disable(PLATFORM_IRQ_TASK_HIGH);
interrupt_unregister(PLATFORM_IRQ_TASK_HIGH);
interrupt_disable((*high)->irq, high);
interrupt_unregister((*high)->irq, high);
list_item_del(&(*high)->list);
spin_unlock_irq(&(*high)->lock, flags);
}

int arch_assign_tasks(void)
{
#if CONFIG_TASK_HAVE_PRIORITY_LOW
/* irq low */
interrupt_register(PLATFORM_IRQ_TASK_LOW, IRQ_AUTO_UNMASK, _irq_task,
task_irq_low_get());
interrupt_enable(PLATFORM_IRQ_TASK_LOW);
#endif

#if CONFIG_TASK_HAVE_PRIORITY_MEDIUM
/* irq medium */
interrupt_register(PLATFORM_IRQ_TASK_MED, IRQ_AUTO_UNMASK, _irq_task,
task_irq_med_get());
interrupt_enable(PLATFORM_IRQ_TASK_MED);
#endif

/* irq high */
interrupt_register(PLATFORM_IRQ_TASK_HIGH, IRQ_AUTO_UNMASK, _irq_task,
task_irq_high_get());
interrupt_enable(PLATFORM_IRQ_TASK_HIGH);

return 0;
}
Loading