Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/arch/xtensa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ else()
)
endif()

add_local_sources(sof timer.c)
add_local_sources(sof task.c timer.c)

if(CONFIG_GDB_DEBUG)
add_subdirectory(gdb)
Expand Down
223 changes: 9 additions & 214 deletions src/arch/xtensa/include/arch/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@
#ifndef __ARCH_TASK_H_
#define __ARCH_TASK_H_

#include <sof/schedule.h>
#include <sof/interrupt.h>
#include <platform/platform.h>
#include <sof/debug.h>
#include <sof/alloc.h>
#include <sof/list.h>

#include <arch/spinlock.h>

/** \brief IRQ task data. */
struct irq_task {
Expand All @@ -51,6 +49,8 @@ struct irq_task {
uint32_t irq; /**< IRQ level */
};

struct task;

/**
* \brief Returns IRQ low task data.
* \return Pointer to pointer of IRQ low task data.
Expand All @@ -69,231 +69,26 @@ struct irq_task **task_irq_med_get(void);
*/
struct irq_task **task_irq_high_get(void);

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

switch (task->priority) {
case TASK_PRI_MED + 1 ... TASK_PRI_LOW:
irq = PLATFORM_IRQ_TASK_LOW;
break;
case TASK_PRI_HIGH ... TASK_PRI_MED - 1:
irq = PLATFORM_IRQ_TASK_HIGH;
break;
case TASK_PRI_MED:
default:
irq = PLATFORM_IRQ_TASK_MED;
break;
}

return irq;
}

/**
* \brief Adds task to the list per IRQ level.
* \param[in,out] task Task data.
*/
static inline int task_set_data(struct task *task)
{
struct list_item *dst = NULL;
struct irq_task *irq_task;
uint32_t flags;

switch (task->priority) {
#ifdef CONFIG_TASK_HAVE_PRIORITY_MEDIUM
case TASK_PRI_MED + 1 ... TASK_PRI_LOW:
irq_task = *task_irq_low_get();
break;
case TASK_PRI_HIGH ... TASK_PRI_MED - 1:
irq_task = *task_irq_high_get();
break;
case TASK_PRI_MED:
irq_task = *task_irq_med_get();
break;
#else
case TASK_PRI_MED ... TASK_PRI_LOW:
irq_task = *task_irq_low_get();
break;
case TASK_PRI_HIGH ... TASK_PRI_MED - 1:
irq_task = *task_irq_high_get();
break;
#endif
default:
trace_error(TRACE_CLASS_IRQ,
"task_set_data() error: task priority %d",
task->priority);
return -EINVAL;
}

dst = &irq_task->list;
spin_lock_irq(&irq_task->lock, flags);
list_item_append(&task->irq_list, dst);
spin_unlock_irq(&irq_task->lock, flags);

return 0;
}

/**
* \brief Interrupt handler for the IRQ task.
* \param[in,out] arg IRQ task data.
*/
static void _irq_task(void *arg)
{
struct irq_task *irq_task = *(struct irq_task **)arg;
struct list_item *tlist;
struct list_item *clist;
struct task *task;
uint32_t flags;
int run_task = 0;

spin_lock_irq(&irq_task->lock, flags);

interrupt_clear(irq_task->irq);

list_for_item_safe(clist, tlist, &irq_task->list) {

task = container_of(clist, struct task, irq_list);
list_item_del(clist);

if (task->func && task->state == TASK_STATE_PENDING) {
schedule_task_running(task);
run_task = 1;
} else {
run_task = 0;
}

/* run task without holding task lock */
spin_unlock_irq(&irq_task->lock, flags);

if (run_task)
task->func(task->data);

spin_lock_irq(&irq_task->lock, flags);
schedule_task_complete(task);
}

spin_unlock_irq(&irq_task->lock, flags);
}

/**
* \brief Runs task.
* \param[in,out] task Task data.
*/
static inline int arch_run_task(struct task *task)
{
uint32_t irq;
int ret;

ret = task_set_data(task);

if (ret < 0)
return ret;

irq = task_get_irq(task);
interrupt_set(irq);

return 0;
}
int arch_run_task(struct task *task);

/**
* \brief Allocates IRQ tasks.
*/
static inline int arch_allocate_tasks(void)
{
/* 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;

#ifdef CONFIG_TASK_HAVE_PRIORITY_MEDIUM
/* irq medium */
struct irq_task **med = task_irq_med_get();
*med = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**med));

list_init(&((*med)->list));
spinlock_init(&((*med)->lock));
(*med)->irq = PLATFORM_IRQ_TASK_MED;
#endif

/* irq high */
struct irq_task **high = task_irq_high_get();
*high = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**high));

list_init(&((*high)->list));
spinlock_init(&((*high)->lock));
(*high)->irq = PLATFORM_IRQ_TASK_HIGH;

return 0;
}
int arch_allocate_tasks(void);

/**
* \brief Frees IRQ tasks.
*/
static inline void arch_free_tasks(void)
{
uint32_t flags;
/* TODO: do not want to free the tasks, just the entire heap */
/* free IRQ low task */
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);
list_item_del(&(*low)->list);
spin_unlock_irq(&(*low)->lock, flags);

#ifdef CONFIG_TASK_HAVE_PRIORITY_MEDIUM
/* free IRQ medium task */
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);
list_item_del(&(*med)->list);
spin_unlock_irq(&(*med)->lock, flags);
#endif

/* free IRQ high task */
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);
list_item_del(&(*high)->list);
spin_unlock_irq(&(*high)->lock, flags);
}
void arch_free_tasks(void);

/**
* \brief Assigns IRQ tasks to interrupts.
*/
static inline int arch_assign_tasks(void)
{
/* irq low */
interrupt_register(PLATFORM_IRQ_TASK_LOW, IRQ_AUTO_UNMASK, _irq_task,
task_irq_low_get());
interrupt_enable(PLATFORM_IRQ_TASK_LOW);

#ifdef 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);
int arch_assign_tasks(void);

return 0;
}

#endif
5 changes: 5 additions & 0 deletions src/arch/xtensa/include/arch/wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/

#ifndef __ARCH_WAIT_H_
#define __ARCH_WAIT_H_

#include <xtensa/xtruntime.h>
#include <arch/interrupt.h>
#include <sof/panic.h>

#include <uapi/ipc/trace.h>

#if defined(PLATFORM_WAITI_DELAY)

Expand Down Expand Up @@ -78,3 +82,4 @@ static inline void idelay(int n)
}
}

#endif
1 change: 1 addition & 0 deletions src/arch/xtensa/smp/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <sof/init.h>
#include <sof/lock.h>
#include <sof/notifier.h>
#include <sof/schedule.h>
#include <sof/task.h>
#include <platform/idc.h>
#include <stdint.h>
Expand Down
Loading