aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif
diff options
context:
space:
mode:
authorsjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com>2011-05-12 22:44:02 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-15 17:45:55 -0400
commitcb3cb423a0f3c627639535e5d87977ae662d779f (patch)
tree37fae151f44b5549bf1d4fd437dd070315d78cad /net/caif
parentf36214408470ecf6a052e76b72d05b2328b60fcf (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')
-rw-r--r--net/caif/cfcnfg.c9
-rw-r--r--net/caif/cffrml.c31
2 files changed, 39 insertions, 1 deletions
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index 7892cc084e27..3f4f31fca2c1 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -519,6 +519,13 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
519 caif_assert(phy_layer->id == phyid); 519 caif_assert(phy_layer->id == phyid);
520 caif_assert(phyinfo->frm_layer->id == phyid); 520 caif_assert(phyinfo->frm_layer->id == phyid);
521 521
522 /* Fail if reference count is not zero */
523 if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
524 pr_info("Wait for device inuse\n");
525 mutex_unlock(&cnfg->lock);
526 return -EAGAIN;
527 }
528
522 list_del_rcu(&phyinfo->node); 529 list_del_rcu(&phyinfo->node);
523 synchronize_rcu(); 530 synchronize_rcu();
524 531
@@ -537,7 +544,7 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
537 if (phyinfo->phy_layer != frml_dn) 544 if (phyinfo->phy_layer != frml_dn)
538 kfree(frml_dn); 545 kfree(frml_dn);
539 546
540 kfree(frml); 547 cffrml_free(frml);
541 kfree(phyinfo); 548 kfree(phyinfo);
542 mutex_unlock(&cnfg->lock); 549 mutex_unlock(&cnfg->lock);
543 550
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 @@
21struct cffrml { 22struct 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
26static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); 28static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
@@ -31,12 +33,19 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
31static u32 cffrml_rcv_error; 33static u32 cffrml_rcv_error;
32static u32 cffrml_rcv_checsum_error; 34static u32 cffrml_rcv_checsum_error;
33struct cflayer *cffrml_create(u16 phyid, bool use_fcs) 35struct 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
61void cffrml_free(struct cflayer *layer)
62{
63 struct cffrml *this = container_obj(layer);
64 free_percpu(this->pcpu_refcnt);
65 kfree(layer);
66}
67
52void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) 68void 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
149void cffrml_put(struct cflayer *layr) 165void 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
153void cffrml_hold(struct cflayer *layr) 172void 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
179int 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}