Blame view

net/caif/cffrml.c 4.45 KB
af873fcec   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
b482cd205   Sjur Braendeland   net-caif: add CAI...
2
3
4
5
  /*
   * CAIF Framing Layer.
   *
   * Copyright (C) ST-Ericsson AB 2010
26ee65e68   sjur.brandeland@stericsson.com   caif: Remove my b...
6
   * Author:	Sjur Brendeland
b482cd205   Sjur Braendeland   net-caif: add CAI...
7
   */
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
8
  #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
b482cd205   Sjur Braendeland   net-caif: add CAI...
9
10
11
12
  #include <linux/stddef.h>
  #include <linux/spinlock.h>
  #include <linux/slab.h>
  #include <linux/crc-ccitt.h>
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
13
  #include <linux/netdevice.h>
b482cd205   Sjur Braendeland   net-caif: add CAI...
14
15
16
17
18
19
20
21
22
  #include <net/caif/caif_layer.h>
  #include <net/caif/cfpkt.h>
  #include <net/caif/cffrml.h>
  
  #define container_obj(layr) container_of(layr, struct cffrml, layer)
  
  struct cffrml {
  	struct cflayer layer;
  	bool dofcs;		/* !< FCS active */
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
23
  	int __percpu		*pcpu_refcnt;
b482cd205   Sjur Braendeland   net-caif: add CAI...
24
25
26
27
28
  };
  
  static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
  static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
  static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
29
  			   int phyid);
b482cd205   Sjur Braendeland   net-caif: add CAI...
30
31
32
33
34
  
  static u32 cffrml_rcv_error;
  static u32 cffrml_rcv_checsum_error;
  struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
  {
7ac2ed0ce   Joe Perches   caif: Remove OOM ...
35
36
  	struct cffrml *this = kzalloc(sizeof(struct cffrml), GFP_ATOMIC);
  	if (!this)
b482cd205   Sjur Braendeland   net-caif: add CAI...
37
  		return NULL;
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
38
39
40
41
42
  	this->pcpu_refcnt = alloc_percpu(int);
  	if (this->pcpu_refcnt == NULL) {
  		kfree(this);
  		return NULL;
  	}
b482cd205   Sjur Braendeland   net-caif: add CAI...
43
  	caif_assert(offsetof(struct cffrml, layer) == 0);
b482cd205   Sjur Braendeland   net-caif: add CAI...
44
45
46
47
48
49
50
51
  	this->layer.receive = cffrml_receive;
  	this->layer.transmit = cffrml_transmit;
  	this->layer.ctrlcmd = cffrml_ctrlcmd;
  	snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid);
  	this->dofcs = use_fcs;
  	this->layer.id = phyid;
  	return (struct cflayer *) this;
  }
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
52
53
54
55
56
57
  void cffrml_free(struct cflayer *layer)
  {
  	struct cffrml *this = container_obj(layer);
  	free_percpu(this->pcpu_refcnt);
  	kfree(layer);
  }
