^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* net/atm/atm_misc.c - Various functions for use by ATM drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /* Written 1995-2000 by Werner Almesberger, EPFL ICA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/atm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/atmdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sonet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) int atm_charge(struct atm_vcc *vcc, int truesize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) atm_force_charge(vcc, truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) atm_return(vcc, truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) atomic_inc(&vcc->stats->rx_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) EXPORT_SYMBOL(atm_charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc, int pdu_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) gfp_t gfp_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct sock *sk = sk_atm(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int guess = SKB_TRUESIZE(pdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) atm_force_charge(vcc, guess);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct sk_buff *skb = alloc_skb(pdu_size, gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) atomic_add(skb->truesize-guess,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) &sk->sk_rmem_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) atm_return(vcc, guess);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) atomic_inc(&vcc->stats->rx_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) EXPORT_SYMBOL(atm_alloc_charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * atm_pcr_goal returns the positive PCR if it should be rounded up, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * negative PCR if it should be rounded down, and zero if the maximum available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * bandwidth should be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * The rules are as follows (* = maximum, - = absent (0), x = value "x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * (x+ = x or next value above x, x- = x or next value below):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * min max pcr result min max pcr result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * - - - * (UBR only) x - - x+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * - - * * x - * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * - - z z- x - z z-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * - * - * x * - x+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * - * * * x * * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * - * z z- x * z z-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * - y - y- x y - x+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * - y * y- x y * y-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * - y z z- x y z z-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * All non-error cases can be converted with the following simple set of rules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * if pcr == z then z-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * else if min == x && pcr == - then x+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * else if max == y then y-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * else *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int atm_pcr_goal(const struct atm_trafprm *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (tp->pcr && tp->pcr != ATM_MAX_PCR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -tp->pcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (tp->min_pcr && !tp->pcr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return tp->min_pcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (tp->max_pcr != ATM_MAX_PCR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -tp->max_pcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) EXPORT_SYMBOL(atm_pcr_goal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) void sonet_copy_stats(struct k_sonet_stats *from, struct sonet_stats *to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) __SONET_ITEMS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #undef __HANDLE_ITEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) EXPORT_SYMBOL(sonet_copy_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void sonet_subtract_stats(struct k_sonet_stats *from, struct sonet_stats *to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) __SONET_ITEMS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #undef __HANDLE_ITEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) EXPORT_SYMBOL(sonet_subtract_stats);