Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3d37d94e5aab669f5a492bb3cda67bbbbbca50b8
Commit:     3d37d94e5aab669f5a492bb3cda67bbbbbca50b8
Parent:     5c37e025352b993d8726b0207ff2270b2f2bc7d6
Author:     Magnus Damm <[EMAIL PROTECTED]>
AuthorDate: Fri Aug 17 00:50:44 2007 +0900
Committer:  Paul Mundt <[EMAIL PROTECTED]>
CommitDate: Fri Sep 21 11:57:50 2007 +0900

    sh: intc - primary priority masking fixes
    
    This patch contains various intc fixes for problems reported by
    Markus Brunner on the linuxsh-dev mailing list:
    
    http://marc.info/?l=linuxsh-dev&m=118701948224991&w=1
    
    Apart from added comments, the fixes are:
    
    - add intc_set_priority() function prototype to hw_irq.h
    - fix off-by-one error in intc_set_priority()
    - make sure _INTC_WIDTH() is set for primary priority masking
    
    Big thanks to Markus for finding these problems. Version two fixes
    a compile error and an inverted primary check.
    
    Signed-off-by: Magnus Damm <[EMAIL PROTECTED]>
    Acked-by: Markus Brunner <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mundt <[EMAIL PROTECTED]>
---
 arch/sh/kernel/cpu/irq/intc.c |   33 ++++++++++++++++++++++++++++-----
 include/asm-sh/hw_irq.h       |    1 +
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c
index d609a8c..481871f 100644
--- a/arch/sh/kernel/cpu/irq/intc.c
+++ b/arch/sh/kernel/cpu/irq/intc.c
@@ -206,6 +206,18 @@ static struct intc_handle_int *intc_find_irq(struct 
intc_handle_int *hp,
 {
        int i;
 
+       /* this doesn't scale well, but...
+        *
+        * this function should only be used for cerain uncommon
+        * operations such as intc_set_priority() and intc_set_sense()
+        * and in those rare cases performance doesn't matter that much.
+        * keeping the memory footprint low is more important.
+        *
+        * one rather simple way to speed this up and still keep the
+        * memory footprint down is to make sure the array is sorted
+        * and then perform a bisect to lookup the irq.
+        */
+
        for (i = 0; i < nr_hp; i++) {
                if ((hp + i)->irq != irq)
                        continue;
@@ -226,7 +238,7 @@ int intc_set_priority(unsigned int irq, unsigned int prio)
 
        ihp = intc_find_irq(d->prio, d->nr_prio, irq);
        if (ihp) {
-               if (prio >= ((1 << _INTC_WIDTH(ihp->handle)) - 1))
+               if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
                        return -EINVAL;
 
                intc_prio_level[irq] = prio;
@@ -237,7 +249,7 @@ int intc_set_priority(unsigned int irq, unsigned int prio)
                 * priority level will be set during next enable()
                 */
 
-               if (ihp->handle)
+               if (_INTC_FN(ihp->handle) != REG_FN_ERR)
                        _intc_enable(irq, ihp->handle);
        }
        return 0;
@@ -457,6 +469,7 @@ static void __init intc_register_irq(struct intc_desc *desc,
                                     intc_enum enum_id,
                                     unsigned int irq)
 {
+       struct intc_handle_int *hp;
        unsigned int data[2], primary;
 
        /* Prefer single interrupt source bitmap over other combinations:
@@ -495,9 +508,19 @@ static void __init intc_register_irq(struct intc_desc 
*desc,
 
        /* add irq to d->prio list if priority is available */
        if (data[1]) {
-               (d->prio + d->nr_prio)->irq = irq;
-               if (!primary) /* only secondary priority can access regs */
-                       (d->prio + d->nr_prio)->handle = data[1];
+               hp = d->prio + d->nr_prio;
+               hp->irq = irq;
+               hp->handle = data[1];
+
+               if (primary) {
+                       /*
+                        * only secondary priority should access registers, so
+                        * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
+                        */
+
+                       hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
+                       hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
+               }
                d->nr_prio++;
        }
 
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 0c016e9..f9c9067 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -90,6 +90,7 @@ struct intc_desc symbol __initdata = {                        
                \
 }
 
 void __init register_intc_controller(struct intc_desc *desc);
+int intc_set_priority(unsigned int irq, unsigned int prio);
 
 void __init plat_irq_setup(void);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to