Changeset 8670c464 in rtems


Ignore:
Timestamp:
May 5, 2017, 1:42:45 PM (3 years ago)
Author:
Daniel Hellstrom <daniel@…>
Branches:
master
Children:
ce76b9d2
Parents:
aa19873
git-author:
Daniel Hellstrom <daniel@…> (05/05/17 13:42:45)
git-committer:
Daniel Hellstrom <daniel@…> (05/14/17 10:31:59)
Message:

leon, genirq: SMP support for PCI peripherals

The common interrupt layer for GRLIB PCI perihperals is prepared for SMP
support by this patch. The existing locking (interrupt disabling) is
replaced by a new requirement on the user to implement locking before
calling the genirq API. This approach avoids taking more locks than
necessary.

The split up of the locks also introduces that the user must allocate
memory to describe ISR handlers, to avoid calling malloc()/free() while
possessing a spin-lock and interrupts are globally disabled.

Location:
c/src/lib/libbsp/sparc/shared
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/shared/include/genirq.h

    raa19873 r8670c464  
    3636
    3737/* Free the dynamically allocated memory that the genirq interface has
    38  * allocated.
     38 * allocated. Also the handlers will be freed.
    3939 *
    4040 * Returns zero on success, otherwise failure.
     
    4848extern int genirq_check(genirq_t d, int irq);
    4949
    50 /* Register shared interrupt handler.
     50/* Allocate one ISR handler and initialize it. Input to genirq_register().
     51 *
     52 * \param isr    The interrupt service routine called upon IRQ
     53 * \param arg    The argument given to isr() when called.
     54 *
     55 * Returns a pointer on success, on failure NULL is returned.
     56 */
     57extern void *genirq_alloc_handler(genirq_handler isr, void *arg);
     58
     59/* Free handler memory */
     60#define genirq_free_handler(handler) free(handler)
     61
     62/* Register shared interrupt handler previously initialized with
     63 * genirq_alloc_handler().
     64 *
     65 * NOTE: internal list structures are accessed and needs to be protected by
     66 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
    5167 *
    5268 * \param irq    The interrupt number to register ISR on
    53  * \param isr    The interrupt service routine called upon IRQ
    54  * \param arg    The argument given to isr() when called.
     69 * \param handler Install the pre- allocated and initialized handler.
    5570 *
    5671 * Return Values
     
    5974 * 1   = Handler registered Successfully, _not_ first handler on this IRQ
    6075 */
    61 extern int genirq_register(genirq_t d, int irq, genirq_handler isr, void *arg);
     76extern int genirq_register(genirq_t d, int irq, void *handler);
    6277
    63 /* Unregister an previous registered interrupt handler
     78/* Unregister an previous registered interrupt handler. It is the user's
     79 * responsibility to free the handler returned by genirq_unregister().
     80 *
     81 * NOTE: internal list structures are accessed and needs to be protected by
     82 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
    6483 *
    6584 * Return Values
    66  *  -1 = ISR not registered before
    67  *  0  = ISR unregistered
    68  *  1  = Unable to unregister enabled ISR
     85 * NULL    = ISR not registered before or unable to unregister enabled ISR
     86 * Pointer = ISR sucessfully unregistered. Returned is the handler pointer
     87 *           previously allocated with genirq_alloc_handler().
    6988 */
    70 extern int genirq_unregister(genirq_t d, int irq, genirq_handler isr, void *arg);
     89extern void *genirq_unregister(genirq_t d, int irq,
     90                                genirq_handler isr, void *arg);
    7191
    7292/* Enables IRQ only for this isr[arg] combination. Records if this
     
    7494 * on the interrupt controller.
    7595 *
    76  * IRQs must be disabled before entering this function.
     96 * NOTE: internal list structures are accessed and needs to be protected by
     97 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
    7798 *
    7899 * Return values
     
    87108 * must interrupts be disabled on the interrupt controller.
    88109 *
    89  * IRQs must be disabled before entering this function.
     110 * NOTE: internal list structures are accessed and needs to be protected by
     111 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
    90112 *
    91113 * Return values
     
    98120/* Must be called by user when an IRQ has fired, the argument 'irq'
    99121 * is the IRQ number of the IRQ which was fired.
     122 *
     123 * NOTE: internal list structures are accessed and needs to be protected by
     124 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
    100125 */
    101126extern void genirq_doirq(genirq_t d, int irq);
  • c/src/lib/libbsp/sparc/shared/irq/genirq.c

    raa19873 r8670c464  
    11/*
    22 * Generic interrupt helpers mainly for GRLIB PCI peripherals
    3  * 
     3 *
    44 * COPYRIGHT (c) 2008.
    55 * Cobham Gaisler AB.
     
    4848        memset(priv, 0, size);
    4949        priv->genirq_max = number_of_irqs - 1;
     50
    5051        return priv;
    5152}
     
    6566                        tmp = isrentry;
    6667                        isrentry = isrentry->next;
    67                         free(tmp);
     68                        genirq_free_handler(tmp);
    6869                }
    6970        }
     
    8283}
    8384
    84 int genirq_register(genirq_t d, int irq, genirq_handler isr, void *arg)
    85 {
    86         struct genirq_priv *priv = d;
    87         struct genirq_irq_entry *irqentry;
    88         struct genirq_handler_entry *isrentry, *newentry;
    89         rtems_interrupt_level level;
    90        
     85void *genirq_alloc_handler(genirq_handler isr, void *arg)
     86{
     87        struct genirq_handler_entry *newentry;
     88
     89        newentry = malloc(sizeof(struct genirq_handler_entry));
     90        if ( newentry ) {
     91                /* Initialize ISR entry */
     92                newentry->isr     = isr;
     93                newentry->arg     = arg;
     94                newentry->enabled = 0;
     95        }
     96        return newentry;
     97}
     98
     99int genirq_register(genirq_t d, int irq, void *handler)
     100{
     101        struct genirq_priv *priv = d;
     102        struct genirq_irq_entry *irqentry;
     103        struct genirq_handler_entry *isrentry, *newentry = handler;
     104
    91105        if ( genirq_check(d, irq) )
    92106                return -1;
    93 
    94         newentry = malloc(sizeof(*newentry));
    95         if ( !newentry )
    96                 return -1;
    97 
    98         /* Initialize ISR entry */
    99         newentry->isr     = isr;
    100         newentry->arg     = arg;
    101         newentry->enabled = 0;
    102 
    103         rtems_interrupt_disable(level);
    104107
    105108        /* Insert new ISR entry first into table */
     
    108111        irqentry->head = newentry;
    109112        newentry->next = isrentry;
    110 
    111         rtems_interrupt_enable(level);
    112113
    113114        if ( isrentry )
     
    116117}
    117118
    118 int genirq_unregister(genirq_t d, int irq, genirq_handler isr, void *arg)
     119void *genirq_unregister(genirq_t d, int irq, genirq_handler isr, void *arg)
    119120{
    120121        struct genirq_priv *priv = d;
    121122        struct genirq_irq_entry *irqentry;
    122123        struct genirq_handler_entry *isrentry, **prev;
    123         rtems_interrupt_level level;
    124         int ret;
     124        void *ret;
    125125
    126126        if ( genirq_check(d, irq) )
    127                 return -1;
     127                return NULL;
    128128
    129129        /* Remove isr[arg] from ISR list */
    130130        irqentry = &priv->genirq_table[irq];
    131         ret = -1;
    132 
    133         rtems_interrupt_disable(level);
     131        ret = NULL;
    134132
    135133        prev = &irqentry->head;
     
    140138                        if ( isrentry->enabled ) {
    141139                                /* Can not remove enabled ISRs, disable first */
    142                                 ret = 1;
     140                                ret = NULL;
    143141                                break;
    144142                        }
    145143                        *prev = isrentry->next;
    146                         ret = 0;
     144                        ret = isrentry;
    147145                        break;
    148146                }
     
    150148                isrentry = isrentry->next;
    151149        }
    152 
    153         rtems_interrupt_enable(level);
    154150
    155151        return ret;
     
    227223        irqentry = &priv->genirq_table[irq];
    228224        irqentry->stats.irq_cnt++;
    229        
     225
    230226        enabled = 0;
    231227
Note: See TracChangeset for help on using the changeset viewer.