Commit 9bd50df6 authored by Philippe Gerum's avatar Philippe Gerum Committed by Bryan Wu

Blackfin arch: Update adeos blackfin arch patch to 1.9-00

Signed-off-by: default avatarPhilippe Gerum <rpm@xenomai.org>
Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
parent 97d4b35f
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/traps.h> #include <asm/traps.h>
#define IPIPE_ARCH_STRING "1.8-00" #define IPIPE_ARCH_STRING "1.9-00"
#define IPIPE_MAJOR_NUMBER 1 #define IPIPE_MAJOR_NUMBER 1
#define IPIPE_MINOR_NUMBER 8 #define IPIPE_MINOR_NUMBER 9
#define IPIPE_PATCH_NUMBER 0 #define IPIPE_PATCH_NUMBER 0
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -83,9 +83,9 @@ struct ipipe_sysinfo { ...@@ -83,9 +83,9 @@ struct ipipe_sysinfo {
"%2 = CYCLES2\n" \ "%2 = CYCLES2\n" \
"CC = %2 == %0\n" \ "CC = %2 == %0\n" \
"if ! CC jump 1b\n" \ "if ! CC jump 1b\n" \
: "=r" (((unsigned long *)&t)[1]), \ : "=d,a" (((unsigned long *)&t)[1]), \
"=r" (((unsigned long *)&t)[0]), \ "=d,a" (((unsigned long *)&t)[0]), \
"=r" (__cy2) \ "=d,a" (__cy2) \
: /*no input*/ : "CC"); \ : /*no input*/ : "CC"); \
t; \ t; \
}) })
...@@ -118,35 +118,40 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, ...@@ -118,35 +118,40 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
#define __ipipe_disable_irq(irq) (irq_desc[irq].chip->mask(irq)) #define __ipipe_disable_irq(irq) (irq_desc[irq].chip->mask(irq))
#define __ipipe_lock_root() \ static inline int __ipipe_check_tickdev(const char *devname)
set_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags) {
return 1;
}
#define __ipipe_unlock_root() \ static inline void __ipipe_lock_root(void)
clear_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags) {
set_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status));
}
static inline void __ipipe_unlock_root(void)
{
clear_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status));
}
void __ipipe_enable_pipeline(void); void __ipipe_enable_pipeline(void);
#define __ipipe_hook_critical_ipi(ipd) do { } while (0) #define __ipipe_hook_critical_ipi(ipd) do { } while (0)
#define __ipipe_sync_pipeline(syncmask) \ #define __ipipe_sync_pipeline ___ipipe_sync_pipeline
do { \ void ___ipipe_sync_pipeline(unsigned long syncmask);
struct ipipe_domain *ipd = ipipe_current_domain; \
if (likely(ipd != ipipe_root_domain || !test_bit(IPIPE_ROOTLOCK_FLAG, &ipd->flags))) \
__ipipe_sync_stage(syncmask); \
} while (0)
void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs); void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
int __ipipe_get_irq_priority(unsigned irq); int __ipipe_get_irq_priority(unsigned irq);
int __ipipe_get_irqthread_priority(unsigned irq);
void __ipipe_stall_root_raw(void); void __ipipe_stall_root_raw(void);
void __ipipe_unstall_root_raw(void); void __ipipe_unstall_root_raw(void);
void __ipipe_serial_debug(const char *fmt, ...); void __ipipe_serial_debug(const char *fmt, ...);
asmlinkage void __ipipe_call_irqtail(unsigned long addr);
DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs); DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
extern unsigned long __ipipe_core_clock; extern unsigned long __ipipe_core_clock;
...@@ -162,42 +167,25 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul) ...@@ -162,42 +167,25 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
#define __ipipe_run_irqtail() /* Must be a macro */ \ #define __ipipe_run_irqtail() /* Must be a macro */ \
do { \ do { \
asmlinkage void __ipipe_call_irqtail(void); \
unsigned long __pending; \ unsigned long __pending; \
CSYNC(); \ CSYNC(); \
__pending = bfin_read_IPEND(); \ __pending = bfin_read_IPEND(); \
if (__pending & 0x8000) { \ if (__pending & 0x8000) { \
__pending &= ~0x8010; \ __pending &= ~0x8010; \
if (__pending && (__pending & (__pending - 1)) == 0) \ if (__pending && (__pending & (__pending - 1)) == 0) \
__ipipe_call_irqtail(); \ __ipipe_call_irqtail(__ipipe_irq_tail_hook); \
} \ } \
} while (0) } while (0)
#define __ipipe_run_isr(ipd, irq) \ #define __ipipe_run_isr(ipd, irq) \
do { \ do { \
if (ipd == ipipe_root_domain) { \ if (ipd == ipipe_root_domain) { \
/* \ local_irq_enable_hw(); \
* Note: the I-pipe implements a threaded interrupt model on \ if (ipipe_virtual_irq_p(irq)) \
* this arch for Linux external IRQs. The interrupt handler we \
* call here only wakes up the associated IRQ thread. \
*/ \
if (ipipe_virtual_irq_p(irq)) { \
/* No irqtail here; virtual interrupts have no effect \
on IPEND so there is no need for processing \
deferral. */ \
local_irq_enable_nohead(ipd); \
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
local_irq_disable_nohead(ipd); \ else \
} else \
/* \
* No need to run the irqtail here either; \
* we can't be preempted by hw IRQs, so \
* non-Linux IRQs cannot stack over the short \
* thread wakeup code. Which in turn means \
* that no irqtail condition could be pending \
* for domains above Linux in the pipeline. \
*/ \
ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \ ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
local_irq_disable_hw(); \
} else { \ } else { \
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ __clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
local_irq_enable_nohead(ipd); \ local_irq_enable_nohead(ipd); \
...@@ -217,42 +205,24 @@ void ipipe_init_irq_threads(void); ...@@ -217,42 +205,24 @@ void ipipe_init_irq_threads(void);
int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc); int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
#define IS_SYSIRQ(irq) ((irq) > IRQ_CORETMR && (irq) <= SYS_IRQS) #ifdef CONFIG_GENERIC_CLOCKEVENTS
#define IS_GPIOIRQ(irq) ((irq) >= GPIO_IRQ_BASE && (irq) < NR_IRQS) #define IRQ_SYSTMR IRQ_CORETMR
#define IRQ_PRIOTMR IRQ_CORETMR
#else
#define IRQ_SYSTMR IRQ_TIMER0 #define IRQ_SYSTMR IRQ_TIMER0
#define IRQ_PRIOTMR CONFIG_IRQ_TIMER0 #define IRQ_PRIOTMR CONFIG_IRQ_TIMER0
#endif
#if defined(CONFIG_BF531) || defined(CONFIG_BF532) || defined(CONFIG_BF533) #ifdef CONFIG_BF561
#define PRIO_GPIODEMUX(irq) CONFIG_PFA
#elif defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
#define PRIO_GPIODEMUX(irq) CONFIG_IRQ_PROG_INTA
#elif defined(CONFIG_BF52x)
#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PORTF_INTA ? CONFIG_IRQ_PORTF_INTA : \
(irq) == IRQ_PORTG_INTA ? CONFIG_IRQ_PORTG_INTA : \
(irq) == IRQ_PORTH_INTA ? CONFIG_IRQ_PORTH_INTA : \
-1)
#elif defined(CONFIG_BF561)
#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PROG0_INTA ? CONFIG_IRQ_PROG0_INTA : \
(irq) == IRQ_PROG1_INTA ? CONFIG_IRQ_PROG1_INTA : \
(irq) == IRQ_PROG2_INTA ? CONFIG_IRQ_PROG2_INTA : \
-1)
#define bfin_write_TIMER_DISABLE(val) bfin_write_TMRS8_DISABLE(val) #define bfin_write_TIMER_DISABLE(val) bfin_write_TMRS8_DISABLE(val)
#define bfin_write_TIMER_ENABLE(val) bfin_write_TMRS8_ENABLE(val) #define bfin_write_TIMER_ENABLE(val) bfin_write_TMRS8_ENABLE(val)
#define bfin_write_TIMER_STATUS(val) bfin_write_TMRS8_STATUS(val) #define bfin_write_TIMER_STATUS(val) bfin_write_TMRS8_STATUS(val)
#define bfin_read_TIMER_STATUS() bfin_read_TMRS8_STATUS() #define bfin_read_TIMER_STATUS() bfin_read_TMRS8_STATUS()
#elif defined(CONFIG_BF54x) #elif defined(CONFIG_BF54x)
#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PINT0 ? CONFIG_IRQ_PINT0 : \
(irq) == IRQ_PINT1 ? CONFIG_IRQ_PINT1 : \
(irq) == IRQ_PINT2 ? CONFIG_IRQ_PINT2 : \
(irq) == IRQ_PINT3 ? CONFIG_IRQ_PINT3 : \
-1)
#define bfin_write_TIMER_DISABLE(val) bfin_write_TIMER_DISABLE0(val) #define bfin_write_TIMER_DISABLE(val) bfin_write_TIMER_DISABLE0(val)
#define bfin_write_TIMER_ENABLE(val) bfin_write_TIMER_ENABLE0(val) #define bfin_write_TIMER_ENABLE(val) bfin_write_TIMER_ENABLE0(val)
#define bfin_write_TIMER_STATUS(val) bfin_write_TIMER_STATUS0(val) #define bfin_write_TIMER_STATUS(val) bfin_write_TIMER_STATUS0(val)
#define bfin_read_TIMER_STATUS(val) bfin_read_TIMER_STATUS0(val) #define bfin_read_TIMER_STATUS(val) bfin_read_TIMER_STATUS0(val)
#else
# error "no PRIO_GPIODEMUX() for this part"
#endif #endif
#define __ipipe_root_tick_p(regs) ((regs->ipend & 0x10) != 0) #define __ipipe_root_tick_p(regs) ((regs->ipend & 0x10) != 0)
...@@ -275,4 +245,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc); ...@@ -275,4 +245,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
#endif /* !CONFIG_IPIPE */ #endif /* !CONFIG_IPIPE */
#define ipipe_update_tick_evtdev(evtdev) do { } while (0)
#endif /* !__ASM_BLACKFIN_IPIPE_H */ #endif /* !__ASM_BLACKFIN_IPIPE_H */
/* -*- linux-c -*- /* -*- linux-c -*-
* include/asm-blackfin/_baseipipe.h * include/asm-blackfin/ipipe_base.h
* *
* Copyright (C) 2007 Philippe Gerum. * Copyright (C) 2007 Philippe Gerum.
* *
...@@ -27,8 +27,9 @@ ...@@ -27,8 +27,9 @@
#define IPIPE_NR_XIRQS NR_IRQS #define IPIPE_NR_XIRQS NR_IRQS
#define IPIPE_IRQ_ISHIFT 5 /* 2^5 for 32bits arch. */ #define IPIPE_IRQ_ISHIFT 5 /* 2^5 for 32bits arch. */
/* Blackfin-specific, global domain flags */ /* Blackfin-specific, per-cpu pipeline status */
#define IPIPE_ROOTLOCK_FLAG 1 /* Lock pipeline for root */ #define IPIPE_SYNCDEFER_FLAG 15
#define IPIPE_SYNCDEFER_MASK (1L << IPIPE_SYNCDEFER_MASK)
/* Blackfin traps -- i.e. exception vector numbers */ /* Blackfin traps -- i.e. exception vector numbers */
#define IPIPE_NR_FAULTS 52 /* We leave a gap after VEC_ILL_RES. */ #define IPIPE_NR_FAULTS 52 /* We leave a gap after VEC_ILL_RES. */
...@@ -48,11 +49,6 @@ ...@@ -48,11 +49,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/bitops.h>
extern int test_bit(int nr, const void *addr);
extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */ extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
static inline void __ipipe_stall_root(void) static inline void __ipipe_stall_root(void)
......
...@@ -61,20 +61,38 @@ void __ipipe_restore_root(unsigned long flags); ...@@ -61,20 +61,38 @@ void __ipipe_restore_root(unsigned long flags);
#define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags)) #define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags))
#define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x) #define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x)
#define local_save_flags(x) \ #define local_save_flags(x) \
do { \ do { \
(x) = __ipipe_test_root() ? \ (x) = __ipipe_test_root() ? \
__all_masked_irq_flags : bfin_irq_flags; \ __all_masked_irq_flags : bfin_irq_flags; \
barrier(); \
} while (0) } while (0)
#define local_irq_save(x) \ #define local_irq_save(x) \
do { \ do { \
(x) = __ipipe_test_and_stall_root(); \ (x) = __ipipe_test_and_stall_root() ? \
__all_masked_irq_flags : bfin_irq_flags; \
barrier(); \
} while (0)
static inline void local_irq_restore(unsigned long x)
{
barrier();
__ipipe_restore_root(x == __all_masked_irq_flags);
}
#define local_irq_disable() \
do { \
__ipipe_stall_root(); \
barrier(); \
} while (0) } while (0)
#define local_irq_restore(x) __ipipe_restore_root(x) static inline void local_irq_enable(void)
#define local_irq_disable() __ipipe_stall_root() {
#define local_irq_enable() __ipipe_unstall_root() barrier();
__ipipe_unstall_root();
}
#define irqs_disabled() __ipipe_test_root() #define irqs_disabled() __ipipe_test_root()
#define local_save_flags_hw(x) \ #define local_save_flags_hw(x) \
......
...@@ -122,6 +122,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -122,6 +122,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_MEMDIE 4 #define TIF_MEMDIE 4
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
#define TIF_FREEZE 6 /* is freezing for suspend */ #define TIF_FREEZE 6 /* is freezing for suspend */
#define TIF_IRQ_SYNC 7 /* sync pipeline stage */
/* as above, but as bit values */ /* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
...@@ -130,6 +131,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -130,6 +131,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_FREEZE (1<<TIF_FREEZE) #define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
......
...@@ -35,14 +35,8 @@ ...@@ -35,14 +35,8 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/io.h> #include <asm/io.h>
static int create_irq_threads;
DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs); DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
static DEFINE_PER_CPU(unsigned long, pending_irqthread_mask);
static DEFINE_PER_CPU(int [IVG13 + 1], pending_irq_count);
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs); asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
static void __ipipe_no_irqtail(void); static void __ipipe_no_irqtail(void);
...@@ -93,6 +87,7 @@ void __ipipe_enable_pipeline(void) ...@@ -93,6 +87,7 @@ void __ipipe_enable_pipeline(void)
*/ */
void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
{ {
struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
struct ipipe_domain *this_domain, *next_domain; struct ipipe_domain *this_domain, *next_domain;
struct list_head *head, *pos; struct list_head *head, *pos;
int m_ack, s = -1; int m_ack, s = -1;
...@@ -104,7 +99,6 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) ...@@ -104,7 +99,6 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
* interrupt. * interrupt.
*/ */
m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR); m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
this_domain = ipipe_current_domain; this_domain = ipipe_current_domain;
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control))) if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
...@@ -114,49 +108,28 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) ...@@ -114,49 +108,28 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
next_domain = list_entry(head, struct ipipe_domain, p_link); next_domain = list_entry(head, struct ipipe_domain, p_link);
if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) { if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
next_domain->irqs[irq].acknowledge(irq, irq_desc + irq); next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)) if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
s = __test_and_set_bit(IPIPE_STALL_FLAG, s = __test_and_set_bit(IPIPE_STALL_FLAG, &p->status);
&ipipe_root_cpudom_var(status));
__ipipe_dispatch_wired(next_domain, irq); __ipipe_dispatch_wired(next_domain, irq);
goto finalize; goto out;
return;
} }
} }
/* Ack the interrupt. */ /* Ack the interrupt. */
pos = head; pos = head;
while (pos != &__ipipe_pipeline) { while (pos != &__ipipe_pipeline) {
next_domain = list_entry(pos, struct ipipe_domain, p_link); next_domain = list_entry(pos, struct ipipe_domain, p_link);
/*
* For each domain handling the incoming IRQ, mark it
* as pending in its log.
*/
if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) { if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) {
/*
* Domains that handle this IRQ are polled for
* acknowledging it by decreasing priority
* order. The interrupt must be made pending
* _first_ in the domain's status flags before
* the PIC is unlocked.
*/
__ipipe_set_irq_pending(next_domain, irq); __ipipe_set_irq_pending(next_domain, irq);
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) { if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
next_domain->irqs[irq].acknowledge(irq, irq_desc + irq); next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
m_ack = 1; m_ack = 1;
} }
} }
/*
* If the domain does not want the IRQ to be passed
* down the interrupt pipe, exit the loop now.
*/
if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control)) if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
break; break;
pos = next_domain->p_link.next; pos = next_domain->p_link.next;
} }
...@@ -166,18 +139,24 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) ...@@ -166,18 +139,24 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
* immediately to the current domain if the interrupt has been * immediately to the current domain if the interrupt has been
* marked as 'sticky'. This search does not go beyond the * marked as 'sticky'. This search does not go beyond the
* current domain in the pipeline. We also enforce the * current domain in the pipeline. We also enforce the
* additional root stage lock (blackfin-specific). */ * additional root stage lock (blackfin-specific).
*/
if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
s = __test_and_set_bit(IPIPE_STALL_FLAG, &p->status);
if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)) /*
s = __test_and_set_bit(IPIPE_STALL_FLAG, * If the interrupt preempted the head domain, then do not
&ipipe_root_cpudom_var(status)); * even try to walk the pipeline, unless an interrupt is
finalize: * pending for it.
*/
if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) &&
ipipe_head_cpudom_var(irqpend_himask) == 0)
goto out;
__ipipe_walk_pipeline(head); __ipipe_walk_pipeline(head);
out:
if (!s) if (!s)
__clear_bit(IPIPE_STALL_FLAG, __clear_bit(IPIPE_STALL_FLAG, &p->status);
&ipipe_root_cpudom_var(status));
} }
int __ipipe_check_root(void) int __ipipe_check_root(void)
...@@ -187,7 +166,7 @@ int __ipipe_check_root(void) ...@@ -187,7 +166,7 @@ int __ipipe_check_root(void)
void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq) void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
{ {
struct irq_desc *desc = irq_desc + irq; struct irq_desc *desc = irq_to_desc(irq);
int prio = desc->ic_prio; int prio = desc->ic_prio;
desc->depth = 0; desc->depth = 0;
...@@ -199,7 +178,7 @@ EXPORT_SYMBOL(__ipipe_enable_irqdesc); ...@@ -199,7 +178,7 @@ EXPORT_SYMBOL(__ipipe_enable_irqdesc);
void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq) void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
{ {
struct irq_desc *desc = irq_desc + irq; struct irq_desc *desc = irq_to_desc(irq);
int prio = desc->ic_prio; int prio = desc->ic_prio;
if (ipd != &ipipe_root && if (ipd != &ipipe_root &&
...@@ -236,15 +215,18 @@ int __ipipe_syscall_root(struct pt_regs *regs) ...@@ -236,15 +215,18 @@ int __ipipe_syscall_root(struct pt_regs *regs)
{ {
unsigned long flags; unsigned long flags;
/* We need to run the IRQ tail hook whenever we don't /*
* We need to run the IRQ tail hook whenever we don't
* propagate a syscall to higher domains, because we know that * propagate a syscall to higher domains, because we know that
* important operations might be pending there (e.g. Xenomai * important operations might be pending there (e.g. Xenomai
* deferred rescheduling). */ * deferred rescheduling).
*/
if (!__ipipe_syscall_watched_p(current, regs->orig_p0)) { if (regs->orig_p0 < NR_syscalls) {
void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook; void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
hook(); hook();
return 0; if ((current->flags & PF_EVNOTIFY) == 0)
return 0;
} }
/* /*
...@@ -312,112 +294,46 @@ int ipipe_trigger_irq(unsigned irq) ...@@ -312,112 +294,46 @@ int ipipe_trigger_irq(unsigned irq)
{ {
unsigned long flags; unsigned long flags;
#ifdef CONFIG_IPIPE_DEBUG
if (irq >= IPIPE_NR_IRQS || if (irq >= IPIPE_NR_IRQS ||
(ipipe_virtual_irq_p(irq) (ipipe_virtual_irq_p(irq)
&& !test_bit(irq - IPIPE_VIRQ_BASE, &__ipipe_virtual_irq_map))) && !test_bit(irq - IPIPE_VIRQ_BASE, &__ipipe_virtual_irq_map)))
return -EINVAL; return -EINVAL;
#endif
local_irq_save_hw(flags); local_irq_save_hw(flags);
__ipipe_handle_irq(irq, NULL); __ipipe_handle_irq(irq, NULL);
local_irq_restore_hw(flags); local_irq_restore_hw(flags);
return 1; return 1;
} }
/* Move Linux IRQ to threads. */ asmlinkage void __ipipe_sync_root(void)
static int do_irqd(void *__desc)
{ {
struct irq_desc *desc = __desc; unsigned long flags;
unsigned irq = desc - irq_desc;
int thrprio = desc->thr_prio;
int thrmask = 1 << thrprio;
int cpu = smp_processor_id();
cpumask_t cpumask;
sigfillset(&current->blocked);
current->flags |= PF_NOFREEZE;
cpumask = cpumask_of_cpu(cpu);
set_cpus_allowed(current, cpumask);
ipipe_setscheduler_root(current, SCHED_FIFO, 50 + thrprio);
while (!kthread_should_stop()) {
local_irq_disable();
if (!(desc->status & IRQ_SCHEDULED)) {
set_current_state(TASK_INTERRUPTIBLE);
resched:
local_irq_enable();
schedule();
local_irq_disable();
}
__set_current_state(TASK_RUNNING);
/*
* If higher priority interrupt servers are ready to
* run, reschedule immediately. We need this for the
* GPIO demux IRQ handler to unmask the interrupt line
* _last_, after all GPIO IRQs have run.
*/
if (per_cpu(pending_irqthread_mask, cpu) & ~(thrmask|(thrmask-1)))
goto resched;
if (--per_cpu(pending_irq_count[thrprio], cpu) == 0)
per_cpu(pending_irqthread_mask, cpu) &= ~thrmask;
desc->status &= ~IRQ_SCHEDULED;
desc->thr_handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs));
local_irq_enable();
}
__set_current_state(TASK_RUNNING);
return 0;
}
static void kick_irqd(unsigned irq, void *cookie) BUG_ON(irqs_disabled());
{
struct irq_desc *desc = irq_desc + irq;
int thrprio = desc->thr_prio;
int thrmask = 1 << thrprio;
int cpu = smp_processor_id();
if (!(desc->status & IRQ_SCHEDULED)) {
desc->status |= IRQ_SCHEDULED;
per_cpu(pending_irqthread_mask, cpu) |= thrmask;
++per_cpu(pending_irq_count[thrprio], cpu);
wake_up_process(desc->thread);
}
}
int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc) local_irq_save_hw(flags);
{
if (desc->thread || !create_irq_threads)
return 0;
desc->thread = kthread_create(do_irqd, desc, "IRQ %d", irq);
if (desc->thread == NULL) {
printk(KERN_ERR "irqd: could not create IRQ thread %d!\n", irq);
return -ENOMEM;
}
wake_up_process(desc->thread); clear_thread_flag(TIF_IRQ_SYNC);
desc->thr_handler = ipipe_root_domain->irqs[irq].handler; if (ipipe_root_cpudom_var(irqpend_himask) != 0)
ipipe_root_domain->irqs[irq].handler = &kick_irqd; __ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
return 0; local_irq_restore_hw(flags);
} }
void __init ipipe_init_irq_threads(void) void ___ipipe_sync_pipeline(unsigned long syncmask)
{ {
unsigned irq; struct ipipe_domain *ipd = ipipe_current_domain;
struct irq_desc *desc;
create_irq_threads = 1;
for (irq = 0; irq < NR_IRQS; irq++) { if (ipd == ipipe_root_domain) {
desc = irq_desc + irq; if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
if (desc->action != NULL || return;
(desc->status & IRQ_NOREQUEST) != 0)
ipipe_start_irq_thread(irq, desc);
} }
__ipipe_sync_stage(syncmask);
} }
EXPORT_SYMBOL(show_stack); EXPORT_SYMBOL(show_stack);
......
...@@ -144,11 +144,15 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) ...@@ -144,11 +144,15 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
#endif #endif
generic_handle_irq(irq); generic_handle_irq(irq);
#ifndef CONFIG_IPIPE /* Useless and bugous over the I-pipe: IRQs are threaded. */ #ifndef CONFIG_IPIPE
/* If we're the only interrupt running (ignoring IRQ15 which is for /*
syscalls), lower our priority to IRQ14 so that softirqs run at * If we're the only interrupt running (ignoring IRQ15 which
that level. If there's another, lower-level interrupt, irq_exit * is for syscalls), lower our priority to IRQ14 so that
will defer softirqs to that. */ * softirqs run at that level. If there's another,
* lower-level interrupt, irq_exit will defer softirqs to
* that. If the interrupt pipeline is enabled, we are already
* running at IRQ14 priority, so we don't need this code.
*/
CSYNC(); CSYNC();
pending = bfin_read_IPEND() & ~0x8000; pending = bfin_read_IPEND() & ~0x8000;
other_ints = pending & (pending - 1); other_ints = pending & (pending - 1);
......
...@@ -134,7 +134,10 @@ irqreturn_t timer_interrupt(int irq, void *dummy) ...@@ -134,7 +134,10 @@ irqreturn_t timer_interrupt(int irq, void *dummy)
write_seqlock(&xtime_lock); write_seqlock(&xtime_lock);
#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) #if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
/* FIXME: Here TIMIL0 is not set when IPIPE enabled, why? */ /*
* TIMIL0 is latched in __ipipe_grab_irq() when the I-Pipe is
* enabled.
*/
if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) { if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
#endif #endif
do_timer(1); do_timer(1);
......
...@@ -600,6 +600,19 @@ ENTRY(_system_call) ...@@ -600,6 +600,19 @@ ENTRY(_system_call)
p2 = [p2]; p2 = [p2];
[p2+(TASK_THREAD+THREAD_KSP)] = sp; [p2+(TASK_THREAD+THREAD_KSP)] = sp;
#ifdef CONFIG_IPIPE
r0 = sp;
SP += -12;
call ___ipipe_syscall_root;
SP += 12;
cc = r0 == 1;
if cc jump .Lsyscall_really_exit;
cc = r0 == -1;
if cc jump .Lresume_userspace;
r3 = [sp + PT_R3];
r4 = [sp + PT_R4];
p0 = [sp + PT_ORIG_P0];
#endif /* CONFIG_IPIPE */
/* Check the System Call */ /* Check the System Call */
r7 = __NR_syscall; r7 = __NR_syscall;
...@@ -654,6 +667,17 @@ ENTRY(_system_call) ...@@ -654,6 +667,17 @@ ENTRY(_system_call)
r7 = r7 & r4; r7 = r7 & r4;
.Lsyscall_resched: .Lsyscall_resched:
#ifdef CONFIG_IPIPE
cc = BITTST(r7, TIF_IRQ_SYNC);
if !cc jump .Lsyscall_no_irqsync;
[--sp] = reti;
r0 = [sp++];
SP += -12;
call ___ipipe_sync_root;
SP += 12;
jump .Lresume_userspace_1;
.Lsyscall_no_irqsync:
#endif
cc = BITTST(r7, TIF_NEED_RESCHED); cc = BITTST(r7, TIF_NEED_RESCHED);
if !cc jump .Lsyscall_sigpending; if !cc jump .Lsyscall_sigpending;
...@@ -685,6 +709,10 @@ ENTRY(_system_call) ...@@ -685,6 +709,10 @@ ENTRY(_system_call)
.Lsyscall_really_exit: .Lsyscall_really_exit:
r5 = [sp + PT_RESERVED]; r5 = [sp + PT_RESERVED];
rets = r5; rets = r5;
#ifdef CONFIG_IPIPE
[--sp] = reti;
r5 = [sp++];
#endif /* CONFIG_IPIPE */
rts; rts;
ENDPROC(_system_call) ENDPROC(_system_call)
...@@ -771,6 +799,15 @@ _new_old_task: ...@@ -771,6 +799,15 @@ _new_old_task:
ENDPROC(_resume) ENDPROC(_resume)
ENTRY(_ret_from_exception) ENTRY(_ret_from_exception)
#ifdef CONFIG_IPIPE
[--sp] = rets;
SP += -12;
call ___ipipe_check_root
SP += 12
rets = [sp++];
cc = r0 == 0;
if cc jump 4f; /* not on behalf of Linux, get out */
#endif /* CONFIG_IPIPE */
p2.l = lo(IPEND); p2.l = lo(IPEND);
p2.h = hi(IPEND); p2.h = hi(IPEND);
...@@ -827,6 +864,28 @@ ENTRY(_ret_from_exception) ...@@ -827,6 +864,28 @@ ENTRY(_ret_from_exception)
rts; rts;
ENDPROC(_ret_from_exception) ENDPROC(_ret_from_exception)
#ifdef CONFIG_IPIPE
_sync_root_irqs:
[--sp] = reti; /* Reenable interrupts */
r0 = [sp++];
jump.l ___ipipe_sync_root
_resume_kernel_from_int:
r0.l = _sync_root_irqs
r0.h = _sync_root_irqs
[--sp] = rets;
[--sp] = ( r7:4, p5:3 );
SP += -12;
call ___ipipe_call_irqtail
SP += 12;
( r7:4, p5:3 ) = [sp++];
rets = [sp++];
rts
#else
#define _resume_kernel_from_int 2f
#endif
ENTRY(_return_from_int) ENTRY(_return_from_int)
/* If someone else already raised IRQ 15, do nothing. */ /* If someone else already raised IRQ 15, do nothing. */
csync; csync;
...@@ -848,7 +907,7 @@ ENTRY(_return_from_int) ...@@ -848,7 +907,7 @@ ENTRY(_return_from_int)
r1 = r0 - r1; r1 = r0 - r1;
r2 = r0 & r1; r2 = r0 & r1;
cc = r2 == 0; cc = r2 == 0;
if !cc jump 2f; if !cc jump _resume_kernel_from_int;
/* Lower the interrupt level to 15. */ /* Lower the interrupt level to 15. */
p0.l = lo(EVT15); p0.l = lo(EVT15);
......
...@@ -235,6 +235,7 @@ ENDPROC(_evt_system_call) ...@@ -235,6 +235,7 @@ ENDPROC(_evt_system_call)
#ifdef CONFIG_IPIPE #ifdef CONFIG_IPIPE
ENTRY(___ipipe_call_irqtail) ENTRY(___ipipe_call_irqtail)
p0 = r0;
r0.l = 1f; r0.l = 1f;
r0.h = 1f; r0.h = 1f;
reti = r0; reti = r0;
...@@ -242,9 +243,6 @@ ENTRY(___ipipe_call_irqtail) ...@@ -242,9 +243,6 @@ ENTRY(___ipipe_call_irqtail)
1: 1:
[--sp] = rets; [--sp] = rets;
[--sp] = ( r7:4, p5:3 ); [--sp] = ( r7:4, p5:3 );
p0.l = ___ipipe_irq_tail_hook;
p0.h = ___ipipe_irq_tail_hook;
p0 = [p0];
sp += -12; sp += -12;
call (p0); call (p0);
sp += 12; sp += 12;
...@@ -259,7 +257,7 @@ ENTRY(___ipipe_call_irqtail) ...@@ -259,7 +257,7 @@ ENTRY(___ipipe_call_irqtail)
p0.h = hi(EVT14); p0.h = hi(EVT14);
[p0] = r0; [p0] = r0;
csync; csync;
r0 = 0x401f; r0 = 0x401f (z);
sti r0; sti r0;
raise 14; raise 14;
[--sp] = reti; /* IRQs on. */ [--sp] = reti; /* IRQs on. */
...@@ -277,11 +275,7 @@ ENTRY(___ipipe_call_irqtail) ...@@ -277,11 +275,7 @@ ENTRY(___ipipe_call_irqtail)
p0.h = _bfin_irq_flags; p0.h = _bfin_irq_flags;
r0 = [p0]; r0 = [p0];
sti r0; sti r0;
#if 0 /* FIXME: this actually raises scheduling latencies */
/* Reenable interrupts */
[--sp] = reti;
r0 = [sp++];
#endif
rts; rts;
ENDPROC(___ipipe_call_irqtail) ENDPROC(___ipipe_call_irqtail)
#endif /* CONFIG_IPIPE */ #endif /* CONFIG_IPIPE */
...@@ -161,11 +161,15 @@ static void bfin_core_unmask_irq(unsigned int irq) ...@@ -161,11 +161,15 @@ static void bfin_core_unmask_irq(unsigned int irq)
static void bfin_internal_mask_irq(unsigned int irq) static void bfin_internal_mask_irq(unsigned int irq)
{ {
unsigned long flags;
#ifdef CONFIG_BF53x #ifdef CONFIG_BF53x
local_irq_save_hw(flags);
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
~(1 << SIC_SYSIRQ(irq))); ~(1 << SIC_SYSIRQ(irq)));
#else #else
unsigned mask_bank, mask_bit; unsigned mask_bank, mask_bit;
local_irq_save_hw(flags);
mask_bank = SIC_SYSIRQ(irq) / 32; mask_bank = SIC_SYSIRQ(irq) / 32;
mask_bit = SIC_SYSIRQ(irq) % 32; mask_bit = SIC_SYSIRQ(irq) % 32;
bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
...@@ -175,15 +179,20 @@ static void bfin_internal_mask_irq(unsigned int irq) ...@@ -175,15 +179,20 @@ static void bfin_internal_mask_irq(unsigned int irq)
~(1 << mask_bit)); ~(1 << mask_bit));
#endif #endif
#endif #endif
local_irq_restore_hw(flags);
} }
static void bfin_internal_unmask_irq(unsigned int irq) static void bfin_internal_unmask_irq(unsigned int irq)
{ {
unsigned long flags;
#ifdef CONFIG_BF53x #ifdef CONFIG_BF53x
local_irq_save_hw(flags);
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
(1 << SIC_SYSIRQ(irq))); (1 << SIC_SYSIRQ(irq)));
#else #else
unsigned mask_bank, mask_bit; unsigned mask_bank, mask_bit;
local_irq_save_hw(flags);
mask_bank = SIC_SYSIRQ(irq) / 32; mask_bank = SIC_SYSIRQ(irq) / 32;
mask_bit = SIC_SYSIRQ(irq) % 32; mask_bit = SIC_SYSIRQ(irq) % 32;
bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
...@@ -193,6 +202,7 @@ static void bfin_internal_unmask_irq(unsigned int irq) ...@@ -193,6 +202,7 @@ static void bfin_internal_unmask_irq(unsigned int irq)
(1 << mask_bit)); (1 << mask_bit));
#endif #endif
#endif #endif
local_irq_restore_hw(flags);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -390,7 +400,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, ...@@ -390,7 +400,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
{ {
#ifdef CONFIG_IPIPE #ifdef CONFIG_IPIPE
_set_irq_handler(irq, handle_edge_irq); _set_irq_handler(irq, handle_level_irq);
#else #else
struct irq_desc *desc = irq_desc + irq; struct irq_desc *desc = irq_desc + irq;
/* May not call generic set_irq_handler() due to spinlock /* May not call generic set_irq_handler() due to spinlock
...@@ -1055,13 +1065,18 @@ int __init init_arch_irq(void) ...@@ -1055,13 +1065,18 @@ int __init init_arch_irq(void)
#endif #endif
default: default:
#ifdef CONFIG_IPIPE #ifdef CONFIG_IPIPE
/* /*
* We want internal interrupt sources to be masked, because * We want internal interrupt sources to be
* ISRs may trigger interrupts recursively (e.g. DMA), but * masked, because ISRs may trigger interrupts
* interrupts are _not_ masked at CPU level. So let's handle * recursively (e.g. DMA), but interrupts are
* them as level interrupts. * _not_ masked at CPU level. So let's handle
*/ * most of them as level interrupts, except
set_irq_handler(irq, handle_level_irq); * the timer interrupt which is special.
*/
if (irq == IRQ_SYSTMR || irq == IRQ_CORETMR)
set_irq_handler(irq, handle_simple_irq);
else
set_irq_handler(irq, handle_level_irq);
#else /* !CONFIG_IPIPE */ #else /* !CONFIG_IPIPE */
set_irq_handler(irq, handle_simple_irq); set_irq_handler(irq, handle_simple_irq);
#endif /* !CONFIG_IPIPE */ #endif /* !CONFIG_IPIPE */
...@@ -1123,9 +1138,8 @@ int __init init_arch_irq(void) ...@@ -1123,9 +1138,8 @@ int __init init_arch_irq(void)
#ifdef CONFIG_IPIPE #ifdef CONFIG_IPIPE
for (irq = 0; irq < NR_IRQS; irq++) { for (irq = 0; irq < NR_IRQS; irq++) {
struct irq_desc *desc = irq_desc + irq; struct irq_desc *desc = irq_to_desc(irq);
desc->ic_prio = __ipipe_get_irq_priority(irq); desc->ic_prio = __ipipe_get_irq_priority(irq);
desc->thr_prio = __ipipe_get_irqthread_priority(irq);
} }
#endif /* CONFIG_IPIPE */ #endif /* CONFIG_IPIPE */
...@@ -1208,76 +1222,21 @@ int __ipipe_get_irq_priority(unsigned irq) ...@@ -1208,76 +1222,21 @@ int __ipipe_get_irq_priority(unsigned irq)
return IVG15; return IVG15;
} }
int __ipipe_get_irqthread_priority(unsigned irq)
{
int ient, prio;
int demux_irq;
/* The returned priority value is rescaled to [0..IVG13+1]
* with 0 being the lowest effective priority level. */
if (irq <= IRQ_CORETMR)
return IVG13 - irq + 1;
/* GPIO IRQs are given the priority of the demux
* interrupt. */
if (IS_GPIOIRQ(irq)) {
#if defined(CONFIG_BF54x)
u32 bank = PINT_2_BANK(irq2pint_lut[irq - SYS_IRQS]);
demux_irq = (bank == 0 ? IRQ_PINT0 :
bank == 1 ? IRQ_PINT1 :
bank == 2 ? IRQ_PINT2 :
IRQ_PINT3);
#elif defined(CONFIG_BF561)
demux_irq = (irq >= IRQ_PF32 ? IRQ_PROG2_INTA :
irq >= IRQ_PF16 ? IRQ_PROG1_INTA :
IRQ_PROG0_INTA);
#elif defined(CONFIG_BF52x)
demux_irq = (irq >= IRQ_PH0 ? IRQ_PORTH_INTA :
irq >= IRQ_PG0 ? IRQ_PORTG_INTA :
IRQ_PORTF_INTA);
#else
demux_irq = irq;
#endif
return IVG13 - PRIO_GPIODEMUX(demux_irq) + 1;
}
/* The GPIO demux interrupt is given a lower priority
* than the GPIO IRQs, so that its threaded handler
* unmasks the interrupt line after the decoded IRQs
* have been processed. */
prio = PRIO_GPIODEMUX(irq);
/* demux irq? */
if (prio != -1)
return IVG13 - prio;
for (ient = 0; ient < NR_PERI_INTS; ient++) {
struct ivgx *ivg = ivg_table + ient;
if (ivg->irqno == irq) {
for (prio = 0; prio <= IVG13-IVG7; prio++) {
if (ivg7_13[prio].ifirst <= ivg &&
ivg7_13[prio].istop > ivg)
return IVG7 - prio;
}
}
}
return 0;
}
/* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */ /* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */
#ifdef CONFIG_DO_IRQ_L1 #ifdef CONFIG_DO_IRQ_L1
__attribute__((l1_text)) __attribute__((l1_text))
#endif #endif
asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
{ {
struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
struct ipipe_domain *this_domain = ipipe_current_domain;
struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop; struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst; struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
int irq; int irq, s;
if (likely(vec == EVT_IVTMR_P)) { if (likely(vec == EVT_IVTMR_P)) {
irq = IRQ_CORETMR; irq = IRQ_CORETMR;
goto handle_irq; goto core_tick;
} }
SSYNC(); SSYNC();
...@@ -1319,24 +1278,39 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) ...@@ -1319,24 +1278,39 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
irq = ivg->irqno; irq = ivg->irqno;
if (irq == IRQ_SYSTMR) { if (irq == IRQ_SYSTMR) {
#ifdef CONFIG_GENERIC_CLOCKEVENTS
core_tick:
#else
bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */ bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */
#endif
/* This is basically what we need from the register frame. */ /* This is basically what we need from the register frame. */
__raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend; __raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend;
__raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc; __raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc;
if (!ipipe_root_domain_p) if (this_domain != ipipe_root_domain)
__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
else
__raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10; __raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10;
else
__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
} }
handle_irq: #ifndef CONFIG_GENERIC_CLOCKEVENTS
core_tick:
#endif
if (this_domain == ipipe_root_domain) {
s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
barrier();
}
ipipe_trace_irq_entry(irq); ipipe_trace_irq_entry(irq);
__ipipe_handle_irq(irq, regs); __ipipe_handle_irq(irq, regs);
ipipe_trace_irq_exit(irq); ipipe_trace_irq_exit(irq);
if (ipipe_root_domain_p) if (this_domain == ipipe_root_domain) {
return !test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status)); set_thread_flag(TIF_IRQ_SYNC);
if (!s) {
__clear_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
return !test_bit(IPIPE_STALL_FLAG, &p->status);
}
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment