Skip to content

Commit

Permalink
Blackfin/ipipe: upgrade to I-pipe mainline
Browse files Browse the repository at this point in the history
This patch introduces Blackfin-specific bits to support the current
tip of the interrupt pipeline development, mainly:

- 2/3-level interrupt maps (sparse IRQs)
- generic virq handling
- sysinfo v2 format for ipipe_get_sysinfo()

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
  • Loading branch information
Philippe Gerum authored and Mike Frysinger committed Mar 18, 2011
1 parent 8944b5a commit 5b5da4c
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 114 deletions.
95 changes: 32 additions & 63 deletions arch/blackfin/include/asm/ipipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
#include <asm/traps.h>
#include <asm/bitsperlong.h>

#define IPIPE_ARCH_STRING "1.12-00"
#define IPIPE_ARCH_STRING "1.16-01"
#define IPIPE_MAJOR_NUMBER 1
#define IPIPE_MINOR_NUMBER 12
#define IPIPE_PATCH_NUMBER 0
#define IPIPE_MINOR_NUMBER 16
#define IPIPE_PATCH_NUMBER 1

#ifdef CONFIG_SMP
#error "I-pipe/blackfin: SMP not implemented"
Expand All @@ -55,25 +56,19 @@ do { \
#define task_hijacked(p) \
({ \
int __x__ = __ipipe_root_domain_p; \
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
if (__x__) \
hard_local_irq_enable(); \
hard_local_irq_enable(); \
!__x__; \
})

struct ipipe_domain;

struct ipipe_sysinfo {

int ncpus; /* Number of CPUs on board */
u64 cpufreq; /* CPU frequency (in Hz) */

/* Arch-dependent block */

struct {
unsigned tmirq; /* Timer tick IRQ */
u64 tmfreq; /* Timer frequency */
} archdep;
int sys_nr_cpus; /* Number of CPUs on board */
int sys_hrtimer_irq; /* hrtimer device IRQ */
u64 sys_hrtimer_freq; /* hrtimer device frequency */
u64 sys_hrclock_freq; /* hrclock device frequency */
u64 sys_cpu_freq; /* CPU frequency (Hz) */
};

#define ipipe_read_tsc(t) \
Expand Down Expand Up @@ -115,9 +110,19 @@ void __ipipe_enable_irqdesc(struct ipipe_domain *ipd,
void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
unsigned irq);

#define __ipipe_enable_irq(irq) (irq_desc[irq].chip->unmask(irq))
#define __ipipe_enable_irq(irq) \
do { \
struct irq_desc *desc = irq_to_desc(irq); \
struct irq_chip *chip = get_irq_desc_chip(desc); \
chip->irq_unmask(&desc->irq_data); \
} while (0)

#define __ipipe_disable_irq(irq) (irq_desc[irq].chip->mask(irq))
#define __ipipe_disable_irq(irq) \
do { \
struct irq_desc *desc = irq_to_desc(irq); \
struct irq_chip *chip = get_irq_desc_chip(desc); \
chip->irq_mask(&desc->irq_data); \
} while (0)

static inline int __ipipe_check_tickdev(const char *devname)
{
Expand All @@ -128,12 +133,11 @@ void __ipipe_enable_pipeline(void);

#define __ipipe_hook_critical_ipi(ipd) do { } while (0)

#define __ipipe_sync_pipeline ___ipipe_sync_pipeline
void ___ipipe_sync_pipeline(unsigned long syncmask);
void ___ipipe_sync_pipeline(void);

void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);

int __ipipe_get_irq_priority(unsigned irq);
int __ipipe_get_irq_priority(unsigned int irq);

void __ipipe_serial_debug(const char *fmt, ...);

Expand All @@ -152,7 +156,10 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
return ffs(ul) - 1;
}

#define __ipipe_run_irqtail() /* Must be a macro */ \
#define __ipipe_do_root_xirq(ipd, irq) \
((ipd)->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)))

#define __ipipe_run_irqtail(irq) /* Must be a macro */ \
do { \
unsigned long __pending; \
CSYNC(); \
Expand All @@ -164,42 +171,8 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
} \
} while (0)