b482cd205   Sjur Braendeland   net-caif: add CAI...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
  {
  	this->up = up;
  }
  
  void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn)
  {
  	this->dn = dn;
  }
  
  static u16 cffrml_checksum(u16 chks, void *buf, u16 len)
  {
  	/* FIXME: FCS should be moved to glue in order to use OS-Specific
  	 * solutions
  	 */
  	return crc_ccitt(chks, buf, len);
  }
  
  static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
  {
  	u16 tmp;
  	u16 len;
  	u16 hdrchks;
278f7b4ff   Dan Carpenter   caif: fix a signe...
81
  	int pktchks;
b482cd205   Sjur Braendeland   net-caif: add CAI...
82
83
84
85
86
87
88
89
90
91
92
93
  	struct cffrml *this;
  	this = container_obj(layr);
  
  	cfpkt_extr_head(pkt, &tmp, 2);
  	len = le16_to_cpu(tmp);
  
  	/* Subtract for FCS on length if FCS is not used. */
  	if (!this->dofcs)
  		len -= 2;
  
  	if (cfpkt_setlen(pkt, len) < 0) {
  		++cffrml_rcv_error;
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
94
95
  		pr_err("Framing length error (%d)
  ", len);
b482cd205   Sjur Braendeland   net-caif: add CAI...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  		cfpkt_destroy(pkt);
  		return -EPROTO;
  	}
  	/*
  	 * Don't do extract if FCS is false, rather do setlen - then we don't
  	 * get a cache-miss.
  	 */
  	if (this->dofcs) {
  		cfpkt_extr_trail(pkt, &tmp, 2);
  		hdrchks = le16_to_cpu(tmp);
  		pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
  		if (pktchks != hdrchks) {
  			cfpkt_add_trail(pkt, &tmp, 2);
  			++cffrml_rcv_error;
  			++cffrml_rcv_checsum_error;
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
111
112
113
  			pr_info("Frame checksum error (0x%x != 0x%x)
  ",
  				hdrchks, pktchks);
b482cd205   Sjur Braendeland   net-caif: add CAI...
114
115
116
117
118
  			return -EILSEQ;
  		}
  	}
  	if (cfpkt_erroneous(pkt)) {
  		++cffrml_rcv_error;
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
119
120
  		pr_err("Packet is erroneous!
  ");
b482cd205   Sjur Braendeland   net-caif: add CAI...
121
122
123
  		cfpkt_destroy(pkt);
  		return -EPROTO;
  	}
c85c2951d   sjur.brandeland@stericsson.com   caif: Handle dev_...
124
125
126
127
128
129
130
  
  	if (layr->up == NULL) {
  		pr_err("Layr up is missing!
  ");
  		cfpkt_destroy(pkt);
  		return -EINVAL;
  	}
b482cd205   Sjur Braendeland   net-caif: add CAI...
131
132
133
134
135
  	return layr->up->receive(layr->up, pkt);
  }
  
  static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
  {
b482cd205   Sjur Braendeland   net-caif: add CAI...
136
137
  	u16 chks;
  	u16 len;
f23aa6254   Dan Carpenter   caif: fix endian ...
138
  	__le16 data;
b482cd205   Sjur Braendeland   net-caif: add CAI...
139
140
141
  	struct cffrml *this = container_obj(layr);
  	if (this->dofcs) {
  		chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
f23aa6254   Dan Carpenter   caif: fix endian ...
142
143
  		data = cpu_to_le16(chks);
  		cfpkt_add_trail(pkt, &data, 2);
b482cd205   Sjur Braendeland   net-caif: add CAI...
144
145
146
147
  	} else {
  		cfpkt_pad_trail(pkt, 2);
  	}
  	len = cfpkt_getlen(pkt);
f23aa6254   Dan Carpenter   caif: fix endian ...
148
149
  	data = cpu_to_le16(len);
  	cfpkt_add_head(pkt, &data, 2);
b482cd205   Sjur Braendeland   net-caif: add CAI...
150
151
  	cfpkt_info(pkt)->hdr_len += 2;
  	if (cfpkt_erroneous(pkt)) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
152
153
  		pr_err("Packet is erroneous!
  ");
c85c2951d   sjur.brandeland@stericsson.com   caif: Handle dev_...
154
  		cfpkt_destroy(pkt);
b482cd205   Sjur Braendeland   net-caif: add CAI...
155
156
  		return -EPROTO;
  	}
c85c2951d   sjur.brandeland@stericsson.com   caif: Handle dev_...
157
158
159
160
161
162
  
  	if (layr->dn == NULL) {
  		cfpkt_destroy(pkt);
  		return -ENODEV;
  
  	}
4dd820c08   Sjur Brændeland   caif: Don't resen...
163
  	return layr->dn->transmit(layr->dn, pkt);
b482cd205   Sjur Braendeland   net-caif: add CAI...
164
165
166
  }
  
  static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
167
  			   int phyid)
b482cd205   Sjur Braendeland   net-caif: add CAI...
168
  {
c85c2951d   sjur.brandeland@stericsson.com   caif: Handle dev_...
169
  	if (layr->up && layr->up->ctrlcmd)
b482cd205   Sjur Braendeland   net-caif: add CAI...
170
171
  		layr->up->ctrlcmd(layr->up, ctrl, layr->id);
  }
0b1e9738d   sjur.brandeland@stericsson.com   caif: Use rcu_rea...
172
173
174
  
  void cffrml_put(struct cflayer *layr)
  {
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
175
176
  	struct cffrml *this = container_obj(layr);
  	if (layr != NULL && this->pcpu_refcnt != NULL)
933393f58   Christoph Lameter   percpu: Remove ir...
177
  		this_cpu_dec(*this->pcpu_refcnt);
0b1e9738d   sjur.brandeland@stericsson.com   caif: Use rcu_rea...
178
179
180
181
  }
  
  void cffrml_hold(struct cflayer *layr)
  {
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
182
183
  	struct cffrml *this = container_obj(layr);
  	if (layr != NULL && this->pcpu_refcnt != NULL)
933393f58   Christoph Lameter   percpu: Remove ir...
184
  		this_cpu_inc(*this->pcpu_refcnt);
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
185
186
187
188
189
190
191
192
193
  }
  
  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;
0b1e9738d   sjur.brandeland@stericsson.com   caif: Use rcu_rea...
194
  }