Changeset 8136102 in mainline for uspace/srv/hw/netif/dp8390/ne2000.c


Ignore:
Timestamp:
2011-01-11T01:33:58Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6b22c97
Parents:
6643a19 (diff), 7300c37 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

improve correctness of the NE2000 driver w.r.t. parallelism of the interrupt notification handler

  • by masking off interrupts in the kernel interrupt handler, the core of the interrupt notification handler (fetching frames from the network card itself) always runs single-threaded (thus avoiding the issues with fetching of frames multiple times from different fibrils, causing ICMP replies to be duplicated)
  • the received frames are buffered locally and then sent to the NIL module with the interrupts unmasked again (thus another notification handler will be scheduled if the sending of the frames to the NIL module blocks)

there is still a synchronization issue without any clear root cause when the network card is flood-pinged even before it is being initialized

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hw/netif/dp8390/ne2000.c

    r6643a19 r8136102  
    6868#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
    6969
     70/** Return the TSR from the interrupt call.
     71 *
     72 * @param[in] call The interrupt call.
     73 *
     74 */
     75#define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
     76
    7077static int irc_service = 0;
    7178static int irc_phone = -1;
     
    7683static irq_cmd_t ne2k_cmds[] = {
    7784        {
     85                /* Read Interrupt Status Register */
    7886                .cmd = CMD_PIO_READ_8,
    7987                .addr = NULL,
     
    8189        },
    8290        {
     91                /* Mask supported interrupt causes */
    8392                .cmd = CMD_BTEST,
    84                 .value = 0x7f,
     93                .value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
     94                    ISR_CNT | ISR_RDC),
    8595                .srcarg = 2,
    8696                .dstarg = 3,
    8797        },
    8898        {
     99                /* Predicate for accepting the interrupt */
    89100                .cmd = CMD_PREDICATE,
    90                 .value = 2,
     101                .value = 4,
    91102                .srcarg = 3
    92103        },
    93104        {
     105                /*
     106                 * Mask future interrupts via
     107                 * Interrupt Mask Register
     108                 */
     109                .cmd = CMD_PIO_WRITE_8,
     110                .addr = NULL,
     111                .value = 0
     112        },
     113        {
     114                /* Acknowledge the current interrupt */
    94115                .cmd = CMD_PIO_WRITE_A_8,
    95116                .addr = NULL,
    96117                .srcarg = 3
     118        },
     119        {
     120                /* Read Transmit Status Register */
     121                .cmd = CMD_PIO_READ_8,
     122                .addr = NULL,
     123                .dstarg = 3
    97124        },
    98125        {
     
    111138/** Handle the interrupt notification.
    112139 *
    113  * This is the interrupt notification function.
     140 * This is the interrupt notification function. It is quarantied
     141 * that there is only a single instance of this notification
     142 * function running at one time until the return from the
     143 * ne2k_interrupt() function (where the interrupts are unmasked
     144 * again).
    114145 *
    115146 * @param[in] iid  Interrupt notification identifier.
     
    134165        fibril_rwlock_read_unlock(&netif_globals.lock);
    135166       
    136         if (ne2k != NULL)
    137                 ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id);
     167        if (ne2k != NULL) {
     168                link_t *frames =
     169                    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
     170               
     171                if (frames != NULL) {
     172                        while (!list_empty(frames)) {
     173                                frame_t *frame =
     174                                    list_get_instance(frames->next, frame_t, link);
     175                               
     176                                list_remove(&frame->link);
     177                                nil_received_msg(nil_phone, device_id, frame->packet,
     178                                    SERVICE_NONE);
     179                                free(frame);
     180                        }
     181                       
     182                        free(frames);
     183                }
     184        }
    138185}
    139186
     
    265312               
    266313                ne2k_cmds[0].addr = ne2k->port + DP_ISR;
    267                 ne2k_cmds[3].addr = ne2k_cmds[0].addr;
     314                ne2k_cmds[3].addr = ne2k->port + DP_IMR;
     315                ne2k_cmds[4].addr = ne2k_cmds[0].addr;
    268316               
    269317                int rc = ipc_register_irq(ne2k->irq, device->device_id,
     
    278326                }
    279327               
     328                change_state(device, NETIF_ACTIVE);
     329               
    280330                if (irc_service)
    281331                        async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
    282                
    283                 change_state(device, NETIF_ACTIVE);
    284332        }
    285333       
Note: See TracChangeset for help on using the changeset viewer.