#define __ipipe_run_isr(ipd, irq) \
do { \
if (!__ipipe_pipeline_head_p(ipd)) \
hard_local_irq_enable(); \
if (ipd == ipipe_root_domain) { \
if (unlikely(ipipe_virtual_irq_p(irq))) { \
irq_enter(); \
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
irq_exit(); \
} else \
ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
} else { \
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
/* Attempt to exit the outer interrupt level before \
* starting the deferred IRQ processing. */ \
__ipipe_run_irqtail(); \
__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
} \
hard_local_irq_disable(); \
} while (0)

#define __ipipe_syscall_watched_p(p, sc) \
(((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls)

void ipipe_init_irq_threads(void);

int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);

#ifdef CONFIG_TICKSOURCE_CORETMR
#define IRQ_SYSTMR IRQ_CORETMR
#define IRQ_PRIOTMR IRQ_CORETMR
#else
#define IRQ_SYSTMR IRQ_TIMER0
#define IRQ_PRIOTMR CONFIG_IRQ_TIMER0
#endif
(ipipe_notifier_enabled_p(p) || (unsigned long)sc >= NR_syscalls)

#ifdef CONFIG_BF561
#define bfin_write_TIMER_DISABLE(val) bfin_write_TMRS8_DISABLE(val)
Expand All @@ -219,22 +192,18 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);

#define task_hijacked(p) 0
#define ipipe_trap_notify(t, r) 0
#define __ipipe_root_tick_p(regs) 1

#define ipipe_init_irq_threads() do { } while (0)
#define ipipe_start_irq_thread(irq, desc) 0
#endif /* !CONFIG_IPIPE */

#ifndef CONFIG_TICKSOURCE_GPTMR0
#ifdef CONFIG_TICKSOURCE_CORETMR
#define IRQ_SYSTMR IRQ_CORETMR
#define IRQ_PRIOTMR IRQ_CORETMR
#else
#define IRQ_SYSTMR IRQ_TIMER0
#define IRQ_PRIOTMR CONFIG_IRQ_TIMER0
#endif

#define __ipipe_root_tick_p(regs) 1

#endif /* !CONFIG_IPIPE */

#define ipipe_update_tick_evtdev(evtdev) do { } while (0)

#endif /* !__ASM_BLACKFIN_IPIPE_H */
11 changes: 9 additions & 2 deletions arch/blackfin/include/asm/ipipe_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@

#ifdef CONFIG_IPIPE

#include <asm/bitsperlong.h>
#include <mach/irq.h>

#define IPIPE_NR_XIRQS NR_IRQS
#define IPIPE_IRQ_ISHIFT 5 /* 2^5 for 32bits arch. */

/* Blackfin-specific, per-cpu pipeline status */
#define IPIPE_SYNCDEFER_FLAG 15
Expand All @@ -42,11 +44,14 @@
#define IPIPE_EVENT_INIT (IPIPE_FIRST_EVENT + 4)
#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 5)
#define IPIPE_EVENT_CLEANUP (IPIPE_FIRST_EVENT + 6)
#define IPIPE_LAST_EVENT IPIPE_EVENT_CLEANUP
#define IPIPE_EVENT_RETURN (IPIPE_FIRST_EVENT + 7)
#define IPIPE_LAST_EVENT IPIPE_EVENT_RETURN
#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1)

#define IPIPE_TIMER_IRQ IRQ_CORETMR

#define __IPIPE_FEATURE_SYSINFO_V2 1

#ifndef __ASSEMBLY__

extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
Expand All @@ -63,6 +68,8 @@ void __ipipe_unlock_root(void);

#endif /* !__ASSEMBLY__ */

#define __IPIPE_FEATURE_SYSINFO_V2 1

#endif /* CONFIG_IPIPE */

#endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */
84 changes: 39 additions & 45 deletions arch/blackfin/kernel/ipipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
* pending for it.
*/
if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) &&
ipipe_head_cpudom_var(irqpend_himask) == 0)
!__ipipe_ipending_p(ipipe_head_cpudom_ptr()))
goto out;

