atm_misc.c 2.57 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10
/* net/atm/atm_misc.c - Various functions for use by ATM drivers */

/* Written 1995-2000 by Werner Almesberger, EPFL ICA */

#include <linux/module.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/skbuff.h>
#include <linux/sonet.h>
#include <linux/bitops.h>
11
#include <linux/errno.h>
Arun Sharma's avatar
Arun Sharma committed
12
#include <linux/atomic.h>
Linus Torvalds's avatar
Linus Torvalds committed
13

14
int atm_charge(struct atm_vcc *vcc, int truesize)
Linus Torvalds's avatar
Linus Torvalds committed
15
{
16
	atm_force_charge(vcc, truesize);
Linus Torvalds's avatar
Linus Torvalds committed
17 18
	if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
		return 1;
19
	atm_return(vcc, truesize);
Linus Torvalds's avatar
Linus Torvalds committed
20 21 22
	atomic_inc(&vcc->stats->rx_drop);
	return 0;
}
23
EXPORT_SYMBOL(atm_charge);
Linus Torvalds's avatar
Linus Torvalds committed
24

25 26
struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc, int pdu_size,
				 gfp_t gfp_flags)
Linus Torvalds's avatar
Linus Torvalds committed
27 28
{
	struct sock *sk = sk_atm(vcc);
29
	int guess = SKB_TRUESIZE(pdu_size);
Linus Torvalds's avatar
Linus Torvalds committed
30

31
	atm_force_charge(vcc, guess);
Linus Torvalds's avatar
Linus Torvalds committed
32
	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
33
		struct sk_buff *skb = alloc_skb(pdu_size, gfp_flags);
Linus Torvalds's avatar
Linus Torvalds committed
34 35 36 37 38 39 40

		if (skb) {
			atomic_add(skb->truesize-guess,
				   &sk->sk_rmem_alloc);
			return skb;
		}
	}
41
	atm_return(vcc, guess);
Linus Torvalds's avatar
Linus Torvalds committed
42 43 44
	atomic_inc(&vcc->stats->rx_drop);
	return NULL;
}
45
EXPORT_SYMBOL(atm_alloc_charge);
Linus Torvalds's avatar
Linus Torvalds committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74


/*
 * atm_pcr_goal returns the positive PCR if it should be rounded up, the
 * negative PCR if it should be rounded down, and zero if the maximum available
 * bandwidth should be used.
 *
 * The rules are as follows (* = maximum, - = absent (0), x = value "x",
 * (x+ = x or next value above x, x- = x or next value below):
 *
 *	min max pcr	result		min max pcr	result
 *	-   -   -	* (UBR only)	x   -   -	x+
 *	-   -   *	*		x   -   *	*
 *	-   -   z	z-		x   -   z	z-
 *	-   *   -	*		x   *   -	x+
 *	-   *   *	*		x   *   *	*
 *	-   *   z	z-		x   *   z	z-
 *	-   y   -	y-		x   y   -	x+
 *	-   y   *	y-		x   y   *	y-
 *	-   y   z	z-		x   y   z	z-
 *
 * All non-error cases can be converted with the following simple set of rules:
 *
 *   if pcr == z then z-
 *   else if min == x && pcr == - then x+
 *     else if max == y then y-
 *	 else *
 */

75
int atm_pcr_goal(const struct atm_trafprm *tp)
Linus Torvalds's avatar
Linus Torvalds committed
76
{
77 78 79 80 81 82
	if (tp->pcr && tp->pcr != ATM_MAX_PCR)
		return -tp->pcr;
	if (tp->min_pcr && !tp->pcr)
		return tp->min_pcr;
	if (tp->max_pcr != ATM_MAX_PCR)
		return -tp->max_pcr;
Linus Torvalds's avatar
Linus Torvalds committed
83 84
	return 0;
}
85
EXPORT_SYMBOL(atm_pcr_goal);
Linus Torvalds's avatar
Linus Torvalds committed
86

87
void sonet_copy_stats(struct k_sonet_stats *from, struct sonet_stats *to)
Linus Torvalds's avatar
Linus Torvalds committed
88 89 90 91 92
{
#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
	__SONET_ITEMS
#undef __HANDLE_ITEM
}
93
EXPORT_SYMBOL(sonet_copy_stats);
Linus Torvalds's avatar
Linus Torvalds committed
94

95
void sonet_subtract_stats(struct k_sonet_stats *from, struct sonet_stats *to)
Linus Torvalds's avatar
Linus Torvalds committed
96
{
97
#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
Linus Torvalds's avatar
Linus Torvalds committed
98 99 100 101
	__SONET_ITEMS
#undef __HANDLE_ITEM
}
EXPORT_SYMBOL(sonet_subtract_stats);