diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-12 22:44:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-15 17:45:55 -0400 |
commit | cb3cb423a0f3c627639535e5d87977ae662d779f (patch) | |
tree | 37fae151f44b5549bf1d4fd437dd070315d78cad /net/caif/cffrml.c | |
parent | f36214408470ecf6a052e76b72d05b2328b60fcf (diff) |
caif: Add ref-count to framing layer
Introduce Per-cpu reference for lower part of CAIF Stack.
Before freeing payload is disabled, synchronize_rcu() is called,
and then ref-count verified to be zero.
Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/caif/cffrml.c')
-rw-r--r-- | net/caif/cffrml.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index f4b88924f83a..4f4f756c49ac 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/crc-ccitt.h> | 14 | #include <linux/crc-ccitt.h> |
15 | #include <linux/netdevice.h> | ||
15 | #include <net/caif/caif_layer.h> | 16 | #include <net/caif/caif_layer.h> |
16 | #include <net/caif/cfpkt.h> | 17 | #include <net/caif/cfpkt.h> |
17 | #include <net/caif/cffrml.h> | 18 | #include <net/caif/cffrml.h> |
@@ -21,6 +22,7 @@ | |||
21 | struct cffrml { | 22 | struct cffrml { |
22 | struct cflayer layer; | 23 | struct cflayer layer; |
23 | bool dofcs; /* !< FCS active */ | 24 | bool dofcs; /* !< FCS active */ |
25 | int __percpu *pcpu_refcnt; | ||
24 | }; | 26 | }; |
25 | 27 | ||
26 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); | 28 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); |
@@ -31,12 +33,19 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
31 | static u32 cffrml_rcv_error; | 33 | static u32 cffrml_rcv_error; |
32 | static u32 cffrml_rcv_checsum_error; | 34 | static u32 cffrml_rcv_checsum_error; |
33 | struct cflayer *cffrml_create(u16 phyid, bool use_fcs) | 35 | struct cflayer *cffrml_create(u16 phyid, bool use_fcs) |
36 | |||
34 | { | 37 | { |
35 | struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); | 38 | struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); |
36 | if (!this) { | 39 | if (!this) { |
37 | pr_warn("Out of memory\n"); | 40 | pr_warn("Out of memory\n"); |
38 | return NULL; | 41 | return NULL; |
39 | } | 42 | } |
43 | this->pcpu_refcnt = alloc_percpu(int); | ||
44 | if (this->pcpu_refcnt == NULL) { | ||
45 | kfree(this); | ||
46 | return NULL; | ||
47 | } | ||
48 | |||
40 | caif_assert(offsetof(struct cffrml, layer) == 0); | 49 | caif_assert(offsetof(struct cffrml, layer) == 0); |
41 | 50 | ||
42 | memset(this, 0, sizeof(struct cflayer)); | 51 | memset(this, 0, sizeof(struct cflayer)); |
@@ -49,6 +58,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs) | |||
49 | return (struct cflayer *) this; | 58 | return (struct cflayer *) this; |
50 | } | 59 | } |
51 | 60 | ||
61 | void cffrml_free(struct cflayer *layer) | ||
62 | { | ||
63 | struct cffrml *this = container_obj(layer); | ||
64 | free_percpu(this->pcpu_refcnt); | ||
65 | kfree(layer); | ||
66 | } | ||
67 | |||
52 | void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) | 68 | void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) |
53 | { | 69 | { |
54 | this->up = up; | 70 | this->up = up; |
@@ -148,8 +164,23 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
148 | 164 | ||
149 | void cffrml_put(struct cflayer *layr) | 165 | void cffrml_put(struct cflayer *layr) |
150 | { | 166 | { |
167 | struct cffrml *this = container_obj(layr); | ||
168 | if (layr != NULL && this->pcpu_refcnt != NULL) | ||
169 | irqsafe_cpu_dec(*this->pcpu_refcnt); | ||
151 | } | 170 | } |
152 | 171 | ||
153 | void cffrml_hold(struct cflayer *layr) | 172 | void cffrml_hold(struct cflayer *layr) |
154 | { | 173 | { |
174 | struct cffrml *this = container_obj(layr); | ||
175 | if (layr != NULL && this->pcpu_refcnt != NULL) | ||
176 | irqsafe_cpu_inc(*this->pcpu_refcnt); | ||
177 | } | ||
178 | |||
179 | int cffrml_refcnt_read(struct cflayer *layr) | ||
180 | { | ||
181 | int i, refcnt = 0; | ||
182 | struct cffrml *this = container_obj(layr); | ||
183 | for_each_possible_cpu(i) | ||
184 | refcnt += *per_cpu_ptr(this->pcpu_refcnt, i); | ||
185 | return refcnt; | ||
155 | } | 186 | } |