Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* net/atm/atm_misc.c - Various functions for use by ATM drivers */
0003 
0004 /* Written 1995-2000 by Werner Almesberger, EPFL ICA */
0005 
0006 #include <linux/module.h>
0007 #include <linux/atm.h>
0008 #include <linux/atmdev.h>
0009 #include <linux/skbuff.h>
0010 #include <linux/sonet.h>
0011 #include <linux/bitops.h>
0012 #include <linux/errno.h>
0013 #include <linux/atomic.h>
0014 
0015 int atm_charge(struct atm_vcc *vcc, int truesize)
0016 {
0017     atm_force_charge(vcc, truesize);
0018     if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
0019         return 1;
0020     atm_return(vcc, truesize);
0021     atomic_inc(&vcc->stats->rx_drop);
0022     return 0;
0023 }
0024 EXPORT_SYMBOL(atm_charge);
0025 
0026 struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc, int pdu_size,
0027                  gfp_t gfp_flags)
0028 {
0029     struct sock *sk = sk_atm(vcc);
0030     int guess = SKB_TRUESIZE(pdu_size);
0031 
0032     atm_force_charge(vcc, guess);
0033     if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
0034         struct sk_buff *skb = alloc_skb(pdu_size, gfp_flags);
0035 
0036         if (skb) {
0037             atomic_add(skb->truesize-guess,
0038                    &sk->sk_rmem_alloc);
0039             return skb;
0040         }
0041     }
0042     atm_return(vcc, guess);
0043     atomic_inc(&vcc->stats->rx_drop);
0044     return NULL;
0045 }
0046 EXPORT_SYMBOL(atm_alloc_charge);
0047 
0048 
0049 /*
0050  * atm_pcr_goal returns the positive PCR if it should be rounded up, the
0051  * negative PCR if it should be rounded down, and zero if the maximum available
0052  * bandwidth should be used.
0053  *
0054  * The rules are as follows (* = maximum, - = absent (0), x = value "x",
0055  * (x+ = x or next value above x, x- = x or next value below):
0056  *
0057  *  min max pcr result      min max pcr result
0058  *  -   -   -   * (UBR only)    x   -   -   x+
0059  *  -   -   *   *       x   -   *   *
0060  *  -   -   z   z-      x   -   z   z-
0061  *  -   *   -   *       x   *   -   x+
0062  *  -   *   *   *       x   *   *   *
0063  *  -   *   z   z-      x   *   z   z-
0064  *  -   y   -   y-      x   y   -   x+
0065  *  -   y   *   y-      x   y   *   y-
0066  *  -   y   z   z-      x   y   z   z-
0067  *
0068  * All non-error cases can be converted with the following simple set of rules:
0069  *
0070  *   if pcr == z then z-
0071  *   else if min == x && pcr == - then x+
0072  *     else if max == y then y-
0073  *   else *
0074  */
0075 
0076 int atm_pcr_goal(const struct atm_trafprm *tp)
0077 {
0078     if (tp->pcr && tp->pcr != ATM_MAX_PCR)
0079         return -tp->pcr;
0080     if (tp->min_pcr && !tp->pcr)
0081         return tp->min_pcr;
0082     if (tp->max_pcr != ATM_MAX_PCR)
0083         return -tp->max_pcr;
0084     return 0;
0085 }
0086 EXPORT_SYMBOL(atm_pcr_goal);
0087 
0088 void sonet_copy_stats(struct k_sonet_stats *from, struct sonet_stats *to)
0089 {
0090 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
0091     __SONET_ITEMS
0092 #undef __HANDLE_ITEM
0093 }
0094 EXPORT_SYMBOL(sonet_copy_stats);
0095 
0096 void sonet_subtract_stats(struct k_sonet_stats *from, struct sonet_stats *to)
0097 {
0098 #define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
0099     __SONET_ITEMS
0100 #undef __HANDLE_ITEM
0101 }
0102 EXPORT_SYMBOL(sonet_subtract_stats);