__ipipe_walk_pipeline(head);
Expand Down Expand Up @@ -185,25 +185,21 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
}
EXPORT_SYMBOL(__ipipe_disable_irqdesc);

int __ipipe_syscall_root(struct pt_regs *regs)
asmlinkage int __ipipe_syscall_root(struct pt_regs *regs)
{
struct ipipe_percpu_domain_data *p;
unsigned long flags;
void (*hook)(void);
int ret;

WARN_ON_ONCE(irqs_disabled_hw());

/*
* We need to run the IRQ tail hook whenever we don't
* propagate a syscall to higher domains, because we know that
* important operations might be pending there (e.g. Xenomai
* deferred rescheduling).
* We need to run the IRQ tail hook each time we intercept a
* syscall, because we know that important operations might be
* pending there (e.g. Xenomai deferred rescheduling).
*/

if (regs->orig_p0 < NR_syscalls) {
void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
hook();
if ((current->flags & PF_EVNOTIFY) == 0)
return 0;
}
hook = (__typeof__(hook))__ipipe_irq_tail_hook;
hook();

/*
* This routine either returns:
Expand All @@ -214,51 +210,47 @@ int __ipipe_syscall_root(struct pt_regs *regs)
* tail work has to be performed (for handling signals etc).
*/

if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
if (!__ipipe_syscall_watched_p(current, regs->orig_p0) ||
!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
return 0;

ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);

flags = hard_local_irq_save();
hard_local_irq_disable();

if (!__ipipe_root_domain_p) {
hard_local_irq_restore(flags);
return 1;
/*
* This is the end of the syscall path, so we may
* safely assume a valid Linux task stack here.
*/
if (current->ipipe_flags & PF_EVTRET) {
current->ipipe_flags &= ~PF_EVTRET;
__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
}

p = ipipe_root_cpudom_ptr();
if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
if (!__ipipe_root_domain_p)
ret = -1;
else {
p = ipipe_root_cpudom_ptr();
if (__ipipe_ipending_p(p))
__ipipe_sync_pipeline();
}

hard_local_irq_restore(flags);
hard_local_irq_enable();

return -ret;
}

unsigned long ipipe_critical_enter(void (*syncfn) (void))
{
unsigned long flags;

flags = hard_local_irq_save();

return flags;
}

void ipipe_critical_exit(unsigned long flags)
{
hard_local_irq_restore(flags);
}

static void __ipipe_no_irqtail(void)
{
}

int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
{
info->ncpus = num_online_cpus();
info->cpufreq = ipipe_cpu_freq();
info->archdep.tmirq = IPIPE_TIMER_IRQ;
info->archdep.tmfreq = info->cpufreq;
info->sys_nr_cpus = num_online_cpus();
info->sys_cpu_freq = ipipe_cpu_freq();
info->sys_hrtimer_irq = IPIPE_TIMER_IRQ;
info->sys_hrtimer_freq = __ipipe_core_clock;
info->sys_hrclock_freq = __ipipe_core_clock;

return 0;
}
Expand Down Expand Up @@ -289,6 +281,7 @@ int ipipe_trigger_irq(unsigned irq)
asmlinkage void __ipipe_sync_root(void)
{
void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
struct ipipe_percpu_domain_data *p;
unsigned long flags;

BUG_ON(irqs_disabled());
Expand All @@ -300,19 +293,20 @@ asmlinkage void __ipipe_sync_root(void)

clear_thread_flag(TIF_IRQ_SYNC);

if (ipipe_root_cpudom_var(irqpend_himask) != 0)
__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
p = ipipe_root_cpudom_ptr();
if (__ipipe_ipending_p(p))
__ipipe_sync_pipeline();

hard_local_irq_restore(flags);
}

void ___ipipe_sync_pipeline(unsigned long syncmask)
void ___ipipe_sync_pipeline(void)
{
if (__ipipe_root_domain_p &&
test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
return;

__ipipe_sync_stage(syncmask);
__ipipe_sync_stage();
}

void __ipipe_disable_root_irqs_hw(void)
Expand Down
Loading

0 comments on commit 5b5da4c

Please sign in to comment.