The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System, Second Edition

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netatm/atm_subr.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *
    3  * ===================================
    4  * HARP  |  Host ATM Research Platform
    5  * ===================================
    6  *
    7  *
    8  * This Host ATM Research Platform ("HARP") file (the "Software") is
    9  * made available by Network Computing Services, Inc. ("NetworkCS")
   10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   11  * support of any kind.
   12  *
   13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   17  * In no event shall NetworkCS be responsible for any damages, including
   18  * but not limited to consequential damages, arising from or relating to
   19  * any use of the Software or related support.
   20  *
   21  * Copyright 1994-1998 Network Computing Services, Inc.
   22  *
   23  * Copies of this Software may be made, however, the above copyright
   24  * notice must be reproduced on all copies.
   25  *
   26  *      @(#) $FreeBSD: src/sys/netatm/atm_subr.c,v 1.3.2.1 1999/08/29 16:28:47 peter Exp $
   27  *
   28  */
   29 
   30 /*
   31  * Core ATM Services
   32  * -----------------
   33  *
   34  * Miscellaneous ATM subroutines
   35  *
   36  */
   37 
   38 #include <netatm/kern_include.h>
   39 
   40 #ifndef lint
   41 __RCSID("@(#) $FreeBSD: src/sys/netatm/atm_subr.c,v 1.3.2.1 1999/08/29 16:28:47 peter Exp $");
   42 #endif
   43 
   44 
   45 /*
   46  * Global variables
   47  */
   48 struct atm_pif          *atm_interface_head = NULL;
   49 struct atm_ncm          *atm_netconv_head = NULL;
   50 Atm_endpoint            *atm_endpoints[ENDPT_MAX+1] = {NULL};
   51 struct sp_info          *atm_pool_head = NULL;
   52 struct stackq_entry     *atm_stackq_head = NULL, *atm_stackq_tail;
   53 struct ifqueue          atm_intrq;
   54 #ifdef sgi
   55 int                     atm_intr_index;
   56 #endif
   57 struct atm_sock_stat    atm_sock_stat = {0};
   58 int                     atm_init = 0;
   59 int                     atm_debug = 0;
   60 int                     atm_dev_print = 0;
   61 int                     atm_print_data = 0;
   62 int                     atm_version = ATM_VERSION;
   63 struct timeval          atm_debugtime = {0, 0};
   64 
   65 struct sp_info  atm_attributes_pool = {
   66         "atm attributes pool",          /* si_name */
   67         sizeof(Atm_attributes),         /* si_blksiz */
   68         10,                             /* si_blkcnt */
   69         100                             /* si_maxallow */
   70 };
   71 
   72 
   73 /*
   74  * Local functions
   75  */
   76 static void     atm_compact __P((struct atm_time *));
   77 static KTimeout_ret     atm_timexp __P((void *));
   78 
   79 /*
   80  * Local variables
   81  */
   82 static struct atm_time  *atm_timeq = NULL;
   83 static struct atm_time  atm_compactimer = {0, 0};
   84 
   85 static struct sp_info   atm_stackq_pool = {
   86         "Service stack queue pool",     /* si_name */
   87         sizeof(struct stackq_entry),    /* si_blksiz */
   88         10,                             /* si_blkcnt */
   89         10                              /* si_maxallow */
   90 };
   91 
   92 
   93 /*
   94  * Initialize ATM kernel
   95  * 
   96  * Performs any initialization required before things really get underway.
   97  * Called from ATM domain initialization or from first registration function 
   98  * which gets called.
   99  *
  100  * Arguments:
  101  *      none
  102  *
  103  * Returns:
  104  *      none
  105  *
  106  */
  107 void
  108 atm_initialize()
  109 {
  110         /*
  111          * Never called from interrupts, so no locking needed
  112          */
  113         if (atm_init)
  114                 return;
  115         atm_init = 1;
  116 
  117 #ifndef __FreeBSD__
  118         /*
  119          * Add ATM protocol family
  120          */
  121         (void) protocol_family(&atmdomain, NULL, NULL);
  122 #endif
  123 
  124         atm_intrq.ifq_maxlen = ATM_INTRQ_MAX;
  125 #ifdef sgi
  126         atm_intr_index = register_isr(atm_intr);
  127 #endif
  128 
  129         /*
  130          * Initialize subsystems
  131          */
  132         atm_aal5_init();
  133 
  134         /*
  135          * Prime the timer
  136          */
  137         (void) timeout(atm_timexp, (void *)0, hz/ATM_HZ);
  138 
  139         /*
  140          * Start the compaction timer
  141          */
  142         atm_timeout(&atm_compactimer, SPOOL_COMPACT, atm_compact);
  143 }
  144 
  145 
  146 /*
  147  * Allocate a Control Block
  148  * 
  149  * Gets a new control block allocated from the specified storage pool, 
  150  * acquiring memory for new pool chunks if required.  The returned control
  151  * block's contents will be cleared.
  152  *
  153  * Arguments:
  154  *      sip     pointer to sp_info for storage pool
  155  *
  156  * Returns:
  157  *      addr    pointer to allocated control block
  158  *      0       allocation failed
  159  *
  160  */
  161 void *
  162 atm_allocate(sip)
  163         struct sp_info  *sip;
  164 {
  165         void            *bp;
  166         struct sp_chunk *scp;
  167         struct sp_link  *slp;
  168         int             s = splnet();
  169 
  170         /*
  171          * Count calls
  172          */
  173         sip->si_allocs++;
  174 
  175         /*
  176          * Are there any free in the pool?
  177          */
  178         if (sip->si_free) {
  179 
  180                 /*
  181                  * Find first chunk with a free block
  182                  */
  183                 for (scp = sip->si_poolh; scp; scp = scp->sc_next) {
  184                         if (scp->sc_freeh != NULL)
  185                                 break;
  186                 }
  187 
  188         } else {
  189 
  190                 /*
  191                  * No free blocks - have to allocate a new
  192                  * chunk (but put a limit to this)
  193                  */
  194                 struct sp_link  *slp_next;
  195                 int     i;
  196 
  197                 /*
  198                  * First time for this pool??
  199                  */
  200                 if (sip->si_chunksiz == 0) {
  201                         size_t  n;
  202 
  203                         /*
  204                          * Initialize pool information
  205                          */
  206                         n = sizeof(struct sp_chunk) +
  207                                 sip->si_blkcnt * 
  208                                 (sip->si_blksiz + sizeof(struct sp_link));
  209                         sip->si_chunksiz = roundup(n, SPOOL_ROUNDUP);
  210 
  211                         /*
  212                          * Place pool on kernel chain
  213                          */
  214                         LINK2TAIL(sip, struct sp_info, atm_pool_head, si_next);
  215                 }
  216 
  217                 if (sip->si_chunks >= sip->si_maxallow) {
  218                         sip->si_fails++;
  219                         (void) splx(s);
  220                         return (NULL);
  221                 }
  222 
  223                 scp = (struct sp_chunk *)
  224                         KM_ALLOC(sip->si_chunksiz, M_DEVBUF, M_NOWAIT);
  225                 if (scp == NULL) {
  226                         sip->si_fails++;
  227                         (void) splx(s);
  228                         return (NULL);
  229                 }
  230                 scp->sc_next = NULL;
  231                 scp->sc_info = sip;
  232                 scp->sc_magic = SPOOL_MAGIC;
  233                 scp->sc_used = 0;
  234 
  235                 /*
  236                  * Divy up chunk into free blocks
  237                  */
  238                 slp = (struct sp_link *)(scp + 1);
  239                 scp->sc_freeh = slp;
  240 
  241                 for (i = sip->si_blkcnt; i > 1; i--) { 
  242                         slp_next = (struct sp_link *)((caddr_t)(slp + 1) + 
  243                                         sip->si_blksiz);
  244                         slp->sl_u.slu_next = slp_next;
  245                         slp = slp_next;
  246                 }
  247                 slp->sl_u.slu_next = NULL;
  248                 scp->sc_freet = slp;
  249 
  250                 /*
  251                  * Add new chunk to end of pool
  252                  */
  253                 if (sip->si_poolh)
  254                         sip->si_poolt->sc_next = scp;
  255                 else
  256                         sip->si_poolh = scp;
  257                 sip->si_poolt = scp;
  258                 
  259                 sip->si_chunks++;
  260                 sip->si_total += sip->si_blkcnt;
  261                 sip->si_free += sip->si_blkcnt;
  262                 if (sip->si_chunks > sip->si_maxused)
  263                         sip->si_maxused = sip->si_chunks;
  264         }
  265 
  266         /*
  267          * Allocate the first free block in chunk
  268          */
  269         slp = scp->sc_freeh;
  270         scp->sc_freeh = slp->sl_u.slu_next;
  271         scp->sc_used++;
  272         sip->si_free--;
  273         bp = (slp + 1);
  274 
  275         /*
  276          * Save link back to pool chunk
  277          */
  278         slp->sl_u.slu_chunk = scp;
  279 
  280         /*
  281          * Clear out block
  282          */
  283         KM_ZERO(bp, sip->si_blksiz);
  284 
  285         (void) splx(s);
  286         return (bp);
  287 }
  288 
  289 
  290 /*
  291  * Free a Control Block
  292  * 
  293  * Returns a previously allocated control block back to the owners 
  294  * storage pool.  
  295  *
  296  * Arguments:
  297  *      bp      pointer to block to be freed
  298  *
  299  * Returns:
  300  *      none
  301  *
  302  */
  303 void
  304 atm_free(bp)
  305         void            *bp;
  306 {
  307         struct sp_info  *sip;
  308         struct sp_chunk *scp;
  309         struct sp_link  *slp;
  310         int             s = splnet();
  311 
  312         /*
  313          * Get containing chunk and pool info
  314          */
  315         slp = (struct sp_link *)bp;
  316         slp--;
  317         scp = slp->sl_u.slu_chunk;
  318         if (scp->sc_magic != SPOOL_MAGIC)
  319                 panic("atm_free: chunk magic missing");
  320         sip = scp->sc_info;
  321 
  322         /*
  323          * Add block to free chain
  324          */
  325         if (scp->sc_freeh) {
  326                 scp->sc_freet->sl_u.slu_next = slp;
  327                 scp->sc_freet = slp;
  328         } else
  329                 scp->sc_freeh = scp->sc_freet = slp;
  330         slp->sl_u.slu_next = NULL;
  331         sip->si_free++;
  332         scp->sc_used--;
  333 
  334         (void) splx(s);
  335         return;
  336 }
  337 
  338 
  339 /*
  340  * Storage Pool Compaction
  341  * 
  342  * Called periodically in order to perform compaction of the
  343  * storage pools.  Each pool will be checked to see if any chunks 
  344  * can be freed, taking some care to avoid freeing too many chunks
  345  * in order to avoid memory thrashing.
  346  *
  347  * Called at splnet.
  348  *
  349  * Arguments:
  350  *      tip     pointer to timer control block (atm_compactimer)
  351  *
  352  * Returns:
  353  *      none
  354  *
  355  */
  356 static void
  357 atm_compact(tip)
  358         struct atm_time *tip;
  359 {
  360         struct sp_info  *sip;
  361         struct sp_chunk *scp;
  362         int             i;
  363         struct sp_chunk *scp_prev;
  364 
  365         /*
  366          * Check out all storage pools
  367          */
  368         for (sip = atm_pool_head; sip; sip = sip->si_next) {
  369 
  370                 /*
  371                  * Always keep a minimum number of chunks around
  372                  */
  373                 if (sip->si_chunks <= SPOOL_MIN_CHUNK)
  374                         continue;
  375 
  376                 /*
  377                  * Maximum chunks to free at one time will leave
  378                  * pool with at least 50% utilization, but never
  379                  * go below minimum chunk count.
  380                  */
  381                 i = ((sip->si_free * 2) - sip->si_total) / sip->si_blkcnt;
  382                 i = MIN(i, sip->si_chunks - SPOOL_MIN_CHUNK);
  383 
  384                 /*
  385                  * Look for chunks to free
  386                  */
  387                 scp_prev = NULL;
  388                 for (scp = sip->si_poolh; scp && i > 0; ) {
  389 
  390                         if (scp->sc_used == 0) {
  391 
  392                                 /*
  393                                  * Found a chunk to free, so do it
  394                                  */
  395                                 if (scp_prev) {
  396                                         scp_prev->sc_next = scp->sc_next;
  397                                         if (sip->si_poolt == scp)
  398                                                 sip->si_poolt = scp_prev;
  399                                 } else
  400                                         sip->si_poolh = scp->sc_next;
  401 
  402                                 KM_FREE((caddr_t)scp, sip->si_chunksiz,
  403                                         M_DEVBUF);
  404 
  405                                 /*
  406                                  * Update pool controls
  407                                  */
  408                                 sip->si_chunks--;
  409                                 sip->si_total -= sip->si_blkcnt;
  410                                 sip->si_free -= sip->si_blkcnt;
  411                                 i--;
  412                                 if (scp_prev)
  413                                         scp = scp_prev->sc_next;
  414                                 else
  415                                         scp = sip->si_poolh;
  416                         } else {
  417                                 scp_prev = scp;
  418                                 scp = scp->sc_next;
  419                         }
  420                 }
  421         }
  422 
  423         /*
  424          * Restart the compaction timer
  425          */
  426         atm_timeout(&atm_compactimer, SPOOL_COMPACT, atm_compact);
  427 
  428         return;
  429 }
  430 
  431 
  432 /*
  433  * Release a Storage Pool
  434  * 
  435  * Frees all dynamic storage acquired for a storage pool.
  436  * This function is normally called just prior to a module's unloading.
  437  *
  438  * Arguments:
  439  *      sip     pointer to sp_info for storage pool
  440  *
  441  * Returns:
  442  *      none
  443  *
  444  */
  445 void
  446 atm_release_pool(sip)
  447         struct sp_info  *sip;
  448 {
  449         struct sp_chunk *scp, *scp_next;
  450         int             s = splnet();
  451 
  452         /*
  453          * Free each chunk in pool
  454          */
  455         for (scp = sip->si_poolh; scp; scp = scp_next) {
  456 
  457                 /*
  458                  * Check for memory leaks
  459                  */
  460                 if (scp->sc_used)
  461                         panic("atm_release_pool: unfreed blocks");
  462 
  463                 scp_next = scp->sc_next;
  464 
  465                 KM_FREE((caddr_t)scp, sip->si_chunksiz, M_DEVBUF);
  466         }
  467 
  468         /*
  469          * Update pool controls
  470          */
  471         sip->si_poolh = NULL;
  472         sip->si_chunks = 0;
  473         sip->si_total = 0;
  474         sip->si_free = 0;
  475 
  476         /*
  477          * Unlink pool from active chain
  478          */
  479         sip->si_chunksiz = 0;
  480         UNLINK(sip, struct sp_info, atm_pool_head, si_next);
  481 
  482         (void) splx(s);
  483         return;
  484 }
  485 
  486 
  487 /*
  488  * Handle timer tick expiration
  489  * 
  490  * Decrement tick count in first block on timer queue.  If there
  491  * are blocks with expired timers, call their timeout function.
  492  * This function is called ATM_HZ times per second.
  493  *
  494  * Arguments:
  495  *      arg     argument passed on timeout() call
  496  *
  497  * Returns:
  498  *      none
  499  *
  500  */
  501 static KTimeout_ret
  502 atm_timexp(arg)
  503         void    *arg;
  504 {
  505         struct atm_time *tip;
  506         int             s = splimp();
  507 
  508 
  509         /*
  510          * Decrement tick count
  511          */
  512         if (((tip = atm_timeq) == NULL) || (--tip->ti_ticks > 0)) {
  513                 goto restart;
  514         }
  515 
  516         /*
  517          * Stack queue should have been drained
  518          */
  519 #ifdef DIAGNOSTIC
  520         if (atm_stackq_head != NULL)
  521                 panic("atm_timexp: stack queue not empty");
  522 #endif
  523 
  524         /*
  525          * Dispatch expired timers
  526          */
  527         while (((tip = atm_timeq) != NULL) && (tip->ti_ticks == 0)) {
  528                 void    (*func)__P((struct atm_time *));
  529 
  530                 /*
  531                  * Remove expired block from queue
  532                  */
  533                 atm_timeq = tip->ti_next;
  534                 tip->ti_flag &= ~TIF_QUEUED;
  535 
  536                 /*
  537                  * Call timeout handler (with network interrupts locked out)
  538                  */
  539                 func = tip->ti_func;
  540                 (void) splx(s);
  541                 s = splnet();
  542                 (*func)(tip);
  543                 (void) splx(s);
  544                 s = splimp();
  545 
  546                 /*
  547                  * Drain any deferred calls
  548                  */
  549                 STACK_DRAIN();
  550         }
  551 
  552 restart:
  553         /*
  554          * Restart the timer
  555          */
  556         (void) splx(s);
  557         (void) timeout(atm_timexp, (void *)0, hz/ATM_HZ);
  558 
  559         return;
  560 }
  561 
  562 
  563 /*
  564  * Schedule a control block timeout
  565  * 
  566  * Place the supplied timer control block on the timer queue.  The
  567  * function (func) will be called in 't' timer ticks with the
  568  * control block address as its only argument.  There are ATM_HZ
  569  * timer ticks per second.  The ticks value stored in each block is
  570  * a delta of the number of ticks from the previous block in the queue.
  571  * Thus, for each tick interval, only the first block in the queue 
  572  * needs to have its tick value decremented.
  573  *
  574  * Arguments:
  575  *      tip     pointer to timer control block
  576  *      t       number of timer ticks until expiration
  577  *      func    pointer to function to call at expiration 
  578  *
  579  * Returns:
  580  *      none
  581  *
  582  */
  583 void
  584 atm_timeout(tip, t, func)
  585         struct atm_time *tip;
  586         int             t;
  587         void            (*func)__P((struct atm_time *));
  588 {
  589         struct atm_time *tip1, *tip2;
  590         int             s;
  591 
  592 
  593         /*
  594          * Check for double queueing error
  595          */
  596         if (tip->ti_flag & TIF_QUEUED)
  597                 panic("atm_timeout: double queueing");
  598 
  599         /*
  600          * Make sure we delay at least a little bit
  601          */
  602         if (t <= 0)
  603                 t = 1;
  604 
  605         /*
  606          * Find out where we belong on the queue
  607          */
  608         s = splimp();
  609         for (tip1 = NULL, tip2 = atm_timeq; tip2 && (tip2->ti_ticks <= t); 
  610                                             tip1 = tip2, tip2 = tip1->ti_next) {
  611                 t -= tip2->ti_ticks;
  612         }
  613 
  614         /*
  615          * Place ourselves on queue and update timer deltas
  616          */
  617         if (tip1 == NULL)
  618                 atm_timeq = tip;
  619         else
  620                 tip1->ti_next = tip;
  621         tip->ti_next = tip2;
  622 
  623         if (tip2)
  624                 tip2->ti_ticks -= t;
  625         
  626         /*
  627          * Setup timer block
  628          */
  629         tip->ti_flag |= TIF_QUEUED;
  630         tip->ti_ticks = t;
  631         tip->ti_func = func;
  632 
  633         (void) splx(s);
  634         return;
  635 }
  636 
  637 
  638 /*
  639  * Cancel a timeout
  640  * 
  641  * Remove the supplied timer control block from the timer queue.
  642  *
  643  * Arguments:
  644  *      tip     pointer to timer control block
  645  *
  646  * Returns:
  647  *      0       control block successfully dequeued
  648  *      1       control block not on timer queue
  649  *
  650  */
  651 int
  652 atm_untimeout(tip)
  653         struct atm_time *tip;
  654 {
  655         struct atm_time *tip1, *tip2;
  656         int             s;
  657 
  658         /*
  659          * Is control block queued?
  660          */
  661         if ((tip->ti_flag & TIF_QUEUED) == 0)
  662                 return(1);
  663 
  664         /*
  665          * Find control block on the queue
  666          */
  667         s = splimp();
  668         for (tip1 = NULL, tip2 = atm_timeq; tip2 && (tip2 != tip); 
  669                                             tip1 = tip2, tip2 = tip1->ti_next) {
  670         }
  671 
  672         if (tip2 == NULL) {
  673                 (void) splx(s);
  674                 return (1);
  675         }
  676 
  677         /*
  678          * Remove block from queue and update timer deltas
  679          */
  680         tip2 = tip->ti_next;
  681         if (tip1 == NULL)
  682                 atm_timeq = tip2;
  683         else
  684                 tip1->ti_next = tip2;
  685 
  686         if (tip2)
  687                 tip2->ti_ticks += tip->ti_ticks;
  688         
  689         /*
  690          * Reset timer block
  691          */
  692         tip->ti_flag &= ~TIF_QUEUED;
  693 
  694         (void) splx(s);
  695         return (0);
  696 }
  697 
  698 
  699 /*
  700  * Queue a Stack Call 
  701  * 
  702  * Queues a stack call which must be deferred to the global stack queue.
  703  * The call parameters are stored in entries which are allocated from the
  704  * stack queue storage pool.
  705  *
  706  * Arguments:
  707  *      cmd     stack command
  708  *      func    destination function
  709  *      token   destination layer's token
  710  *      cvp     pointer to  connection vcc
  711  *      arg1    command argument
  712  *      arg2    command argument
  713  *
  714  * Returns:
  715  *      0       call queued
  716  *      errno   call not queued - reason indicated
  717  *
  718  */
  719 int
  720 atm_stack_enq(cmd, func, token, cvp, arg1, arg2)
  721         int             cmd;
  722         void            (*func)__P((int, void *, int, int));
  723         void            *token;
  724         Atm_connvc      *cvp;
  725         int             arg1;
  726         int             arg2;
  727 {
  728         struct stackq_entry     *sqp;
  729         int             s = splnet();
  730 
  731         /*
  732          * Get a new queue entry for this call
  733          */
  734         sqp = (struct stackq_entry *)atm_allocate(&atm_stackq_pool);
  735         if (sqp == NULL) {
  736                 (void) splx(s);
  737                 return (ENOMEM);
  738         }
  739 
  740         /*
  741          * Fill in new entry
  742          */
  743         sqp->sq_next = NULL;
  744         sqp->sq_cmd = cmd;
  745         sqp->sq_func = func;
  746         sqp->sq_token = token;
  747         sqp->sq_arg1 = arg1;
  748         sqp->sq_arg2 = arg2;
  749         sqp->sq_connvc = cvp;
  750 
  751         /*
  752          * Put new entry at end of queue
  753          */
  754         if (atm_stackq_head == NULL)
  755                 atm_stackq_head = sqp;
  756         else
  757                 atm_stackq_tail->sq_next = sqp;
  758         atm_stackq_tail = sqp;
  759 
  760         (void) splx(s);
  761         return (0);
  762 }
  763 
  764 
  765 /*
  766  * Drain the Stack Queue
  767  * 
  768  * Dequeues and processes entries from the global stack queue.  
  769  *
  770  * Arguments:
  771  *      none
  772  *
  773  * Returns:
  774  *      none
  775  *
  776  */
  777 void
  778 atm_stack_drain()
  779 {
  780         struct stackq_entry     *sqp, *qprev, *qnext;
  781         int             s = splnet();
  782         int             cnt;
  783 
  784         /*
  785          * Loop thru entire queue until queue is empty
  786          *      (but panic rather loop forever)
  787          */
  788         do {
  789                 cnt = 0;
  790                 qprev = NULL;
  791                 for (sqp = atm_stackq_head; sqp; ) {
  792 
  793                         /*
  794                          * Got an eligible entry, do STACK_CALL stuff
  795                          */
  796                         if (sqp->sq_cmd & STKCMD_UP) {
  797                                 if (sqp->sq_connvc->cvc_downcnt) {
  798 
  799                                         /*
  800                                          * Cant process now, skip it
  801                                          */
  802                                         qprev = sqp;
  803                                         sqp = sqp->sq_next;
  804                                         continue;
  805                                 }
  806 
  807                                 /*
  808                                  * OK, dispatch the call
  809                                  */
  810                                 sqp->sq_connvc->cvc_upcnt++;
  811                                 (*sqp->sq_func)(sqp->sq_cmd, 
  812                                                 sqp->sq_token,
  813                                                 sqp->sq_arg1,
  814                                                 sqp->sq_arg2);
  815                                 sqp->sq_connvc->cvc_upcnt--;
  816                         } else {
  817                                 if (sqp->sq_connvc->cvc_upcnt) {
  818 
  819                                         /*
  820                                          * Cant process now, skip it
  821                                          */
  822                                         qprev = sqp;
  823                                         sqp = sqp->sq_next;
  824                                         continue;
  825                                 }
  826 
  827                                 /*
  828                                  * OK, dispatch the call
  829                                  */
  830                                 sqp->sq_connvc->cvc_downcnt++;
  831                                 (*sqp->sq_func)(sqp->sq_cmd, 
  832                                                 sqp->sq_token,
  833                                                 sqp->sq_arg1,
  834                                                 sqp->sq_arg2);
  835                                 sqp->sq_connvc->cvc_downcnt--;
  836                         }
  837 
  838                         /*
  839                          * Dequeue processed entry and free it
  840                          */
  841                         cnt++;
  842                         qnext = sqp->sq_next;
  843                         if (qprev)
  844                                 qprev->sq_next = qnext;
  845                         else
  846                                 atm_stackq_head = qnext;
  847                         if (qnext == NULL)
  848                                 atm_stackq_tail = qprev;
  849                         atm_free((caddr_t)sqp);
  850                         sqp = qnext;
  851                 }
  852         } while (cnt > 0);
  853 
  854         /*
  855          * Make sure entire queue was drained
  856          */
  857         if (atm_stackq_head != NULL)
  858                 panic("atm_stack_drain: Queue not emptied");
  859 
  860         (void) splx(s);
  861 }
  862 
  863 
  864 /*
  865  * Process Interrupt Queue
  866  * 
  867  * Processes entries on the ATM interrupt queue.  This queue is used by
  868  * device interface drivers in order to schedule events from the driver's 
  869  * lower (interrupt) half to the driver's stack services.
  870  *
  871  * The interrupt routines must store the stack processing function to call
  872  * and a token (typically a driver/stack control block) at the front of the
  873  * queued buffer.  We assume that the function pointer and token values are 
  874  * both contained (and properly aligned) in the first buffer of the chain.
  875  *
  876  * Arguments:
  877  *      none
  878  *
  879  * Returns:
  880  *      none
  881  *
  882  */
  883 void
  884 atm_intr()
  885 {
  886         KBuffer         *m;
  887         caddr_t         cp;
  888         atm_intr_func_t func;
  889         void            *token;
  890         int             s;
  891 
  892         for (; ; ) {
  893                 /*
  894                  * Get next buffer from queue
  895                  */
  896                 s = splimp();
  897                 IF_DEQUEUE(&atm_intrq, m);
  898                 (void) splx(s);
  899                 if (m == NULL)
  900                         break;
  901 
  902                 /*
  903                  * Get function to call and token value
  904                  */
  905                 KB_DATASTART(m, cp, caddr_t);
  906                 func = *(atm_intr_func_t *)cp;
  907                 cp += sizeof(func);
  908                 token = *(void **)cp;
  909                 KB_HEADADJ(m, -(sizeof(func) + sizeof(token)));
  910                 if (KB_LEN(m) == 0) {
  911                         KBuffer         *m1;
  912                         KB_UNLINKHEAD(m, m1);
  913                         m = m1;
  914                 }
  915 
  916                 /*
  917                  * Call processing function
  918                  */
  919                 (*func)(token, m);
  920 
  921                 /*
  922                  * Drain any deferred calls
  923                  */
  924                 STACK_DRAIN();
  925         }
  926 }
  927 
  928 #ifdef __FreeBSD__
  929 NETISR_SET(NETISR_ATM, atm_intr);
  930 #endif
  931 
  932 
  933 /*
  934  * Print a pdu buffer chain
  935  * 
  936  * Arguments:
  937  *      m       pointer to pdu buffer chain
  938  *      msg     pointer to message header string
  939  *
  940  * Returns:
  941  *      none
  942  *
  943  */
  944 void
  945 atm_pdu_print(m, msg)
  946         KBuffer         *m;
  947         char            *msg;
  948 {
  949         caddr_t         cp;
  950         int             i;
  951         char            c = ' ';
  952 
  953         printf("%s:", msg);
  954         while (m) { 
  955                 KB_DATASTART(m, cp, caddr_t);
  956                 printf("%cbfr=%p data=%p len=%d: ",
  957                         c, m, cp, KB_LEN(m));
  958                 c = '\t';
  959                 if (atm_print_data) {
  960                         for (i = 0; i < KB_LEN(m); i++) {
  961                                 printf("%2x ", (u_char)*cp++);
  962                         }
  963                         printf("<end_bfr>\n");
  964                 } else {
  965                         printf("\n");
  966                 }
  967                 m = KB_NEXT(m);
  968         }
  969 }
  970 

Cache object: ad978679bbdfc579fae77f872f0ee3ea


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.