Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-drm-fsl-dcu.git] / net / sctp / ssnmap.c
1 /* SCTP kernel implementation
2  * Copyright (c) 2003 International Business Machines, Corp.
3  *
4  * This file is part of the SCTP kernel implementation
5  *
6  * These functions manipulate sctp SSN tracker.
7  *
8  * This SCTP implementation is free software;
9  * you can redistribute it and/or modify it under the terms of
10  * the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * This SCTP implementation is distributed in the hope that it
15  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16  *                 ************************
17  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  * See the GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with GNU CC; see the file COPYING.  If not, see
22  * <http://www.gnu.org/licenses/>.
23  *
24  * Please send any bug reports or fixes you make to the
25  * email address(es):
26  *    lksctp developers <linux-sctp@vger.kernel.org>
27  *
28  * Written or modified by:
29  *    Jon Grimm             <jgrimm@us.ibm.com>
30  */
31
32 #include <linux/types.h>
33 #include <linux/slab.h>
34 #include <net/sctp/sctp.h>
35 #include <net/sctp/sm.h>
36
37 static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
38                                             __u16 out);
39
40 /* Storage size needed for map includes 2 headers and then the
41  * specific needs of in or out streams.
42  */
43 static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)
44 {
45         return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16);
46 }
47
48
49 /* Create a new sctp_ssnmap.
50  * Allocate room to store at least 'len' contiguous TSNs.
51  */
52 struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
53                                     gfp_t gfp)
54 {
55         struct sctp_ssnmap *retval;
56         int size;
57
58         size = sctp_ssnmap_size(in, out);
59         if (size <= KMALLOC_MAX_SIZE)
60                 retval = kmalloc(size, gfp);
61         else
62                 retval = (struct sctp_ssnmap *)
63                           __get_free_pages(gfp, get_order(size));
64         if (!retval)
65                 goto fail;
66
67         if (!sctp_ssnmap_init(retval, in, out))
68                 goto fail_map;
69
70         SCTP_DBG_OBJCNT_INC(ssnmap);
71
72         return retval;
73
74 fail_map:
75         if (size <= KMALLOC_MAX_SIZE)
76                 kfree(retval);
77         else
78                 free_pages((unsigned long)retval, get_order(size));
79 fail:
80         return NULL;
81 }
82
83
84 /* Initialize a block of memory as a ssnmap.  */
85 static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
86                                             __u16 out)
87 {
88         memset(map, 0x00, sctp_ssnmap_size(in, out));
89
90         /* Start 'in' stream just after the map header. */
91         map->in.ssn = (__u16 *)&map[1];
92         map->in.len = in;
93
94         /* Start 'out' stream just after 'in'. */
95         map->out.ssn = &map->in.ssn[in];
96         map->out.len = out;
97
98         return map;
99 }
100
101 /* Clear out the ssnmap streams.  */
102 void sctp_ssnmap_clear(struct sctp_ssnmap *map)
103 {
104         size_t size;
105
106         size = (map->in.len + map->out.len) * sizeof(__u16);
107         memset(map->in.ssn, 0x00, size);
108 }
109
110 /* Dispose of a ssnmap.  */
111 void sctp_ssnmap_free(struct sctp_ssnmap *map)
112 {
113         int size;
114
115         if (unlikely(!map))
116                 return;
117
118         size = sctp_ssnmap_size(map->in.len, map->out.len);
119         if (size <= KMALLOC_MAX_SIZE)
120                 kfree(map);
121         else
122                 free_pages((unsigned long)map, get_order(size));
123
124         SCTP_DBG_OBJCNT_DEC(ssnmap);
125 }