|
@@ -12,6 +12,7 @@
|
|
|
#include <linux/spinlock.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/crc-ccitt.h>
|
|
|
+#include <linux/netdevice.h>
|
|
|
#include <net/caif/caif_layer.h>
|
|
|
#include <net/caif/cfpkt.h>
|
|
|
#include <net/caif/cffrml.h>
|
|
@@ -21,6 +22,7 @@
|
|
|
struct cffrml {
|
|
|
struct cflayer layer;
|
|
|
bool dofcs; /* !< FCS active */
|
|
|
+ int __percpu *pcpu_refcnt;
|
|
|
};
|
|
|
|
|
|
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,
|
|
|
static u32 cffrml_rcv_error;
|
|
|
static u32 cffrml_rcv_checsum_error;
|
|
|
struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
|
|
|
+
|
|
|
{
|
|
|
struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
|
|
|
if (!this) {
|
|
|
pr_warn("Out of memory\n");
|
|
|
return NULL;
|
|
|
}
|
|
|
+ this->pcpu_refcnt = alloc_percpu(int);
|
|
|
+ if (this->pcpu_refcnt == NULL) {
|
|
|
+ kfree(this);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
caif_assert(offsetof(struct cffrml, layer) == 0);
|
|
|
|
|
|
memset(this, 0, sizeof(struct cflayer));
|
|
@@ -49,6 +58,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
|
|
|
return (struct cflayer *) this;
|
|
|
}
|
|
|
|
|
|
+void cffrml_free(struct cflayer *layer)
|
|
|
+{
|
|
|
+ struct cffrml *this = container_obj(layer);
|
|
|
+ free_percpu(this->pcpu_refcnt);
|
|
|
+ kfree(layer);
|
|
|
+}
|
|
|
+
|
|
|
void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
|
|
|
{
|
|
|
this->up = up;
|
|
@@ -148,8 +164,23 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
|
|
|
|
|
|
void cffrml_put(struct cflayer *layr)
|
|
|
{
|
|
|
+ struct cffrml *this = container_obj(layr);
|
|
|
+ if (layr != NULL && this->pcpu_refcnt != NULL)
|
|
|
+ irqsafe_cpu_dec(*this->pcpu_refcnt);
|
|
|
}
|
|
|
|
|
|
void cffrml_hold(struct cflayer *layr)
|
|
|
{
|
|
|
+ struct cffrml *this = container_obj(layr);
|
|
|
+ if (layr != NULL && this->pcpu_refcnt != NULL)
|
|
|
+ irqsafe_cpu_inc(*this->pcpu_refcnt);
|
|
|
+}
|
|
|
+
|
|
|
+int cffrml_refcnt_read(struct cflayer *layr)
|
|
|
+{
|
|
|
+ int i, refcnt = 0;
|
|
|
+ struct cffrml *this = container_obj(layr);
|
|
|
+ for_each_possible_cpu(i)
|
|
|
+ refcnt += *per_cpu_ptr(this->pcpu_refcnt, i);
|
|
|
+ return refcnt;
|
|
|
}
|