Changeset e3890b3f in mainline for kernel/generic/src/ddi/irq.c


Ignore:
Timestamp:
2006-10-15T12:46:29Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2b017ba
Parents:
63530c62
Message:

More IRQ stuff.
Modify the IRQ hash table functions to support lookup based on inr and devno.
Add method member to irq_t.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ddi/irq.c

    r63530c62 re3890b3f  
    3232/**
    3333 * @file
    34  * @brief       IRQ redirector.
     34 * @brief       IRQ dispatcher.
    3535 *
    3636 * This file provides means of connecting IRQs with particular
     
    5757 * array. Next, when it is known that the IRQ numbers (aka INR's)
    5858 * are unique, the claim functions can always return IRQ_ACCEPT.
     59 *
     60 *
     61 * Note about the irq_hash_table.
     62 *
     63 * The hash table is configured to use two keys: inr and devno.
     64 * However, the hash index is computed only from inr. Moreover,
     65 * if devno is -1, the match is based on the return value of
     66 * the claim() function instead of on devno.
    5967 */
    6068
     
    6775#include <arch.h>
    6876
     77#define KEY_INR         0
     78#define KEY_DEVNO       1
     79
    6980/**
    7081 * Spinlock protecting the hash table.
     
    116127         */
    117128        if (inrs == chains)
    118                 hash_table_create(&irq_hash_table, chains, 1, &irq_lin_ops);
     129                hash_table_create(&irq_hash_table, chains, 2, &irq_lin_ops);
    119130        else
    120                 hash_table_create(&irq_hash_table, chains, 1, &irq_ht_ops);
     131                hash_table_create(&irq_hash_table, chains, 2, &irq_ht_ops);
    121132}
    122133
     
    138149        irq->notif_answerbox = NULL;
    139150        irq->code = NULL;
     151        irq->method = 0;
    140152        atomic_set(&irq->counter, 0);
    141153}
     
    152164{
    153165        ipl_t ipl;
     166        unative_t key[] = {
     167                (unative_t) irq->inr,
     168                (unative_t) irq->devno
     169        };
    154170       
    155171        ipl = interrupts_disable();
    156172        spinlock_lock(&irq_hash_table_lock);
    157         hash_table_insert(&irq_hash_table, (void *) &irq->inr, &irq->link);
     173        hash_table_insert(&irq_hash_table, key, &irq->link);
    158174        spinlock_unlock(&irq_hash_table_lock);
    159175        interrupts_restore(ipl);
     
    162178/** Dispatch the IRQ.
    163179 *
     180 * We assume this function is only called from interrupt
     181 * context (i.e. that interrupts are disabled prior to
     182 * this call).
     183 *
     184 * This function attempts to lookup a fitting IRQ
     185 * structure. In case of success, return with interrupts
     186 * disabled and holding the respective structure.
     187 *
    164188 * @param inr Interrupt number (aka inr or irq).
    165189 *
    166190 * @return IRQ structure of the respective device or NULL.
    167191 */
    168 irq_t *irq_dispatch(inr_t inr)
    169 {
    170         ipl_t ipl;
     192irq_t *irq_dispatch_and_lock(inr_t inr)
     193{
    171194        link_t *lnk;
    172        
    173         ipl = interrupts_disable();
     195        unative_t key[] = {
     196                (unative_t) inr,
     197                (unative_t) -1          /* search will use claim() instead of devno */
     198        };
     199       
    174200        spinlock_lock(&irq_hash_table_lock);
    175201
    176         lnk = hash_table_find(&irq_hash_table, (void *) &inr);
     202        lnk = hash_table_find(&irq_hash_table, key);
    177203        if (lnk) {
    178204                irq_t *irq;
     
    181207
    182208                spinlock_unlock(&irq_hash_table_lock);
    183                 interrupts_restore(ipl);
    184209                return irq;
    185210        }
    186211       
    187212        spinlock_unlock(&irq_hash_table_lock);
    188         interrupts_restore(ipl);
     213
     214        return NULL;   
     215}
     216
     217/** Find the IRQ structure corresponding to inr and devno.
     218 *
     219 * This functions attempts to lookup the IRQ structure
     220 * corresponding to its arguments. On success, this
     221 * function returns with interrups disabled, holding
     222 * the lock of the respective IRQ structure.
     223 *
     224 * This function assumes interrupts are already disabled.
     225 *
     226 * @param inr INR being looked up.
     227 * @param devno Devno being looked up.
     228 *
     229 * @return Locked IRQ structure on success or NULL on failure.
     230 */
     231irq_t *irq_find_and_lock(inr_t inr, devno_t devno)
     232{
     233        link_t *lnk;
     234        unative_t keys[] = {
     235                (unative_t) inr,
     236                (unative_t) devno
     237        };
     238       
     239        spinlock_lock(&irq_hash_table_lock);
     240
     241        lnk = hash_table_find(&irq_hash_table, keys);
     242        if (lnk) {
     243                irq_t *irq;
     244               
     245                irq = hash_table_get_instance(lnk, irq_t, link);
     246
     247                spinlock_unlock(&irq_hash_table_lock);
     248                return irq;
     249        }
     250       
     251        spinlock_unlock(&irq_hash_table_lock);
    189252
    190253        return NULL;   
     
    198261 * INRs.
    199262 *
    200  * @param key Pointer to INR.
     263 * The devno is not used to compute the hash.
     264 *
     265 * @param key The first of the keys is inr and the second is devno or -1.
    201266 *
    202267 * @return Index into the hash table.
    203268 */
    204 index_t irq_ht_hash(unative_t *key)
    205 {
    206         inr_t *inr = (inr_t *) key;
    207         return *inr % irq_hash_table.entries;
     269index_t irq_ht_hash(unative_t key[])
     270{
     271        inr_t inr = (inr_t) key[KEY_INR];
     272        return inr % irq_hash_table.entries;
    208273}
    209274
    210275/** Compare hash table element with a key.
    211276 *
    212  * As usually, we do sort of a hack here.
    213  * Even when the key matches the inr member,
    214  * we ask the device to either accept
    215  * or decline to service the interrupt.
    216  *
    217  * @param key Pointer to key (i.e. inr).
    218  * @param keys This is 1.
     277 * There are two things to note about this function.
     278 * First, it is used for the more complex architecture setup
     279 * in which there are way too many interrupt numbers (i.e. inr's)
     280 * to arrange the hash table so that collisions occur only
     281 * among same inrs of different devnos. So the explicit check
     282 * for inr match must be done.
     283 * Second, if devno is -1, the second key (i.e. devno) is not
     284 * used for the match and the result of the claim() function
     285 * is used instead.
     286 *
     287 * This function assumes interrupts are already disabled.
     288 *
     289 * @param key Keys (i.e. inr and devno).
     290 * @param keys This is 2.
    219291 * @param item The item to compare the key with.
    220292 *
    221293 * @return True on match or false otherwise.
    222294 */
    223 bool irq_ht_compare(unative_t *key, count_t keys, link_t *item)
     295bool irq_ht_compare(unative_t key[], count_t keys, link_t *item)
    224296{
    225297        irq_t *irq = hash_table_get_instance(item, irq_t, link);
    226         inr_t *inr = (inr_t *) key;
     298        inr_t inr = (inr_t) key[KEY_INR];
     299        devno_t devno = (devno_t) key[KEY_DEVNO];
     300
    227301        bool rv;
    228302       
    229303        spinlock_lock(&irq->lock);
    230         rv = ((irq->inr == *inr) && (irq->claim() == IRQ_ACCEPT));
    231         spinlock_unlock(&irq->lock);
     304        if (devno == -1) {
     305                /* Invoked by irq_dispatch(). */
     306                rv = ((irq->inr == inr) && (irq->claim() == IRQ_ACCEPT));
     307        } else {
     308                /* Invoked by irq_find(). */
     309                rv = ((irq->inr == inr) && (irq->devno == devno));
     310        }
     311       
     312        /* unlock only on non-match */
     313        if (!rv)
     314                spinlock_unlock(&irq->lock);
    232315
    233316        return rv;
     
    241324 * INRs.
    242325 *
    243  * @param key INR.
     326 * @param key The first of the keys is inr and the second is devno or -1.
    244327 *
    245328 * @return Index into the hash table.
    246329 */
    247 index_t irq_lin_hash(unative_t *key)
    248 {
    249         inr_t *inr = (inr_t *) key;
    250         return *inr;
     330index_t irq_lin_hash(unative_t key[])
     331{
     332        inr_t inr = (inr_t) key[KEY_INR];
     333        return inr;
    251334}
    252335
    253336/** Compare hash table element with a key.
    254337 *
    255  * As usually, we do sort of a hack here.
    256  * We don't compare the inr member with
    257  * the key because we know that there are
    258  * no collision between different keys.
    259  * We only ask the device to either accept
    260  * or decline to service the interrupt.
    261  *
    262  * @param key Pointer to key (i.e. inr).
    263  * @param keys This is 1.
     338 * There are two things to note about this function.
     339 * First, it is used for the less complex architecture setup
     340 * in which there are not too many interrupt numbers (i.e. inr's)
     341 * to arrange the hash table so that collisions occur only
     342 * among same inrs of different devnos. So the explicit check
     343 * for inr match is not done.
     344 * Second, if devno is -1, the second key (i.e. devno) is not
     345 * used for the match and the result of the claim() function
     346 * is used instead.
     347 *
     348 * This function assumes interrupts are already disabled.
     349 *
     350 * @param key Keys (i.e. inr and devno).
     351 * @param keys This is 2.
    264352 * @param item The item to compare the key with.
    265353 *
    266354 * @return True on match or false otherwise.
    267355 */
    268 bool irq_lin_compare(unative_t *key, count_t keys, link_t *item)
     356bool irq_lin_compare(unative_t key[], count_t keys, link_t *item)
    269357{
    270358        irq_t *irq = list_get_instance(item, irq_t, link);
     359        devno_t devno = (devno_t) key[KEY_DEVNO];
    271360        bool rv;
    272361       
    273362        spinlock_lock(&irq->lock);
    274         rv = (irq->claim() == IRQ_ACCEPT);
    275         spinlock_unlock(&irq->lock);
     363        if (devno == -1) {
     364                /* Invoked by irq_dispatch() */
     365                rv = (irq->claim() == IRQ_ACCEPT);
     366        } else {
     367                /* Invoked by irq_find() */
     368                rv = (irq->devno == devno);
     369        }
     370       
     371        /* unlock only on non-match */
     372        if (!rv)
     373                spinlock_unlock(&irq->lock);
    276374       
    277375        return rv;
Note: See TracChangeset for help on using the changeset viewer.