Import 2.3.18pre1
[davej-history.git] / net / atm / atm_misc.c
blob2a3a891b86c082bd078c79bcfd317bf3afb1f067
1 /* net/atm/atm_misc.c - Various functions for use by ATM drivers */
3 /* Written 1995-1999 by Werner Almesberger, EPFL ICA */
6 #include <linux/module.h>
7 #include <linux/atm.h>
8 #include <linux/atmdev.h>
9 #include <linux/skbuff.h>
10 #include <asm/atomic.h>
11 #include <asm/errno.h>
13 #include "tunable.h"
16 int atm_charge(struct atm_vcc *vcc,int truesize)
18 atm_force_charge(vcc,truesize);
19 if (atomic_read(&vcc->rx_inuse) <= vcc->rx_quota) return 1;
20 atm_return(vcc,truesize);
21 vcc->stats->rx_drop++;
22 return 0;
26 struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
27 int gfp_flags)
29 int guess = atm_guess_pdu2truesize(pdu_size);
31 atm_force_charge(vcc,guess);
32 if (atomic_read(&vcc->rx_inuse) <= vcc->rx_quota) {
33 struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
35 if (skb) {
36 atomic_add(skb->truesize-guess,&vcc->rx_inuse);
37 return skb;
40 atm_return(vcc,guess);
41 vcc->stats->rx_drop++;
42 return NULL;
46 static int check_ci(struct atm_vcc *vcc,short vpi,int vci)
48 struct atm_vcc *walk;
50 for (walk = vcc->dev->vccs; walk; walk = walk->next)
51 if ((walk->flags & ATM_VF_ADDR) && 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;
64 int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
66 static short p = 0; /* poor man's per-device cache */
67 static int c = 0;
68 short old_p;
69 int old_c;
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;
87 if (*vci == ATM_VCI_ANY) {
88 c++;
89 if (c >= 1 << vcc->dev->ci_range.vci_bits)
90 c = ATM_NOT_RSV_VCI;
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;
98 while (old_p != p || old_c != c);
99 return -EADDRINUSE;
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.
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):
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-
122 * All non-error cases can be converted with the following simple set of rules:
124 * if pcr == z then z-
125 * else if min == x && pcr == - then x+
126 * else if max == y then y-
127 * else *
131 int atm_pcr_goal(struct atm_trafprm *tp)
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;
140 EXPORT_SYMBOL(atm_charge);
141 EXPORT_SYMBOL(atm_alloc_charge);
142 EXPORT_SYMBOL(atm_find_ci);
143 EXPORT_SYMBOL(atm_pcr_goal);