~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/atm/atm_misc.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* net/atm/atm_misc.c - Various functions for use by ATM drivers */
  2 
  3 /* Written 1995-2000 by Werner Almesberger, EPFL ICA */
  4 
  5 
  6 #include <linux/module.h>
  7 #include <linux/atm.h>
  8 #include <linux/atmdev.h>
  9 #include <linux/skbuff.h>
 10 #include <linux/sonet.h>
 11 #include <linux/bitops.h>
 12 #include <asm/atomic.h>
 13 #include <asm/errno.h>
 14 
 15 
 16 int atm_charge(struct atm_vcc *vcc,int truesize)
 17 {
 18         atm_force_charge(vcc,truesize);
 19         if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) return 1;
 20         atm_return(vcc,truesize);
 21         atomic_inc(&vcc->stats->rx_drop);
 22         return 0;
 23 }
 24 
 25 
 26 struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
 27     int gfp_flags)
 28 {
 29         int guess = atm_guess_pdu2truesize(pdu_size);
 30 
 31         atm_force_charge(vcc,guess);
 32         if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) {
 33                 struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
 34 
 35                 if (skb) {
 36                         atomic_add(skb->truesize-guess,&vcc->rx_inuse);
 37                         return skb;
 38                 }
 39         }
 40         atm_return(vcc,guess);
 41         atomic_inc(&vcc->stats->rx_drop);
 42         return NULL;
 43 }
 44 
 45 
 46 static int check_ci(struct atm_vcc *vcc,short vpi,int vci)
 47 {
 48         struct atm_vcc *walk;
 49 
 50         for (walk = vcc->dev->vccs; walk; walk = walk->next)
 51                 if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vpi == vpi &&
 52                     walk->vci == vci && ((walk->qos.txtp.traffic_class !=
 53                     ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) ||
 54                     (walk->qos.rxtp.traffic_class != ATM_NONE &&
 55                     vcc->qos.rxtp.traffic_class != ATM_NONE)))
 56                         return -EADDRINUSE;
 57                 /* allow VCCs with same VPI/VCI iff they don't collide on
 58                    TX/RX (but we may refuse such sharing for other reasons,
 59                    e.g. if protocol requires to have both channels) */
 60         return 0;
 61 }
 62 
 63 
 64 int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
 65 {
 66         static short p = 0; /* poor man's per-device cache */
 67         static int c = 0;
 68         short old_p;
 69         int old_c;
 70 
 71         if (*vpi != ATM_VPI_ANY && *vci != ATM_VCI_ANY)
 72                 return check_ci(vcc,*vpi,*vci);
 73         /* last scan may have left values out of bounds for current device */
 74         if (*vpi != ATM_VPI_ANY) p = *vpi;
 75         else if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
 76         if (*vci != ATM_VCI_ANY) c = *vci;
 77         else if (c < ATM_NOT_RSV_VCI || c >= 1 << vcc->dev->ci_range.vci_bits)
 78                         c = ATM_NOT_RSV_VCI;
 79         old_p = p;
 80         old_c = c;
 81         do {
 82                 if (!check_ci(vcc,p,c)) {
 83                         *vpi = p;
 84                         *vci = c;
 85                         return 0;
 86                 }
 87                 if (*vci == ATM_VCI_ANY) {
 88                         c++;
 89                         if (c >= 1 << vcc->dev->ci_range.vci_bits)
 90                                 c = ATM_NOT_RSV_VCI;
 91                 }
 92                 if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
 93                     *vpi == ATM_VPI_ANY) {
 94                         p++;
 95                         if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0;
 96                 }
 97         }
 98         while (old_p != p || old_c != c);
 99         return -EADDRINUSE;
100 }
101 
102 
103 /*
104  * atm_pcr_goal returns the positive PCR if it should be rounded up, the
105  * negative PCR if it should be rounded down, and zero if the maximum available
106  * bandwidth should be used.
107  *
108  * The rules are as follows (* = maximum, - = absent (0), x = value "x",
109  * (x+ = x or next value above x, x- = x or next value below):
110  *
111  *      min max pcr     result          min max pcr     result
112  *      -   -   -       * (UBR only)    x   -   -       x+
113  *      -   -   *       *               x   -   *       *
114  *      -   -   z       z-              x   -   z       z-
115  *      -   *   -       *               x   *   -       x+
116  *      -   *   *       *               x   *   *       *
117  *      -   *   z       z-              x   *   z       z-
118  *      -   y   -       y-              x   y   -       x+
119  *      -   y   *       y-              x   y   *       y-
120  *      -   y   z       z-              x   y   z       z-
121  *
122  * All non-error cases can be converted with the following simple set of rules:
123  *
124  *   if pcr == z then z-
125  *   else if min == x && pcr == - then x+
126  *     else if max == y then y-
127  *       else *
128  */
129 
130 
131 int atm_pcr_goal(struct atm_trafprm *tp)
132 {
133         if (tp->pcr && tp->pcr != ATM_MAX_PCR) return -tp->pcr;
134         if (tp->min_pcr && !tp->pcr) return tp->min_pcr;
135         if (tp->max_pcr != ATM_MAX_PCR) return -tp->max_pcr;
136         return 0;
137 }
138 
139 
140 void sonet_copy_stats(struct k_sonet_stats *from,struct sonet_stats *to)
141 {
142 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
143         __SONET_ITEMS
144 #undef __HANDLE_ITEM
145 }
146 
147 
148 void sonet_subtract_stats(struct k_sonet_stats *from,struct sonet_stats *to)
149 {
150 #define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i)
151         __SONET_ITEMS
152 #undef __HANDLE_ITEM
153 }
154 
155 
156 EXPORT_SYMBOL(atm_charge);
157 EXPORT_SYMBOL(atm_alloc_charge);
158 EXPORT_SYMBOL(atm_find_ci);
159 EXPORT_SYMBOL(atm_pcr_goal);
160 EXPORT_SYMBOL(sonet_copy_stats);
161 EXPORT_SYMBOL(sonet_subtract_stats);
162 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.