Ignore:
File:
1 edited

Legend:

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

    r1d432f9 ra70bda4  
    3131 * @{
    3232 */
    33 
    3433/**
    3534 * @file
     
    6867 *   structure are finished. Because we hold the hash table lock, we prevent new
    6968 *   IRQs from taking new references to the IRQ structure.
    70  *
    7169 */
    7270
     
    8381/** Free the top-half pseudocode.
    8482 *
    85  * @param code Pointer to the top-half pseudocode.
    86  *
     83 * @param code          Pointer to the top-half pseudocode.
    8784 */
    8885static void code_free(irq_code_t *code)
     
    9693/** Copy the top-half pseudocode from userspace into the kernel.
    9794 *
    98  * @param ucode Userspace address of the top-half pseudocode.
    99  *
    100  * @return Kernel address of the copied pseudocode.
    101  *
     95 * @param ucode         Userspace address of the top-half pseudocode.
     96 *
     97 * @return              Kernel address of the copied pseudocode.
    10298 */
    10399static irq_code_t *code_from_uspace(irq_code_t *ucode)
    104100{
    105         irq_code_t *code = malloc(sizeof(*code), 0);
    106         int rc = copy_from_uspace(code, ucode, sizeof(*code));
     101        irq_code_t *code;
     102        irq_cmd_t *ucmds;
     103        int rc;
     104
     105        code = malloc(sizeof(*code), 0);
     106        rc = copy_from_uspace(code, ucode, sizeof(*code));
    107107        if (rc != 0) {
    108108                free(code);
     
    114114                return NULL;
    115115        }
    116        
    117         irq_cmd_t *ucmds = code->cmds;
     116        ucmds = code->cmds;
    118117        code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
    119118        rc = copy_from_uspace(code->cmds, ucmds,
     
    124123                return NULL;
    125124        }
    126        
     125
    127126        return code;
    128127}
     
    142141    unative_t method, irq_code_t *ucode)
    143142{
     143        ipl_t ipl;
     144        irq_code_t *code;
     145        irq_t *irq;
     146        link_t *hlp;
    144147        unative_t key[] = {
    145148                (unative_t) inr,
     
    147150        };
    148151       
    149         irq_code_t *code;
    150152        if (ucode) {
    151153                code = code_from_uspace(ucode);
    152154                if (!code)
    153155                        return EBADMEM;
    154         } else
     156        } else {
    155157                code = NULL;
     158        }
    156159       
    157160        /*
    158161         * Allocate and populate the IRQ structure.
    159162         */
    160         irq_t *irq = malloc(sizeof(irq_t), 0);
    161        
     163        irq = malloc(sizeof(irq_t), 0);
    162164        irq_initialize(irq);
    163165        irq->devno = devno;
     
    175177         * answerbox's list.
    176178         */
    177         irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    178        
    179         link_t *hlp = hash_table_find(&irq_uspace_hash_table, key);
     179        ipl = interrupts_disable();
     180        spinlock_lock(&irq_uspace_hash_table_lock);
     181        hlp = hash_table_find(&irq_uspace_hash_table, key);
    180182        if (hlp) {
    181                 irq_t *hirq = hash_table_get_instance(hlp, irq_t, link);
     183                irq_t *hirq __attribute__((unused))
     184                    = hash_table_get_instance(hlp, irq_t, link);
    182185               
    183186                /* hirq is locked */
    184                 irq_spinlock_unlock(&hirq->lock, false);
     187                spinlock_unlock(&hirq->lock);
    185188                code_free(code);
    186                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    187                
     189                spinlock_unlock(&irq_uspace_hash_table_lock);
    188190                free(irq);
     191                interrupts_restore(ipl);
    189192                return EEXISTS;
    190193        }
    191194       
    192         /* Locking is not really necessary, but paranoid */
    193         irq_spinlock_lock(&irq->lock, false);
    194         irq_spinlock_lock(&box->irq_lock, false);
    195        
     195        spinlock_lock(&irq->lock);  /* Not really necessary, but paranoid */
     196        spinlock_lock(&box->irq_lock);
    196197        hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
    197198        list_append(&irq->notif_cfg.link, &box->irq_head);
    198        
    199         irq_spinlock_unlock(&box->irq_lock, false);
    200         irq_spinlock_unlock(&irq->lock, false);
    201         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    202        
     199        spinlock_unlock(&box->irq_lock);
     200        spinlock_unlock(&irq->lock);
     201        spinlock_unlock(&irq_uspace_hash_table_lock);
     202       
     203        interrupts_restore(ipl);
    203204        return EOK;
    204205}
     
    206207/** Unregister task from IRQ notification.
    207208 *
    208  * @param box   Answerbox associated with the notification.
    209  * @param inr   IRQ number.
    210  * @param devno Device number.
    211  *
     209 * @param box           Answerbox associated with the notification.
     210 * @param inr           IRQ number.
     211 * @param devno         Device number.
    212212 */
    213213int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
    214214{
     215        ipl_t ipl;
    215216        unative_t key[] = {
    216217                (unative_t) inr,
    217218                (unative_t) devno
    218219        };
    219        
    220         irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    221         link_t *lnk = hash_table_find(&irq_uspace_hash_table, key);
     220        link_t *lnk;
     221        irq_t *irq;
     222
     223        ipl = interrupts_disable();
     224        spinlock_lock(&irq_uspace_hash_table_lock);
     225        lnk = hash_table_find(&irq_uspace_hash_table, key);
    222226        if (!lnk) {
    223                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     227                spinlock_unlock(&irq_uspace_hash_table_lock);
     228                interrupts_restore(ipl);
    224229                return ENOENT;
    225230        }
    226        
    227         irq_t *irq = hash_table_get_instance(lnk, irq_t, link);
    228        
     231        irq = hash_table_get_instance(lnk, irq_t, link);
    229232        /* irq is locked */
    230         irq_spinlock_lock(&box->irq_lock, false);
     233        spinlock_lock(&box->irq_lock);
    231234       
    232235        ASSERT(irq->notif_cfg.answerbox == box);
     
    234237        /* Free up the pseudo code and associated structures. */
    235238        code_free(irq->notif_cfg.code);
    236        
    237         /* Remove the IRQ from the answerbox's list. */
     239
     240        /* Remove the IRQ from the answerbox's list. */ 
    238241        list_remove(&irq->notif_cfg.link);
    239        
     242
    240243        /*
    241244         * We need to drop the IRQ lock now because hash_table_remove() will try
     
    245248         * the meantime.
    246249         */
    247         irq_spinlock_unlock(&irq->lock, false);
    248        
     250        spinlock_unlock(&irq->lock);
     251
    249252        /* Remove the IRQ from the uspace IRQ hash table. */
    250253        hash_table_remove(&irq_uspace_hash_table, key, 2);
    251254       
    252         irq_spinlock_unlock(&box->irq_lock, false);
    253         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     255        spinlock_unlock(&irq_uspace_hash_table_lock);
     256        spinlock_unlock(&box->irq_lock);
    254257       
    255258        /* Free up the IRQ structure. */
    256259        free(irq);
    257260       
     261        interrupts_restore(ipl);
    258262        return EOK;
    259263}
     264
    260265
    261266/** Disconnect all IRQ notifications from an answerbox.
     
    265270 * send notifications to it.
    266271 *
    267  * @param box Answerbox for which we want to carry out the cleanup.
    268  *
     272 * @param box           Answerbox for which we want to carry out the cleanup.
    269273 */
    270274void ipc_irq_cleanup(answerbox_t *box)
    271275{
     276        ipl_t ipl;
     277       
    272278loop:
    273         irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    274         irq_spinlock_lock(&box->irq_lock, false);
     279        ipl = interrupts_disable();
     280        spinlock_lock(&irq_uspace_hash_table_lock);
     281        spinlock_lock(&box->irq_lock);
    275282       
    276283        while (box->irq_head.next != &box->irq_head) {
     284                link_t *cur = box->irq_head.next;
     285                irq_t *irq;
    277286                DEADLOCK_PROBE_INIT(p_irqlock);
    278                
    279                 irq_t *irq = list_get_instance(box->irq_head.next, irq_t,
    280                     notif_cfg.link);
    281                
    282                 if (!irq_spinlock_trylock(&irq->lock)) {
     287                unative_t key[2];
     288               
     289                irq = list_get_instance(cur, irq_t, notif_cfg.link);
     290                if (!spinlock_trylock(&irq->lock)) {
    283291                        /*
    284292                         * Avoid deadlock by trying again.
    285293                         */
    286                         irq_spinlock_unlock(&box->irq_lock, false);
    287                         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     294                        spinlock_unlock(&box->irq_lock);
     295                        spinlock_unlock(&irq_uspace_hash_table_lock);
     296                        interrupts_restore(ipl);
    288297                        DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
    289298                        goto loop;
    290299                }
    291                
    292                 unative_t key[2];
    293300                key[0] = irq->inr;
    294301                key[1] = irq->devno;
     302               
    295303               
    296304                ASSERT(irq->notif_cfg.answerbox == box);
     
    309317                 * didn't drop the hash table lock in the meantime.
    310318                 */
    311                 irq_spinlock_unlock(&irq->lock, false);
     319                spinlock_unlock(&irq->lock);
    312320               
    313321                /* Remove from the hash table. */
     
    317325        }
    318326       
    319         irq_spinlock_unlock(&box->irq_lock, false);
    320         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     327        spinlock_unlock(&box->irq_lock);
     328        spinlock_unlock(&irq_uspace_hash_table_lock);
     329        interrupts_restore(ipl);
    321330}
    322331
    323332/** Add a call to the proper answerbox queue.
    324333 *
    325  * Assume irq->lock is locked and interrupts disabled.
    326  *
    327  * @param irq  IRQ structure referencing the target answerbox.
    328  * @param call IRQ notification call.
    329  *
     334 * Assume irq->lock is locked.
     335 *
     336 * @param irq           IRQ structure referencing the target answerbox.
     337 * @param call          IRQ notification call.
    330338 */
    331339static void send_call(irq_t *irq, call_t *call)
    332340{
    333         irq_spinlock_lock(&irq->notif_cfg.answerbox->irq_lock, false);
     341        spinlock_lock(&irq->notif_cfg.answerbox->irq_lock);
    334342        list_append(&call->link, &irq->notif_cfg.answerbox->irq_notifs);
    335         irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false);
    336        
     343        spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock);
     344               
    337345        waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST);
    338346}
     
    340348/** Apply the top-half pseudo code to find out whether to accept the IRQ or not.
    341349 *
    342  * @param irq IRQ structure.
    343  *
    344  * @return IRQ_ACCEPT if the interrupt is accepted by the
    345  *         pseudocode, IRQ_DECLINE otherwise.
    346  *
     350 * @param irq           IRQ structure.
     351 *
     352 * @return              IRQ_ACCEPT if the interrupt is accepted by the
     353 *                      pseudocode. IRQ_DECLINE otherwise.
    347354 */
    348355irq_ownership_t ipc_irq_top_half_claim(irq_t *irq)
    349356{
     357        unsigned int i;
     358        unative_t dstval;
    350359        irq_code_t *code = irq->notif_cfg.code;
    351         uint32_t *scratch = irq->notif_cfg.scratch;
     360        unative_t *scratch = irq->notif_cfg.scratch;
     361
    352362       
    353363        if (!irq->notif_cfg.notify)
     
    357367                return IRQ_DECLINE;
    358368       
    359         size_t i;
    360369        for (i = 0; i < code->cmdcount; i++) {
    361                 uint32_t dstval;
    362                 uintptr_t srcarg = code->cmds[i].srcarg;
    363                 uintptr_t dstarg = code->cmds[i].dstarg;
     370                unsigned int srcarg = code->cmds[i].srcarg;
     371                unsigned int dstarg = code->cmds[i].dstarg;
    364372               
    365373                if (srcarg >= IPC_CALL_LEN)
    366374                        break;
    367                
    368375                if (dstarg >= IPC_CALL_LEN)
    369376                        break;
     
    398405                        break;
    399406                case CMD_BTEST:
    400                         if ((srcarg) && (dstarg)) {
     407                        if (srcarg && dstarg) {
    401408                                dstval = scratch[srcarg] & code->cmds[i].value;
    402409                                scratch[dstarg] = dstval;
     
    404411                        break;
    405412                case CMD_PREDICATE:
    406                         if ((srcarg) && (!scratch[srcarg])) {
     413                        if (srcarg && !scratch[srcarg]) {
    407414                                i += code->cmds[i].value;
    408415                                continue;
     
    420427}
    421428
     429
    422430/* IRQ top-half handler.
    423431 *
    424432 * We expect interrupts to be disabled and the irq->lock already held.
    425433 *
    426  * @param irq IRQ structure.
    427  *
     434 * @param irq           IRQ structure.
    428435 */
    429436void ipc_irq_top_half_handler(irq_t *irq)
     
    431438        ASSERT(irq);
    432439
    433         ASSERT(interrupts_disabled());
    434         ASSERT(irq_spinlock_locked(&irq->lock));
    435        
    436440        if (irq->notif_cfg.answerbox) {
    437                 call_t *call = ipc_call_alloc(FRAME_ATOMIC);
     441                call_t *call;
     442
     443                call = ipc_call_alloc(FRAME_ATOMIC);
    438444                if (!call)
    439445                        return;
     
    442448                /* Put a counter to the message */
    443449                call->priv = ++irq->notif_cfg.counter;
    444                
     450
    445451                /* Set up args */
    446452                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
     
    450456                IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]);
    451457                IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]);
    452                
     458
    453459                send_call(irq, call);
    454460        }
     
    457463/** Send notification message.
    458464 *
    459  * @param irq IRQ structure.
    460  * @param a1  Driver-specific payload argument.
    461  * @param a2  Driver-specific payload argument.
    462  * @param a3  Driver-specific payload argument.
    463  * @param a4  Driver-specific payload argument.
    464  * @param a5  Driver-specific payload argument.
    465  *
     465 * @param irq           IRQ structure.
     466 * @param a1            Driver-specific payload argument.
     467 * @param a2            Driver-specific payload argument.
     468 * @param a3            Driver-specific payload argument.
     469 * @param a4            Driver-specific payload argument.
     470 * @param a5            Driver-specific payload argument.
    466471 */
    467472void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
    468473    unative_t a4, unative_t a5)
    469474{
    470         irq_spinlock_lock(&irq->lock, true);
    471        
     475        call_t *call;
     476
     477        spinlock_lock(&irq->lock);
     478
    472479        if (irq->notif_cfg.answerbox) {
    473                 call_t *call = ipc_call_alloc(FRAME_ATOMIC);
     480                call = ipc_call_alloc(FRAME_ATOMIC);
    474481                if (!call) {
    475                         irq_spinlock_unlock(&irq->lock, true);
     482                        spinlock_unlock(&irq->lock);
    476483                        return;
    477484                }
    478                
    479485                call->flags |= IPC_CALL_NOTIF;
    480486                /* Put a counter to the message */
    481487                call->priv = ++irq->notif_cfg.counter;
    482                
     488
    483489                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
    484490                IPC_SET_ARG1(call->data, a1);
     
    490496                send_call(irq, call);
    491497        }
    492        
    493         irq_spinlock_unlock(&irq->lock, true);
     498        spinlock_unlock(&irq->lock);
    494499}
    495500
Note: See TracChangeset for help on using the changeset viewer.