aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif
diff options
context:
space:
mode:
Diffstat (limited to 'net/caif')
-rw-r--r--net/caif/Kconfig48
-rw-r--r--net/caif/Makefile26
-rw-r--r--net/caif/caif_config_util.c87
-rw-r--r--net/caif/caif_dev.c413
-rw-r--r--net/caif/caif_socket.c1391
-rw-r--r--net/caif/cfcnfg.c530
-rw-r--r--net/caif/cfctrl.c664
-rw-r--r--net/caif/cfdbgl.c40
-rw-r--r--net/caif/cfdgml.c108
-rw-r--r--net/caif/cffrml.c151
-rw-r--r--net/caif/cfmuxl.c246
-rw-r--r--net/caif/cfpkt_skbuff.c571
-rw-r--r--net/caif/cfrfml.c108
-rw-r--r--net/caif/cfserl.c192
-rw-r--r--net/caif/cfsrvl.c185
-rw-r--r--net/caif/cfutill.c115
-rw-r--r--net/caif/cfveil.c107
-rw-r--r--net/caif/cfvidl.c65
-rw-r--r--net/caif/chnl_net.c451
19 files changed, 5498 insertions, 0 deletions
diff --git a/net/caif/Kconfig b/net/caif/Kconfig
new file mode 100644
index 000000000000..cd1daf6008bd
--- /dev/null
+++ b/net/caif/Kconfig
@@ -0,0 +1,48 @@
1#
2# CAIF net configurations
3#
4
5#menu "CAIF Support"
6comment "CAIF Support"
7menuconfig CAIF
8 tristate "Enable CAIF support"
9 select CRC_CCITT
10 default n
11 ---help---
12 The "Communication CPU to Application CPU Interface" (CAIF) is a packet
13 based connection-oriented MUX protocol developed by ST-Ericsson for use
14 with its modems. It is accessed from user space as sockets (PF_CAIF).
15
16 Say Y (or M) here if you build for a phone product (e.g. Android or
17 MeeGo ) that uses CAIF as transport, if unsure say N.
18
19 If you select to build it as module then CAIF_NETDEV also needs to be
20 built as modules. You will also need to say yes to any CAIF physical
21 devices that your platform requires.
22
23 See Documentation/networking/caif for a further explanation on how to
24 use and configure CAIF.
25
26if CAIF
27
28config CAIF_DEBUG
29 bool "Enable Debug"
30 default n
31 --- help ---
32 Enable the inclusion of debug code in the CAIF stack.
33 Be aware that doing this will impact performance.
34 If unsure say N.
35
36
37config CAIF_NETDEV
38 tristate "CAIF GPRS Network device"
39 default CAIF
40 ---help---
41 Say Y if you will be using a CAIF based GPRS network device.
42 This can be either built-in or a loadable module,
43 If you select to build it as a built-in then the main CAIF device must
44 also be a built-in.
45 If unsure say Y.
46
47endif
48#endmenu
diff --git a/net/caif/Makefile b/net/caif/Makefile
new file mode 100644
index 000000000000..34852af2595e
--- /dev/null
+++ b/net/caif/Makefile
@@ -0,0 +1,26 @@
1ifeq ($(CONFIG_CAIF_DEBUG),1)
2CAIF_DBG_FLAGS := -DDEBUG
3endif
4
5ccflags-y := $(CAIF_FLAGS) $(CAIF_DBG_FLAGS)
6
7caif-objs := caif_dev.o \
8 cfcnfg.o cfmuxl.o cfctrl.o \
9 cffrml.o cfveil.o cfdbgl.o\
10 cfserl.o cfdgml.o \
11 cfrfml.o cfvidl.o cfutill.o \
12 cfsrvl.o cfpkt_skbuff.o caif_config_util.o
13clean-dirs:= .tmp_versions
14
15clean-files:= \
16 Module.symvers \
17 modules.order \
18 *.cmd \
19 *.o \
20 *~
21
22obj-$(CONFIG_CAIF) += caif.o
23obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o
24obj-$(CONFIG_CAIF) += caif_socket.o
25
26export-objs := caif.o
diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c
new file mode 100644
index 000000000000..6f36580366f0
--- /dev/null
+++ b/net/caif/caif_config_util.c
@@ -0,0 +1,87 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/module.h>
8#include <linux/spinlock.h>
9#include <net/caif/cfctrl.h>
10#include <net/caif/cfcnfg.h>
11#include <net/caif/caif_dev.h>
12
13int connect_req_to_link_param(struct cfcnfg *cnfg,
14 struct caif_connect_request *s,
15 struct cfctrl_link_param *l)
16{
17 struct dev_info *dev_info;
18 enum cfcnfg_phy_preference pref;
19 memset(l, 0, sizeof(*l));
20 l->priority = s->priority;
21
22 if (s->link_name[0] != '\0')
23 l->phyid = cfcnfg_get_named(cnfg, s->link_name);
24 else {
25 switch (s->link_selector) {
26 case CAIF_LINK_HIGH_BANDW:
27 pref = CFPHYPREF_HIGH_BW;
28 break;
29 case CAIF_LINK_LOW_LATENCY:
30 pref = CFPHYPREF_LOW_LAT;
31 break;
32 default:
33 return -EINVAL;
34 }
35 dev_info = cfcnfg_get_phyid(cnfg, pref);
36 if (dev_info == NULL)
37 return -ENODEV;
38 l->phyid = dev_info->id;
39 }
40 switch (s->protocol) {
41 case CAIFPROTO_AT:
42 l->linktype = CFCTRL_SRV_VEI;
43 if (s->sockaddr.u.at.type == CAIF_ATTYPE_PLAIN)
44 l->chtype = 0x02;
45 else
46 l->chtype = s->sockaddr.u.at.type;
47 l->endpoint = 0x00;
48 break;
49 case CAIFPROTO_DATAGRAM:
50 l->linktype = CFCTRL_SRV_DATAGRAM;
51 l->chtype = 0x00;
52 l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
53 break;
54 case CAIFPROTO_DATAGRAM_LOOP:
55 l->linktype = CFCTRL_SRV_DATAGRAM;
56 l->chtype = 0x03;
57 l->endpoint = 0x00;
58 l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
59 break;
60 case CAIFPROTO_RFM:
61 l->linktype = CFCTRL_SRV_RFM;
62 l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
63 strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
64 sizeof(l->u.rfm.volume)-1);
65 l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0;
66 break;
67 case CAIFPROTO_UTIL:
68 l->linktype = CFCTRL_SRV_UTIL;
69 l->endpoint = 0x00;
70 l->chtype = 0x00;
71 strncpy(l->u.utility.name, s->sockaddr.u.util.service,
72 sizeof(l->u.utility.name)-1);
73 l->u.utility.name[sizeof(l->u.utility.name)-1] = 0;
74 caif_assert(sizeof(l->u.utility.name) > 10);
75 l->u.utility.paramlen = s->param.size;
76 if (l->u.utility.paramlen > sizeof(l->u.utility.params))
77 l->u.utility.paramlen = sizeof(l->u.utility.params);
78
79 memcpy(l->u.utility.params, s->param.data,
80 l->u.utility.paramlen);
81
82 break;
83 default:
84 return -EINVAL;
85 }
86 return 0;
87}
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
new file mode 100644
index 000000000000..e84837e1bc86
--- /dev/null
+++ b/net/caif/caif_dev.c
@@ -0,0 +1,413 @@
1/*
2 * CAIF Interface registration.
3 * Copyright (C) ST-Ericsson AB 2010
4 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
5 * License terms: GNU General Public License (GPL) version 2
6 *
7 * Borrowed heavily from file: pn_dev.c. Thanks to
8 * Remi Denis-Courmont <remi.denis-courmont@nokia.com>
9 * and Sakari Ailus <sakari.ailus@nokia.com>
10 */
11
12#include <linux/version.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/if_arp.h>
16#include <linux/net.h>
17#include <linux/netdevice.h>
18#include <linux/skbuff.h>
19#include <linux/sched.h>
20#include <linux/wait.h>
21#include <net/netns/generic.h>
22#include <net/net_namespace.h>
23#include <net/pkt_sched.h>
24#include <net/caif/caif_device.h>
25#include <net/caif/caif_dev.h>
26#include <net/caif/caif_layer.h>
27#include <net/caif/cfpkt.h>
28#include <net/caif/cfcnfg.h>
29
30MODULE_LICENSE("GPL");
31#define TIMEOUT (HZ*5)
32
33/* Used for local tracking of the CAIF net devices */
34struct caif_device_entry {
35 struct cflayer layer;
36 struct list_head list;
37 atomic_t in_use;
38 atomic_t state;
39 u16 phyid;
40 struct net_device *netdev;
41 wait_queue_head_t event;
42};
43
44struct caif_device_entry_list {
45 struct list_head list;
46 /* Protects simulanous deletes in list */
47 spinlock_t lock;
48};
49
50struct caif_net {
51 struct caif_device_entry_list caifdevs;
52};
53
54static int caif_net_id;
55static struct cfcnfg *cfg;
56
57static struct caif_device_entry_list *caif_device_list(struct net *net)
58{
59 struct caif_net *caifn;
60 BUG_ON(!net);
61 caifn = net_generic(net, caif_net_id);
62 BUG_ON(!caifn);
63 return &caifn->caifdevs;
64}
65
66/* Allocate new CAIF device. */
67static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
68{
69 struct caif_device_entry_list *caifdevs;
70 struct caif_device_entry *caifd;
71 caifdevs = caif_device_list(dev_net(dev));
72 BUG_ON(!caifdevs);
73 caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC);
74 if (!caifd)
75 return NULL;
76 caifd->netdev = dev;
77 list_add(&caifd->list, &caifdevs->list);
78 init_waitqueue_head(&caifd->event);
79 return caifd;
80}
81
82static struct caif_device_entry *caif_get(struct net_device *dev)
83{
84 struct caif_device_entry_list *caifdevs =
85 caif_device_list(dev_net(dev));
86 struct caif_device_entry *caifd;
87 BUG_ON(!caifdevs);
88 list_for_each_entry(caifd, &caifdevs->list, list) {
89 if (caifd->netdev == dev)
90 return caifd;
91 }
92 return NULL;
93}
94
95static void caif_device_destroy(struct net_device *dev)
96{
97 struct caif_device_entry_list *caifdevs =
98 caif_device_list(dev_net(dev));
99 struct caif_device_entry *caifd;
100 ASSERT_RTNL();
101 if (dev->type != ARPHRD_CAIF)
102 return;
103
104 spin_lock_bh(&caifdevs->lock);
105 caifd = caif_get(dev);
106 if (caifd == NULL) {
107 spin_unlock_bh(&caifdevs->lock);
108 return;
109 }
110
111 list_del(&caifd->list);
112 spin_unlock_bh(&caifdevs->lock);
113
114 kfree(caifd);
115 return;
116}
117
118static int transmit(struct cflayer *layer, struct cfpkt *pkt)
119{
120 struct caif_device_entry *caifd =
121 container_of(layer, struct caif_device_entry, layer);
122 struct sk_buff *skb, *skb2;
123 int ret = -EINVAL;
124 skb = cfpkt_tonative(pkt);
125 skb->dev = caifd->netdev;
126 /*
127 * Don't allow SKB to be destroyed upon error, but signal resend
128 * notification to clients. We can't rely on the return value as
129 * congestion (NET_XMIT_CN) sometimes drops the packet, sometimes don't.
130 */
131 if (netif_queue_stopped(caifd->netdev))
132 return -EAGAIN;
133 skb2 = skb_get(skb);
134
135 ret = dev_queue_xmit(skb2);
136
137 if (!ret)
138 kfree_skb(skb);
139 else
140 return -EAGAIN;
141
142 return 0;
143}
144
145static int modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
146{
147 struct caif_device_entry *caifd;
148 struct caif_dev_common *caifdev;
149 caifd = container_of(layr, struct caif_device_entry, layer);
150 caifdev = netdev_priv(caifd->netdev);
151 if (ctrl == _CAIF_MODEMCMD_PHYIF_USEFULL) {
152 atomic_set(&caifd->in_use, 1);
153 wake_up_interruptible(&caifd->event);
154
155 } else if (ctrl == _CAIF_MODEMCMD_PHYIF_USELESS) {
156 atomic_set(&caifd->in_use, 0);
157 wake_up_interruptible(&caifd->event);
158 }
159 return 0;
160}
161
162/*
163 * Stuff received packets to associated sockets.
164 * On error, returns non-zero and releases the skb.
165 */
166static int receive(struct sk_buff *skb, struct net_device *dev,
167 struct packet_type *pkttype, struct net_device *orig_dev)
168{
169 struct net *net;
170 struct cfpkt *pkt;
171 struct caif_device_entry *caifd;
172 net = dev_net(dev);
173 pkt = cfpkt_fromnative(CAIF_DIR_IN, skb);
174 caifd = caif_get(dev);
175 if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd)
176 return NET_RX_DROP;
177
178 if (caifd->layer.up->receive(caifd->layer.up, pkt))
179 return NET_RX_DROP;
180
181 return 0;
182}
183
184static struct packet_type caif_packet_type __read_mostly = {
185 .type = cpu_to_be16(ETH_P_CAIF),
186 .func = receive,
187};
188
189static void dev_flowctrl(struct net_device *dev, int on)
190{
191 struct caif_device_entry *caifd = caif_get(dev);
192 if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd)
193 return;
194
195 caifd->layer.up->ctrlcmd(caifd->layer.up,
196 on ?
197 _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND :
198 _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND,
199 caifd->layer.id);
200}
201
202/* notify Caif of device events */
203static int caif_device_notify(struct notifier_block *me, unsigned long what,
204 void *arg)
205{
206 struct net_device *dev = arg;
207 struct caif_device_entry *caifd = NULL;
208 struct caif_dev_common *caifdev;
209 enum cfcnfg_phy_preference pref;
210 int res = -EINVAL;
211 enum cfcnfg_phy_type phy_type;
212
213 if (dev->type != ARPHRD_CAIF)
214 return 0;
215
216 switch (what) {
217 case NETDEV_REGISTER:
218 pr_info("CAIF: %s():register %s\n", __func__, dev->name);
219 caifd = caif_device_alloc(dev);
220 if (caifd == NULL)
221 break;
222 caifdev = netdev_priv(dev);
223 caifdev->flowctrl = dev_flowctrl;
224 atomic_set(&caifd->state, what);
225 res = 0;
226 break;
227
228 case NETDEV_UP:
229 pr_info("CAIF: %s(): up %s\n", __func__, dev->name);
230 caifd = caif_get(dev);
231 if (caifd == NULL)
232 break;
233 caifdev = netdev_priv(dev);
234 if (atomic_read(&caifd->state) == NETDEV_UP) {
235 pr_info("CAIF: %s():%s already up\n",
236 __func__, dev->name);
237 break;
238 }
239 atomic_set(&caifd->state, what);
240 caifd->layer.transmit = transmit;
241 caifd->layer.modemcmd = modemcmd;
242
243 if (caifdev->use_frag)
244 phy_type = CFPHYTYPE_FRAG;
245 else
246 phy_type = CFPHYTYPE_CAIF;
247
248 switch (caifdev->link_select) {
249 case CAIF_LINK_HIGH_BANDW:
250 pref = CFPHYPREF_LOW_LAT;
251 break;
252 case CAIF_LINK_LOW_LATENCY:
253 pref = CFPHYPREF_HIGH_BW;
254 break;
255 default:
256 pref = CFPHYPREF_HIGH_BW;
257 break;
258 }
259
260 cfcnfg_add_phy_layer(get_caif_conf(),
261 phy_type,
262 dev,
263 &caifd->layer,
264 &caifd->phyid,
265 pref,
266 caifdev->use_fcs,
267 caifdev->use_stx);
268 strncpy(caifd->layer.name, dev->name,
269 sizeof(caifd->layer.name) - 1);
270 caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0;
271 break;
272
273 case NETDEV_GOING_DOWN:
274 caifd = caif_get(dev);
275 if (caifd == NULL)
276 break;
277 pr_info("CAIF: %s():going down %s\n", __func__, dev->name);
278
279 if (atomic_read(&caifd->state) == NETDEV_GOING_DOWN ||
280 atomic_read(&caifd->state) == NETDEV_DOWN)
281 break;
282
283 atomic_set(&caifd->state, what);
284 if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd)
285 return -EINVAL;
286 caifd->layer.up->ctrlcmd(caifd->layer.up,
287 _CAIF_CTRLCMD_PHYIF_DOWN_IND,
288 caifd->layer.id);
289 res = wait_event_interruptible_timeout(caifd->event,
290 atomic_read(&caifd->in_use) == 0,
291 TIMEOUT);
292 break;
293
294 case NETDEV_DOWN:
295 caifd = caif_get(dev);
296 if (caifd == NULL)
297 break;
298 pr_info("CAIF: %s(): down %s\n", __func__, dev->name);
299 if (atomic_read(&caifd->in_use))
300 pr_warning("CAIF: %s(): "
301 "Unregistering an active CAIF device: %s\n",
302 __func__, dev->name);
303 cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer);
304 atomic_set(&caifd->state, what);
305 break;
306
307 case NETDEV_UNREGISTER:
308 caifd = caif_get(dev);
309 pr_info("CAIF: %s(): unregister %s\n", __func__, dev->name);
310 atomic_set(&caifd->state, what);
311 caif_device_destroy(dev);
312 break;
313 }
314 return 0;
315}
316
317static struct notifier_block caif_device_notifier = {
318 .notifier_call = caif_device_notify,
319 .priority = 0,
320};
321
322
323struct cfcnfg *get_caif_conf(void)
324{
325 return cfg;
326}
327EXPORT_SYMBOL(get_caif_conf);
328
329int caif_connect_client(struct caif_connect_request *conn_req,
330 struct cflayer *client_layer)
331{
332 struct cfctrl_link_param param;
333 if (connect_req_to_link_param(get_caif_conf(), conn_req, &param) == 0)
334 /* Hook up the adaptation layer. */
335 return cfcnfg_add_adaptation_layer(get_caif_conf(),
336 &param, client_layer);
337
338 return -EINVAL;
339
340 caif_assert(0);
341}
342EXPORT_SYMBOL(caif_connect_client);
343
344int caif_disconnect_client(struct cflayer *adap_layer)
345{
346 return cfcnfg_del_adapt_layer(get_caif_conf(), adap_layer);
347}
348EXPORT_SYMBOL(caif_disconnect_client);
349
350/* Per-namespace Caif devices handling */
351static int caif_init_net(struct net *net)
352{
353 struct caif_net *caifn = net_generic(net, caif_net_id);
354 INIT_LIST_HEAD(&caifn->caifdevs.list);
355 spin_lock_init(&caifn->caifdevs.lock);
356 return 0;
357}
358
359static void caif_exit_net(struct net *net)
360{
361 struct net_device *dev;
362 int res;
363 rtnl_lock();
364 for_each_netdev(net, dev) {
365 if (dev->type != ARPHRD_CAIF)
366 continue;
367 res = dev_close(dev);
368 caif_device_destroy(dev);
369 }
370 rtnl_unlock();
371}
372
373static struct pernet_operations caif_net_ops = {
374 .init = caif_init_net,
375 .exit = caif_exit_net,
376 .id = &caif_net_id,
377 .size = sizeof(struct caif_net),
378};
379
380/* Initialize Caif devices list */
381static int __init caif_device_init(void)
382{
383 int result;
384 cfg = cfcnfg_create();
385 if (!cfg) {
386 pr_warning("CAIF: %s(): can't create cfcnfg.\n", __func__);
387 goto err_cfcnfg_create_failed;
388 }
389 result = register_pernet_device(&caif_net_ops);
390
391 if (result) {
392 kfree(cfg);
393 cfg = NULL;
394 return result;
395 }
396 dev_add_pack(&caif_packet_type);
397 register_netdevice_notifier(&caif_device_notifier);
398
399 return result;
400err_cfcnfg_create_failed:
401 return -ENODEV;
402}
403
404static void __exit caif_device_exit(void)
405{
406 dev_remove_pack(&caif_packet_type);
407 unregister_pernet_device(&caif_net_ops);
408 unregister_netdevice_notifier(&caif_device_notifier);
409 cfcnfg_remove(cfg);
410}
411
412module_init(caif_device_init);
413module_exit(caif_device_exit);
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
new file mode 100644
index 000000000000..cdf62b9fefac
--- /dev/null
+++ b/net/caif/caif_socket.c
@@ -0,0 +1,1391 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland sjur.brandeland@stericsson.com
4 * Per Sigmond per.sigmond@stericsson.com
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#include <linux/fs.h>
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/sched.h>
12#include <linux/spinlock.h>
13#include <linux/mutex.h>
14#include <linux/list.h>
15#include <linux/wait.h>
16#include <linux/poll.h>
17#include <linux/tcp.h>
18#include <linux/uaccess.h>
19#include <asm/atomic.h>
20
21#include <linux/caif/caif_socket.h>
22#include <net/caif/caif_layer.h>
23#include <net/caif/caif_dev.h>
24#include <net/caif/cfpkt.h>
25
26MODULE_LICENSE("GPL");
27
28#define CHNL_SKT_READ_QUEUE_HIGH 200
29#define CHNL_SKT_READ_QUEUE_LOW 100
30
31static int caif_sockbuf_size = 40000;
32static atomic_t caif_nr_socks = ATOMIC_INIT(0);
33
34#define CONN_STATE_OPEN_BIT 1
35#define CONN_STATE_PENDING_BIT 2
36#define CONN_STATE_PEND_DESTROY_BIT 3
37#define CONN_REMOTE_SHUTDOWN_BIT 4
38
39#define TX_FLOW_ON_BIT 1
40#define RX_FLOW_ON_BIT 2
41
42#define STATE_IS_OPEN(cf_sk) test_bit(CONN_STATE_OPEN_BIT,\
43 (void *) &(cf_sk)->conn_state)
44#define STATE_IS_REMOTE_SHUTDOWN(cf_sk) test_bit(CONN_REMOTE_SHUTDOWN_BIT,\
45 (void *) &(cf_sk)->conn_state)
46#define STATE_IS_PENDING(cf_sk) test_bit(CONN_STATE_PENDING_BIT,\
47 (void *) &(cf_sk)->conn_state)
48#define STATE_IS_PENDING_DESTROY(cf_sk) test_bit(CONN_STATE_PEND_DESTROY_BIT,\
49 (void *) &(cf_sk)->conn_state)
50
51#define SET_STATE_PENDING_DESTROY(cf_sk) set_bit(CONN_STATE_PEND_DESTROY_BIT,\
52 (void *) &(cf_sk)->conn_state)
53#define SET_STATE_OPEN(cf_sk) set_bit(CONN_STATE_OPEN_BIT,\
54 (void *) &(cf_sk)->conn_state)
55#define SET_STATE_CLOSED(cf_sk) clear_bit(CONN_STATE_OPEN_BIT,\
56 (void *) &(cf_sk)->conn_state)
57#define SET_PENDING_ON(cf_sk) set_bit(CONN_STATE_PENDING_BIT,\
58 (void *) &(cf_sk)->conn_state)
59#define SET_PENDING_OFF(cf_sk) clear_bit(CONN_STATE_PENDING_BIT,\
60 (void *) &(cf_sk)->conn_state)
61#define SET_REMOTE_SHUTDOWN(cf_sk) set_bit(CONN_REMOTE_SHUTDOWN_BIT,\
62 (void *) &(cf_sk)->conn_state)
63
64#define SET_REMOTE_SHUTDOWN_OFF(dev) clear_bit(CONN_REMOTE_SHUTDOWN_BIT,\
65 (void *) &(dev)->conn_state)
66#define RX_FLOW_IS_ON(cf_sk) test_bit(RX_FLOW_ON_BIT,\
67 (void *) &(cf_sk)->flow_state)
68#define TX_FLOW_IS_ON(cf_sk) test_bit(TX_FLOW_ON_BIT,\
69 (void *) &(cf_sk)->flow_state)
70
71#define SET_RX_FLOW_OFF(cf_sk) clear_bit(RX_FLOW_ON_BIT,\
72 (void *) &(cf_sk)->flow_state)
73#define SET_RX_FLOW_ON(cf_sk) set_bit(RX_FLOW_ON_BIT,\
74 (void *) &(cf_sk)->flow_state)
75#define SET_TX_FLOW_OFF(cf_sk) clear_bit(TX_FLOW_ON_BIT,\
76 (void *) &(cf_sk)->flow_state)
77#define SET_TX_FLOW_ON(cf_sk) set_bit(TX_FLOW_ON_BIT,\
78 (void *) &(cf_sk)->flow_state)
79
80#define SKT_READ_FLAG 0x01
81#define SKT_WRITE_FLAG 0x02
82static struct dentry *debugfsdir;
83#include <linux/debugfs.h>
84
85#ifdef CONFIG_DEBUG_FS
86struct debug_fs_counter {
87 atomic_t num_open;
88 atomic_t num_close;
89 atomic_t num_init;
90 atomic_t num_init_resp;
91 atomic_t num_init_fail_resp;
92 atomic_t num_deinit;
93 atomic_t num_deinit_resp;
94 atomic_t num_remote_shutdown_ind;
95 atomic_t num_tx_flow_off_ind;
96 atomic_t num_tx_flow_on_ind;
97 atomic_t num_rx_flow_off;
98 atomic_t num_rx_flow_on;
99 atomic_t skb_in_use;
100 atomic_t skb_alloc;
101 atomic_t skb_free;
102};
103static struct debug_fs_counter cnt;
104#define dbfs_atomic_inc(v) atomic_inc(v)
105#define dbfs_atomic_dec(v) atomic_dec(v)
106#else
107#define dbfs_atomic_inc(v)
108#define dbfs_atomic_dec(v)
109#endif
110
111/* The AF_CAIF socket */
112struct caifsock {
113 /* NOTE: sk has to be the first member */
114 struct sock sk;
115 struct cflayer layer;
116 char name[CAIF_LAYER_NAME_SZ];
117 u32 conn_state;
118 u32 flow_state;
119 struct cfpktq *pktq;
120 int file_mode;
121 struct caif_connect_request conn_req;
122 int read_queue_len;
123 /* protect updates of read_queue_len */
124 spinlock_t read_queue_len_lock;
125 struct dentry *debugfs_socket_dir;
126};
127
128static void drain_queue(struct caifsock *cf_sk);
129
130/* Packet Receive Callback function called from CAIF Stack */
131static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt)
132{
133 struct caifsock *cf_sk;
134 int read_queue_high;
135 cf_sk = container_of(layr, struct caifsock, layer);
136
137 if (!STATE_IS_OPEN(cf_sk)) {
138 /*FIXME: This should be allowed finally!*/
139 pr_debug("CAIF: %s(): called after close request\n", __func__);
140 cfpkt_destroy(pkt);
141 return 0;
142 }
143 /* NOTE: This function may be called in Tasklet context! */
144
145 /* The queue has its own lock */
146 cfpkt_queue(cf_sk->pktq, pkt, 0);
147
148 spin_lock(&cf_sk->read_queue_len_lock);
149 cf_sk->read_queue_len++;
150
151 read_queue_high = (cf_sk->read_queue_len > CHNL_SKT_READ_QUEUE_HIGH);
152 spin_unlock(&cf_sk->read_queue_len_lock);
153
154 if (RX_FLOW_IS_ON(cf_sk) && read_queue_high) {
155 dbfs_atomic_inc(&cnt.num_rx_flow_off);
156 SET_RX_FLOW_OFF(cf_sk);
157
158 /* Send flow off (NOTE: must not sleep) */
159 pr_debug("CAIF: %s():"
160 " sending flow OFF (queue len = %d)\n",
161 __func__,
162 cf_sk->read_queue_len);
163 caif_assert(cf_sk->layer.dn);
164 caif_assert(cf_sk->layer.dn->ctrlcmd);
165
166 (void) cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
167 CAIF_MODEMCMD_FLOW_OFF_REQ);
168 }
169
170 /* Signal reader that data is available. */
171
172 wake_up_interruptible(cf_sk->sk.sk_sleep);
173
174 return 0;
175}
176
177/* Packet Flow Control Callback function called from CAIF */
178static void caif_sktflowctrl_cb(struct cflayer *layr,
179 enum caif_ctrlcmd flow,
180 int phyid)
181{
182 struct caifsock *cf_sk;
183
184 /* NOTE: This function may be called in Tasklet context! */
185 pr_debug("CAIF: %s(): flowctrl func called: %s.\n",
186 __func__,
187 flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" :
188 flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" :
189 flow == CAIF_CTRLCMD_INIT_RSP ? "INIT_RSP" :
190 flow == CAIF_CTRLCMD_DEINIT_RSP ? "DEINIT_RSP" :
191 flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "INIT_FAIL_RSP" :
192 flow ==
193 CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? "REMOTE_SHUTDOWN" :
194 "UKNOWN CTRL COMMAND");
195
196 if (layr == NULL)
197 return;
198
199 cf_sk = container_of(layr, struct caifsock, layer);
200
201 switch (flow) {
202 case CAIF_CTRLCMD_FLOW_ON_IND:
203 dbfs_atomic_inc(&cnt.num_tx_flow_on_ind);
204 /* Signal reader that data is available. */
205 SET_TX_FLOW_ON(cf_sk);
206 wake_up_interruptible(cf_sk->sk.sk_sleep);
207 break;
208
209 case CAIF_CTRLCMD_FLOW_OFF_IND:
210 dbfs_atomic_inc(&cnt.num_tx_flow_off_ind);
211 SET_TX_FLOW_OFF(cf_sk);
212 break;
213
214 case CAIF_CTRLCMD_INIT_RSP:
215 dbfs_atomic_inc(&cnt.num_init_resp);
216 /* Signal reader that data is available. */
217 caif_assert(STATE_IS_OPEN(cf_sk));
218 SET_PENDING_OFF(cf_sk);
219 SET_TX_FLOW_ON(cf_sk);
220 wake_up_interruptible(cf_sk->sk.sk_sleep);
221 break;
222
223 case CAIF_CTRLCMD_DEINIT_RSP:
224 dbfs_atomic_inc(&cnt.num_deinit_resp);
225 caif_assert(!STATE_IS_OPEN(cf_sk));
226 SET_PENDING_OFF(cf_sk);
227 if (!STATE_IS_PENDING_DESTROY(cf_sk)) {
228 if (cf_sk->sk.sk_sleep != NULL)
229 wake_up_interruptible(cf_sk->sk.sk_sleep);
230 }
231 dbfs_atomic_inc(&cnt.num_deinit);
232 sock_put(&cf_sk->sk);
233 break;
234
235 case CAIF_CTRLCMD_INIT_FAIL_RSP:
236 dbfs_atomic_inc(&cnt.num_init_fail_resp);
237 caif_assert(STATE_IS_OPEN(cf_sk));
238 SET_STATE_CLOSED(cf_sk);
239 SET_PENDING_OFF(cf_sk);
240 SET_TX_FLOW_OFF(cf_sk);
241 wake_up_interruptible(cf_sk->sk.sk_sleep);
242 break;
243
244 case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
245 dbfs_atomic_inc(&cnt.num_remote_shutdown_ind);
246 SET_REMOTE_SHUTDOWN(cf_sk);
247 /* Use sk_shutdown to indicate remote shutdown indication */
248 cf_sk->sk.sk_shutdown |= RCV_SHUTDOWN;
249 cf_sk->file_mode = 0;
250 wake_up_interruptible(cf_sk->sk.sk_sleep);
251 break;
252
253 default:
254 pr_debug("CAIF: %s(): Unexpected flow command %d\n",
255 __func__, flow);
256 }
257}
258
259static void skb_destructor(struct sk_buff *skb)
260{
261 dbfs_atomic_inc(&cnt.skb_free);
262 dbfs_atomic_dec(&cnt.skb_in_use);
263}
264
265
266static int caif_recvmsg(struct kiocb *iocb, struct socket *sock,
267 struct msghdr *m, size_t buf_len, int flags)
268
269{
270 struct sock *sk = sock->sk;
271 struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
272 struct cfpkt *pkt = NULL;
273 size_t len;
274 int result;
275 struct sk_buff *skb;
276 ssize_t ret = -EIO;
277 int read_queue_low;
278
279 if (cf_sk == NULL) {
280 pr_debug("CAIF: %s(): private_data not set!\n",
281 __func__);
282 ret = -EBADFD;
283 goto read_error;
284 }
285
286 /* Don't do multiple iovec entries yet */
287 if (m->msg_iovlen != 1)
288 return -EOPNOTSUPP;
289
290 if (unlikely(!buf_len))
291 return -EINVAL;
292
293 lock_sock(&(cf_sk->sk));
294
295 caif_assert(cf_sk->pktq);
296
297 if (!STATE_IS_OPEN(cf_sk)) {
298 /* Socket is closed or closing. */
299 if (!STATE_IS_PENDING(cf_sk)) {
300 pr_debug("CAIF: %s(): socket is closed (by remote)\n",
301 __func__);
302 ret = -EPIPE;
303 } else {
304 pr_debug("CAIF: %s(): socket is closing..\n", __func__);
305 ret = -EBADF;
306 }
307 goto read_error;
308 }
309 /* Socket is open or opening. */
310 if (STATE_IS_PENDING(cf_sk)) {
311 pr_debug("CAIF: %s(): socket is opening...\n", __func__);
312
313 if (flags & MSG_DONTWAIT) {
314 /* We can't block. */
315 pr_debug("CAIF: %s():state pending and MSG_DONTWAIT\n",
316 __func__);
317 ret = -EAGAIN;
318 goto read_error;
319 }
320
321 /*
322 * Blocking mode; state is pending and we need to wait
323 * for its conclusion.
324 */
325 release_sock(&cf_sk->sk);
326
327 result =
328 wait_event_interruptible(*cf_sk->sk.sk_sleep,
329 !STATE_IS_PENDING(cf_sk));
330
331 lock_sock(&(cf_sk->sk));
332
333 if (result == -ERESTARTSYS) {
334 pr_debug("CAIF: %s(): wait_event_interruptible"
335 " woken by a signal (1)", __func__);
336 ret = -ERESTARTSYS;
337 goto read_error;
338 }
339 }
340
341 if (STATE_IS_REMOTE_SHUTDOWN(cf_sk) ||
342 !STATE_IS_OPEN(cf_sk) ||
343 STATE_IS_PENDING(cf_sk)) {
344
345 pr_debug("CAIF: %s(): socket closed\n",
346 __func__);
347 ret = -ESHUTDOWN;
348 goto read_error;
349 }
350
351 /*
352 * Block if we don't have any received buffers.
353 * The queue has its own lock.
354 */
355 while ((pkt = cfpkt_qpeek(cf_sk->pktq)) == NULL) {
356
357 if (flags & MSG_DONTWAIT) {
358 pr_debug("CAIF: %s(): MSG_DONTWAIT\n", __func__);
359 ret = -EAGAIN;
360 goto read_error;
361 }
362 trace_printk("CAIF: %s() wait_event\n", __func__);
363
364 /* Let writers in. */
365 release_sock(&cf_sk->sk);
366
367 /* Block reader until data arrives or socket is closed. */
368 if (wait_event_interruptible(*cf_sk->sk.sk_sleep,
369 cfpkt_qpeek(cf_sk->pktq)
370 || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
371 || !STATE_IS_OPEN(cf_sk)) ==
372 -ERESTARTSYS) {
373 pr_debug("CAIF: %s():"
374 " wait_event_interruptible woken by "
375 "a signal, signal_pending(current) = %d\n",
376 __func__,
377 signal_pending(current));
378 return -ERESTARTSYS;
379 }
380
381 trace_printk("CAIF: %s() awake\n", __func__);
382 if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
383 pr_debug("CAIF: %s(): "
384 "received remote_shutdown indication\n",
385 __func__);
386 ret = -ESHUTDOWN;
387 goto read_error_no_unlock;
388 }
389
390 /* I want to be alone on cf_sk (except status and queue). */
391 lock_sock(&(cf_sk->sk));
392
393 if (!STATE_IS_OPEN(cf_sk)) {
394 /* Someone closed the link, report error. */
395 pr_debug("CAIF: %s(): remote end shutdown!\n",
396 __func__);
397 ret = -EPIPE;
398 goto read_error;
399 }
400 }
401
402 /* The queue has its own lock. */
403 len = cfpkt_getlen(pkt);
404
405 /* Check max length that can be copied. */
406 if (len <= buf_len)
407 pkt = cfpkt_dequeue(cf_sk->pktq);
408 else {
409 pr_debug("CAIF: %s(): user buffer too small (%ld,%ld)\n",
410 __func__, (long) len, (long) buf_len);
411 if (sock->type == SOCK_SEQPACKET) {
412 ret = -EMSGSIZE;
413 goto read_error;
414 }
415 len = buf_len;
416 }
417
418
419 spin_lock(&cf_sk->read_queue_len_lock);
420 cf_sk->read_queue_len--;
421 read_queue_low = (cf_sk->read_queue_len < CHNL_SKT_READ_QUEUE_LOW);
422 spin_unlock(&cf_sk->read_queue_len_lock);
423
424 if (!RX_FLOW_IS_ON(cf_sk) && read_queue_low) {
425 dbfs_atomic_inc(&cnt.num_rx_flow_on);
426 SET_RX_FLOW_ON(cf_sk);
427
428 /* Send flow on. */
429 pr_debug("CAIF: %s(): sending flow ON (queue len = %d)\n",
430 __func__, cf_sk->read_queue_len);
431 caif_assert(cf_sk->layer.dn);
432 caif_assert(cf_sk->layer.dn->ctrlcmd);
433 (void) cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
434 CAIF_MODEMCMD_FLOW_ON_REQ);
435
436 caif_assert(cf_sk->read_queue_len >= 0);
437 }
438
439 skb = cfpkt_tonative(pkt);
440 result = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len);
441 skb_pull(skb, len);
442
443 if (result) {
444 pr_debug("CAIF: %s(): copy to_iovec failed\n", __func__);
445 cfpkt_destroy(pkt);
446 ret = -EFAULT;
447 goto read_error;
448 }
449
450 /* Free packet and remove from queue */
451 if (skb->len == 0)
452 skb_free_datagram(sk, skb);
453
454 /* Let the others in. */
455 release_sock(&cf_sk->sk);
456 return len;
457
458read_error:
459 release_sock(&cf_sk->sk);
460read_error_no_unlock:
461 return ret;
462}
463
464/* Send a signal as a consequence of sendmsg, sendto or caif_sendmsg. */
465static int caif_sendmsg(struct kiocb *kiocb, struct socket *sock,
466 struct msghdr *msg, size_t len)
467{
468
469 struct sock *sk = sock->sk;
470 struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
471 size_t payload_size = msg->msg_iov->iov_len;
472 struct cfpkt *pkt = NULL;
473 struct caif_payload_info info;
474 unsigned char *txbuf;
475 ssize_t ret = -EIO;
476 int result;
477 struct sk_buff *skb;
478 caif_assert(msg->msg_iovlen == 1);
479
480 if (cf_sk == NULL) {
481 pr_debug("CAIF: %s(): private_data not set!\n",
482 __func__);
483 ret = -EBADFD;
484 goto write_error_no_unlock;
485 }
486
487 if (unlikely(msg->msg_iov->iov_base == NULL)) {
488 pr_warning("CAIF: %s(): Buffer is NULL.\n", __func__);
489 ret = -EINVAL;
490 goto write_error_no_unlock;
491 }
492
493 if (payload_size > CAIF_MAX_PAYLOAD_SIZE) {
494 pr_debug("CAIF: %s(): buffer too long\n", __func__);
495 if (sock->type == SOCK_SEQPACKET) {
496 ret = -EINVAL;
497 goto write_error_no_unlock;
498 }
499 payload_size = CAIF_MAX_PAYLOAD_SIZE;
500 }
501
502 /* I want to be alone on cf_sk (except status and queue) */
503 lock_sock(&(cf_sk->sk));
504
505 caif_assert(cf_sk->pktq);
506
507 if (!STATE_IS_OPEN(cf_sk)) {
508 /* Socket is closed or closing */
509 if (!STATE_IS_PENDING(cf_sk)) {
510 pr_debug("CAIF: %s(): socket is closed (by remote)\n",
511 __func__);
512 ret = -EPIPE;
513 } else {
514 pr_debug("CAIF: %s(): socket is closing...\n",
515 __func__);
516 ret = -EBADF;
517 }
518 goto write_error;
519 }
520
521 /* Socket is open or opening */
522 if (STATE_IS_PENDING(cf_sk)) {
523 pr_debug("CAIF: %s(): socket is opening...\n", __func__);
524
525 if (msg->msg_flags & MSG_DONTWAIT) {
526 /* We can't block */
527 trace_printk("CAIF: %s():state pending:"
528 "state=MSG_DONTWAIT\n", __func__);
529 ret = -EAGAIN;
530 goto write_error;
531 }
532 /* Let readers in */
533 release_sock(&cf_sk->sk);
534
535 /*
536 * Blocking mode; state is pending and we need to wait
537 * for its conclusion.
538 */
539 result =
540 wait_event_interruptible(*cf_sk->sk.sk_sleep,
541 !STATE_IS_PENDING(cf_sk));
542 /* I want to be alone on cf_sk (except status and queue) */
543 lock_sock(&(cf_sk->sk));
544
545 if (result == -ERESTARTSYS) {
546 pr_debug("CAIF: %s(): wait_event_interruptible"
547 " woken by a signal (1)", __func__);
548 ret = -ERESTARTSYS;
549 goto write_error;
550 }
551 }
552 if (STATE_IS_REMOTE_SHUTDOWN(cf_sk) ||
553 !STATE_IS_OPEN(cf_sk) ||
554 STATE_IS_PENDING(cf_sk)) {
555
556 pr_debug("CAIF: %s(): socket closed\n",
557 __func__);
558 ret = -ESHUTDOWN;
559 goto write_error;
560 }
561
562 if (!TX_FLOW_IS_ON(cf_sk)) {
563
564 /* Flow is off. Check non-block flag */
565 if (msg->msg_flags & MSG_DONTWAIT) {
566 trace_printk("CAIF: %s(): MSG_DONTWAIT and tx flow off",
567 __func__);
568 ret = -EAGAIN;
569 goto write_error;
570 }
571
572 /* release lock before waiting */
573 release_sock(&cf_sk->sk);
574
575 /* Wait until flow is on or socket is closed */
576 if (wait_event_interruptible(*cf_sk->sk.sk_sleep,
577 TX_FLOW_IS_ON(cf_sk)
578 || !STATE_IS_OPEN(cf_sk)
579 || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
580 ) == -ERESTARTSYS) {
581 pr_debug("CAIF: %s():"
582 " wait_event_interruptible woken by a signal",
583 __func__);
584 ret = -ERESTARTSYS;
585 goto write_error_no_unlock;
586 }
587
588 /* I want to be alone on cf_sk (except status and queue) */
589 lock_sock(&(cf_sk->sk));
590
591 if (!STATE_IS_OPEN(cf_sk)) {
592 /* someone closed the link, report error */
593 pr_debug("CAIF: %s(): remote end shutdown!\n",
594 __func__);
595 ret = -EPIPE;
596 goto write_error;
597 }
598
599 if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
600 pr_debug("CAIF: %s(): "
601 "received remote_shutdown indication\n",
602 __func__);
603 ret = -ESHUTDOWN;
604 goto write_error;
605 }
606 }
607
608 pkt = cfpkt_create(payload_size);
609 skb = (struct sk_buff *)pkt;
610 skb->destructor = skb_destructor;
611 skb->sk = sk;
612 dbfs_atomic_inc(&cnt.skb_alloc);
613 dbfs_atomic_inc(&cnt.skb_in_use);
614 if (cfpkt_raw_append(pkt, (void **) &txbuf, payload_size) < 0) {
615 pr_debug("CAIF: %s(): cfpkt_raw_append failed\n", __func__);
616 cfpkt_destroy(pkt);
617 ret = -EINVAL;
618 goto write_error;
619 }
620
621 /* Copy data into buffer. */
622 if (copy_from_user(txbuf, msg->msg_iov->iov_base, payload_size)) {
623 pr_debug("CAIF: %s(): copy_from_user returned non zero.\n",
624 __func__);
625 cfpkt_destroy(pkt);
626 ret = -EINVAL;
627 goto write_error;
628 }
629 memset(&info, 0, sizeof(info));
630
631 /* Send the packet down the stack. */
632 caif_assert(cf_sk->layer.dn);
633 caif_assert(cf_sk->layer.dn->transmit);
634
635 do {
636 ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
637
638 if (likely((ret >= 0) || (ret != -EAGAIN)))
639 break;
640
641 /* EAGAIN - retry */
642 if (msg->msg_flags & MSG_DONTWAIT) {
643 pr_debug("CAIF: %s(): NONBLOCK and transmit failed,"
644 " error = %ld\n", __func__, (long) ret);
645 ret = -EAGAIN;
646 goto write_error;
647 }
648
649 /* Let readers in */
650 release_sock(&cf_sk->sk);
651
652 /* Wait until flow is on or socket is closed */
653 if (wait_event_interruptible(*cf_sk->sk.sk_sleep,
654 TX_FLOW_IS_ON(cf_sk)
655 || !STATE_IS_OPEN(cf_sk)
656 || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
657 ) == -ERESTARTSYS) {
658 pr_debug("CAIF: %s(): wait_event_interruptible"
659 " woken by a signal", __func__);
660 ret = -ERESTARTSYS;
661 goto write_error_no_unlock;
662 }
663
664 /* I want to be alone on cf_sk (except status and queue) */
665 lock_sock(&(cf_sk->sk));
666
667 } while (ret == -EAGAIN);
668
669 if (ret < 0) {
670 cfpkt_destroy(pkt);
671 pr_debug("CAIF: %s(): transmit failed, error = %ld\n",
672 __func__, (long) ret);
673
674 goto write_error;
675 }
676
677 release_sock(&cf_sk->sk);
678 return payload_size;
679
680write_error:
681 release_sock(&cf_sk->sk);
682write_error_no_unlock:
683 return ret;
684}
685
686static unsigned int caif_poll(struct file *file, struct socket *sock,
687 poll_table *wait)
688{
689 struct sock *sk = sock->sk;
690 struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
691 u32 mask = 0;
692 poll_wait(file, sk->sk_sleep, wait);
693 lock_sock(&(cf_sk->sk));
694 if (!STATE_IS_OPEN(cf_sk)) {
695 if (!STATE_IS_PENDING(cf_sk))
696 mask |= POLLHUP;
697 } else {
698 if (cfpkt_qpeek(cf_sk->pktq) != NULL)
699 mask |= (POLLIN | POLLRDNORM);
700 if (TX_FLOW_IS_ON(cf_sk))
701 mask |= (POLLOUT | POLLWRNORM);
702 }
703 release_sock(&cf_sk->sk);
704 trace_printk("CAIF: %s(): poll mask=0x%04x\n",
705 __func__, mask);
706 return mask;
707}
708
709static void drain_queue(struct caifsock *cf_sk)
710{
711 struct cfpkt *pkt = NULL;
712
713 /* Empty the queue */
714 do {
715 /* The queue has its own lock */
716 if (!cf_sk->pktq)
717 break;
718
719 pkt = cfpkt_dequeue(cf_sk->pktq);
720 if (!pkt)
721 break;
722 pr_debug("CAIF: %s(): freeing packet from read queue\n",
723 __func__);
724 cfpkt_destroy(pkt);
725
726 } while (1);
727
728 cf_sk->read_queue_len = 0;
729}
730
731static int setsockopt(struct socket *sock,
732 int lvl, int opt, char __user *ov, unsigned int ol)
733{
734 struct sock *sk = sock->sk;
735 struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
736 int prio, linksel;
737 struct ifreq ifreq;
738
739 if (STATE_IS_OPEN(cf_sk)) {
740 pr_debug("CAIF: %s(): setsockopt "
741 "cannot be done on a connected socket\n",
742 __func__);
743 return -ENOPROTOOPT;
744 }
745 switch (opt) {
746 case CAIFSO_LINK_SELECT:
747 if (ol < sizeof(int)) {
748 pr_debug("CAIF: %s(): setsockopt"
749 " CAIFSO_CHANNEL_CONFIG bad size\n", __func__);
750 return -EINVAL;
751 }
752 if (lvl != SOL_CAIF)
753 goto bad_sol;
754 if (copy_from_user(&linksel, ov, sizeof(int)))
755 return -EINVAL;
756 lock_sock(&(cf_sk->sk));
757 cf_sk->conn_req.link_selector = linksel;
758 release_sock(&cf_sk->sk);
759 return 0;
760
761 case SO_PRIORITY:
762 if (lvl != SOL_SOCKET)
763 goto bad_sol;
764 if (ol < sizeof(int)) {
765 pr_debug("CAIF: %s(): setsockopt"
766 " SO_PRIORITY bad size\n", __func__);
767 return -EINVAL;
768 }
769 if (copy_from_user(&prio, ov, sizeof(int)))
770 return -EINVAL;
771 lock_sock(&(cf_sk->sk));
772 cf_sk->conn_req.priority = prio;
773 pr_debug("CAIF: %s(): Setting sockopt priority=%d\n", __func__,
774 cf_sk->conn_req.priority);
775 release_sock(&cf_sk->sk);
776 return 0;
777
778 case SO_BINDTODEVICE:
779 if (lvl != SOL_SOCKET)
780 goto bad_sol;
781 if (ol < sizeof(struct ifreq)) {
782 pr_debug("CAIF: %s(): setsockopt"
783 " SO_PRIORITY bad size\n", __func__);
784 return -EINVAL;
785 }
786 if (copy_from_user(&ifreq, ov, sizeof(ifreq)))
787 return -EFAULT;
788 lock_sock(&(cf_sk->sk));
789 strncpy(cf_sk->conn_req.link_name, ifreq.ifr_name,
790 sizeof(cf_sk->conn_req.link_name));
791 cf_sk->conn_req.link_name
792 [sizeof(cf_sk->conn_req.link_name)-1] = 0;
793 release_sock(&cf_sk->sk);
794 return 0;
795
796 case CAIFSO_REQ_PARAM:
797 if (lvl != SOL_CAIF)
798 goto bad_sol;
799 if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL)
800 return -ENOPROTOOPT;
801 if (ol > sizeof(cf_sk->conn_req.param.data))
802 goto req_param_bad_size;
803
804 lock_sock(&(cf_sk->sk));
805 cf_sk->conn_req.param.size = ol;
806 if (copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) {
807 release_sock(&cf_sk->sk);
808req_param_bad_size:
809 pr_debug("CAIF: %s(): setsockopt"
810 " CAIFSO_CHANNEL_CONFIG bad size\n", __func__);
811 return -EINVAL;
812 }
813
814 release_sock(&cf_sk->sk);
815 return 0;
816
817 default:
818 pr_debug("CAIF: %s(): unhandled option %d\n", __func__, opt);
819 return -EINVAL;
820 }
821
822 return 0;
823bad_sol:
824 pr_debug("CAIF: %s(): setsockopt bad level\n", __func__);
825 return -ENOPROTOOPT;
826
827}
828
829static int caif_connect(struct socket *sock, struct sockaddr *uservaddr,
830 int sockaddr_len, int flags)
831{
832 struct caifsock *cf_sk = NULL;
833 int result = -1;
834 int mode = 0;
835 int ret = -EIO;
836 struct sock *sk = sock->sk;
837 BUG_ON(sk == NULL);
838
839 cf_sk = container_of(sk, struct caifsock, sk);
840
841 trace_printk("CAIF: %s(): cf_sk=%p OPEN=%d, TX_FLOW=%d, RX_FLOW=%d\n",
842 __func__, cf_sk,
843 STATE_IS_OPEN(cf_sk),
844 TX_FLOW_IS_ON(cf_sk), RX_FLOW_IS_ON(cf_sk));
845
846
847 if (sock->type == SOCK_SEQPACKET || sock->type == SOCK_STREAM)
848 sock->state = SS_CONNECTING;
849 else
850 goto out;
851
852 /* I want to be alone on cf_sk (except status and queue) */
853 lock_sock(&(cf_sk->sk));
854
855 if (sockaddr_len != sizeof(struct sockaddr_caif)) {
856 pr_debug("CAIF: %s(): Bad address len (%ld,%lu)\n",
857 __func__, (long) sockaddr_len,
858 (long unsigned) sizeof(struct sockaddr_caif));
859 ret = -EINVAL;
860 goto open_error;
861 }
862
863 if (uservaddr->sa_family != AF_CAIF) {
864 pr_debug("CAIF: %s(): Bad address family (%d)\n",
865 __func__, uservaddr->sa_family);
866 ret = -EAFNOSUPPORT;
867 goto open_error;
868 }
869
870 memcpy(&cf_sk->conn_req.sockaddr, uservaddr,
871 sizeof(struct sockaddr_caif));
872
873 dbfs_atomic_inc(&cnt.num_open);
874 mode = SKT_READ_FLAG | SKT_WRITE_FLAG;
875
876 /* If socket is not open, make sure socket is in fully closed state */
877 if (!STATE_IS_OPEN(cf_sk)) {
878 /* Has link close response been received (if we ever sent it)?*/
879 if (STATE_IS_PENDING(cf_sk)) {
880 /*
881 * Still waiting for close response from remote.
882 * If opened non-blocking, report "would block"
883 */
884 if (flags & O_NONBLOCK) {
885 pr_debug("CAIF: %s(): O_NONBLOCK"
886 " && close pending\n", __func__);
887 ret = -EAGAIN;
888 goto open_error;
889 }
890
891 pr_debug("CAIF: %s(): Wait for close response"
892 " from remote...\n", __func__);
893
894 release_sock(&cf_sk->sk);
895
896 /*
897 * Blocking mode; close is pending and we need to wait
898 * for its conclusion.
899 */
900 result =
901 wait_event_interruptible(*cf_sk->sk.sk_sleep,
902 !STATE_IS_PENDING(cf_sk));
903
904 lock_sock(&(cf_sk->sk));
905 if (result == -ERESTARTSYS) {
906 pr_debug("CAIF: %s(): wait_event_interruptible"
907 "woken by a signal (1)", __func__);
908 ret = -ERESTARTSYS;
909 goto open_error;
910 }
911 }
912 }
913
914 /* socket is now either closed, pending open or open */
915 if (STATE_IS_OPEN(cf_sk) && !STATE_IS_PENDING(cf_sk)) {
916 /* Open */
917 pr_debug("CAIF: %s(): Socket is already opened (cf_sk=%p)"
918 " check access f_flags = 0x%x file_mode = 0x%x\n",
919 __func__, cf_sk, mode, cf_sk->file_mode);
920
921 } else {
922 /* We are closed or pending open.
923 * If closed: send link setup
924 * If pending open: link setup already sent (we could have been
925 * interrupted by a signal last time)
926 */
927 if (!STATE_IS_OPEN(cf_sk)) {
928 /* First opening of file; connect lower layers: */
929 /* Drain queue (very unlikely) */
930 drain_queue(cf_sk);
931
932 cf_sk->layer.receive = caif_sktrecv_cb;
933 SET_STATE_OPEN(cf_sk);
934 SET_PENDING_ON(cf_sk);
935
936 /* Register this channel. */
937 result =
938 caif_connect_client(&cf_sk->conn_req,
939 &cf_sk->layer);
940 if (result < 0) {
941 pr_debug("CAIF: %s(): can't register channel\n",
942 __func__);
943 ret = -EIO;
944 SET_STATE_CLOSED(cf_sk);
945 SET_PENDING_OFF(cf_sk);
946 goto open_error;
947 }
948 dbfs_atomic_inc(&cnt.num_init);
949 }
950
951 /* If opened non-blocking, report "success".
952 */
953 if (flags & O_NONBLOCK) {
954 pr_debug("CAIF: %s(): O_NONBLOCK success\n",
955 __func__);
956 ret = -EINPROGRESS;
957 cf_sk->sk.sk_err = -EINPROGRESS;
958 goto open_error;
959 }
960
961 trace_printk("CAIF: %s(): Wait for connect response\n",
962 __func__);
963
964 /* release lock before waiting */
965 release_sock(&cf_sk->sk);
966
967 result =
968 wait_event_interruptible(*cf_sk->sk.sk_sleep,
969 !STATE_IS_PENDING(cf_sk));
970
971 lock_sock(&(cf_sk->sk));
972
973 if (result == -ERESTARTSYS) {
974 pr_debug("CAIF: %s(): wait_event_interruptible"
975 "woken by a signal (2)", __func__);
976 ret = -ERESTARTSYS;
977 goto open_error;
978 }
979
980 if (!STATE_IS_OPEN(cf_sk)) {
981 /* Lower layers said "no" */
982 pr_debug("CAIF: %s(): Closed received\n", __func__);
983 ret = -EPIPE;
984 goto open_error;
985 }
986
987 trace_printk("CAIF: %s(): Connect received\n", __func__);
988 }
989 /* Open is ok */
990 cf_sk->file_mode |= mode;
991
992 trace_printk("CAIF: %s(): Connected - file mode = %x\n",
993 __func__, cf_sk->file_mode);
994
995 release_sock(&cf_sk->sk);
996 return 0;
997open_error:
998 sock->state = SS_UNCONNECTED;
999 release_sock(&cf_sk->sk);
1000out:
1001 return ret;
1002}
1003
1004static int caif_shutdown(struct socket *sock, int how)
1005{
1006 struct caifsock *cf_sk = NULL;
1007 int result = 0;
1008 int tx_flow_state_was_on;
1009 struct sock *sk = sock->sk;
1010
1011 trace_printk("CAIF: %s(): enter\n", __func__);
1012 pr_debug("f_flags=%x\n", sock->file->f_flags);
1013
1014 if (how != SHUT_RDWR)
1015 return -EOPNOTSUPP;
1016
1017 cf_sk = container_of(sk, struct caifsock, sk);
1018 if (cf_sk == NULL) {
1019 pr_debug("CAIF: %s(): COULD NOT FIND SOCKET\n", __func__);
1020 return -EBADF;
1021 }
1022
1023 /* I want to be alone on cf_sk (except status queue) */
1024 lock_sock(&(cf_sk->sk));
1025 sock_hold(&cf_sk->sk);
1026
1027 /* IS_CLOSED have double meaning:
1028 * 1) Spontanous Remote Shutdown Request.
1029 * 2) Ack on a channel teardown(disconnect)
1030 * Must clear bit in case we previously received
1031 * remote shudown request.
1032 */
1033 if (STATE_IS_OPEN(cf_sk) && !STATE_IS_PENDING(cf_sk)) {
1034 SET_STATE_CLOSED(cf_sk);
1035 SET_PENDING_ON(cf_sk);
1036 tx_flow_state_was_on = TX_FLOW_IS_ON(cf_sk);
1037 SET_TX_FLOW_OFF(cf_sk);
1038
1039 /* Hold the socket until DEINIT_RSP is received */
1040 sock_hold(&cf_sk->sk);
1041 result = caif_disconnect_client(&cf_sk->layer);
1042
1043 if (result < 0) {
1044 pr_debug("CAIF: %s(): "
1045 "caif_disconnect_client() failed\n",
1046 __func__);
1047 SET_STATE_CLOSED(cf_sk);
1048 SET_PENDING_OFF(cf_sk);
1049 SET_TX_FLOW_OFF(cf_sk);
1050 release_sock(&cf_sk->sk);
1051 sock_put(&cf_sk->sk);
1052 return -EIO;
1053 }
1054
1055 }
1056 if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
1057 SET_PENDING_OFF(cf_sk);
1058 SET_REMOTE_SHUTDOWN_OFF(cf_sk);
1059 }
1060
1061 /*
1062 * Socket is no longer in state pending close,
1063 * and we can release the reference.
1064 */
1065
1066 dbfs_atomic_inc(&cnt.num_close);
1067 drain_queue(cf_sk);
1068 SET_RX_FLOW_ON(cf_sk);
1069 cf_sk->file_mode = 0;
1070 sock_put(&cf_sk->sk);
1071 release_sock(&cf_sk->sk);
1072 if (!result && (sock->file->f_flags & O_NONBLOCK)) {
1073 pr_debug("nonblocking shutdown returing -EAGAIN\n");
1074 return -EAGAIN;
1075 } else
1076 return result;
1077}
1078
1079static ssize_t caif_sock_no_sendpage(struct socket *sock,
1080 struct page *page,
1081 int offset, size_t size, int flags)
1082{
1083 return -EOPNOTSUPP;
1084}
1085
1086/* This function is called as part of close. */
1087static int caif_release(struct socket *sock)
1088{
1089 struct sock *sk = sock->sk;
1090 struct caifsock *cf_sk = NULL;
1091 int res;
1092 caif_assert(sk != NULL);
1093 cf_sk = container_of(sk, struct caifsock, sk);
1094
1095 if (cf_sk->debugfs_socket_dir != NULL)
1096 debugfs_remove_recursive(cf_sk->debugfs_socket_dir);
1097
1098 res = caif_shutdown(sock, SHUT_RDWR);
1099 if (res && res != -EINPROGRESS)
1100 return res;
1101
1102 /*
1103 * FIXME: Shutdown should probably be possible to do async
1104 * without flushing queues, allowing reception of frames while
1105 * waiting for DEINIT_IND.
1106 * Release should always block, to allow secure decoupling of
1107 * CAIF stack.
1108 */
1109 if (!(sock->file->f_flags & O_NONBLOCK)) {
1110 res = wait_event_interruptible(*cf_sk->sk.sk_sleep,
1111 !STATE_IS_PENDING(cf_sk));
1112
1113 if (res == -ERESTARTSYS) {
1114 pr_debug("CAIF: %s(): wait_event_interruptible"
1115 "woken by a signal (1)", __func__);
1116 }
1117 }
1118 lock_sock(&(cf_sk->sk));
1119
1120 sock->sk = NULL;
1121
1122 /* Detach the socket from its process context by making it orphan. */
1123 sock_orphan(sk);
1124
1125 /*
1126 * Setting SHUTDOWN_MASK means that both send and receive are shutdown
1127 * for the socket.
1128 */
1129 sk->sk_shutdown = SHUTDOWN_MASK;
1130
1131 /*
1132 * Set the socket state to closed, the TCP_CLOSE macro is used when
1133 * closing any socket.
1134 */
1135
1136 /* Flush out this sockets receive queue. */
1137 drain_queue(cf_sk);
1138
1139 /* Finally release the socket. */
1140 SET_STATE_PENDING_DESTROY(cf_sk);
1141
1142 release_sock(&cf_sk->sk);
1143
1144 sock_put(sk);
1145
1146 /*
1147 * The rest of the cleanup will be handled from the
1148 * caif_sock_destructor
1149 */
1150 return res;
1151}
1152
1153static const struct proto_ops caif_ops = {
1154 .family = PF_CAIF,
1155 .owner = THIS_MODULE,
1156 .release = caif_release,
1157 .bind = sock_no_bind,
1158 .connect = caif_connect,
1159 .socketpair = sock_no_socketpair,
1160 .accept = sock_no_accept,
1161 .getname = sock_no_getname,
1162 .poll = caif_poll,
1163 .ioctl = sock_no_ioctl,
1164 .listen = sock_no_listen,
1165 .shutdown = caif_shutdown,
1166 .setsockopt = setsockopt,
1167 .getsockopt = sock_no_getsockopt,
1168 .sendmsg = caif_sendmsg,
1169 .recvmsg = caif_recvmsg,
1170 .mmap = sock_no_mmap,
1171 .sendpage = caif_sock_no_sendpage,
1172};
1173
1174/* This function is called when a socket is finally destroyed. */
1175static void caif_sock_destructor(struct sock *sk)
1176{
1177 struct caifsock *cf_sk = NULL;
1178 cf_sk = container_of(sk, struct caifsock, sk);
1179 /* Error checks. */
1180 caif_assert(!atomic_read(&sk->sk_wmem_alloc));
1181 caif_assert(sk_unhashed(sk));
1182 caif_assert(!sk->sk_socket);
1183 if (!sock_flag(sk, SOCK_DEAD)) {
1184 pr_debug("CAIF: %s(): 0x%p", __func__, sk);
1185 return;
1186 }
1187
1188 if (STATE_IS_OPEN(cf_sk)) {
1189 pr_debug("CAIF: %s(): socket is opened (cf_sk=%p)"
1190 " file_mode = 0x%x\n", __func__,
1191 cf_sk, cf_sk->file_mode);
1192 return;
1193 }
1194 drain_queue(cf_sk);
1195 kfree(cf_sk->pktq);
1196
1197 trace_printk("CAIF: %s(): caif_sock_destructor: Removing socket %s\n",
1198 __func__, cf_sk->name);
1199 atomic_dec(&caif_nr_socks);
1200}
1201
1202static int caif_create(struct net *net, struct socket *sock, int protocol,
1203 int kern)
1204{
1205 struct sock *sk = NULL;
1206 struct caifsock *cf_sk = NULL;
1207 int result = 0;
1208 static struct proto prot = {.name = "PF_CAIF",
1209 .owner = THIS_MODULE,
1210 .obj_size = sizeof(struct caifsock),
1211 };
1212
1213 /*
1214 * The sock->type specifies the socket type to use.
1215 * in SEQPACKET mode packet boundaries are enforced.
1216 */
1217 if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
1218 return -ESOCKTNOSUPPORT;
1219
1220 if (net != &init_net)
1221 return -EAFNOSUPPORT;
1222
1223 if (protocol < 0 || protocol >= CAIFPROTO_MAX)
1224 return -EPROTONOSUPPORT;
1225 /*
1226 * Set the socket state to unconnected. The socket state is really
1227 * not used at all in the net/core or socket.c but the
1228 * initialization makes sure that sock->state is not uninitialized.
1229 */
1230 sock->state = SS_UNCONNECTED;
1231
1232 sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot);
1233 if (!sk)
1234 return -ENOMEM;
1235
1236 cf_sk = container_of(sk, struct caifsock, sk);
1237
1238 /* Store the protocol */
1239 sk->sk_protocol = (unsigned char) protocol;
1240
1241 spin_lock_init(&cf_sk->read_queue_len_lock);
1242
1243 /* Fill in some information concerning the misc socket. */
1244 snprintf(cf_sk->name, sizeof(cf_sk->name), "cf_sk%d",
1245 atomic_read(&caif_nr_socks));
1246
1247 /*
1248 * Lock in order to try to stop someone from opening the socket
1249 * too early.
1250 */
1251 lock_sock(&(cf_sk->sk));
1252
1253 /* Initialize the nozero default sock structure data. */
1254 sock_init_data(sock, sk);
1255 sock->ops = &caif_ops;
1256 sk->sk_destruct = caif_sock_destructor;
1257 sk->sk_sndbuf = caif_sockbuf_size;
1258 sk->sk_rcvbuf = caif_sockbuf_size;
1259
1260 cf_sk->pktq = cfpktq_create();
1261
1262 if (!cf_sk->pktq) {
1263 pr_err("CAIF: %s(): queue create failed.\n", __func__);
1264 result = -ENOMEM;
1265 release_sock(&cf_sk->sk);
1266 goto err_failed;
1267 }
1268 cf_sk->layer.ctrlcmd = caif_sktflowctrl_cb;
1269 SET_STATE_CLOSED(cf_sk);
1270 SET_PENDING_OFF(cf_sk);
1271 SET_TX_FLOW_OFF(cf_sk);
1272 SET_RX_FLOW_ON(cf_sk);
1273
1274 /* Set default options on configuration */
1275 cf_sk->conn_req.priority = CAIF_PRIO_NORMAL;
1276 cf_sk->conn_req.link_selector = CAIF_LINK_HIGH_BANDW;
1277 cf_sk->conn_req.protocol = protocol;
1278 /* Increase the number of sockets created. */
1279 atomic_inc(&caif_nr_socks);
1280 if (!IS_ERR(debugfsdir)) {
1281 cf_sk->debugfs_socket_dir =
1282 debugfs_create_dir(cf_sk->name, debugfsdir);
1283 debugfs_create_u32("conn_state", S_IRUSR | S_IWUSR,
1284 cf_sk->debugfs_socket_dir, &cf_sk->conn_state);
1285 debugfs_create_u32("flow_state", S_IRUSR | S_IWUSR,
1286 cf_sk->debugfs_socket_dir, &cf_sk->flow_state);
1287 debugfs_create_u32("read_queue_len", S_IRUSR | S_IWUSR,
1288 cf_sk->debugfs_socket_dir,
1289 (u32 *) &cf_sk->read_queue_len);
1290 debugfs_create_u32("identity", S_IRUSR | S_IWUSR,
1291 cf_sk->debugfs_socket_dir,
1292 (u32 *) &cf_sk->layer.id);
1293 }
1294 release_sock(&cf_sk->sk);
1295 return 0;
1296err_failed:
1297 sk_free(sk);
1298 return result;
1299}
1300
1301static struct net_proto_family caif_family_ops = {
1302 .family = PF_CAIF,
1303 .create = caif_create,
1304 .owner = THIS_MODULE,
1305};
1306
1307static int af_caif_init(void)
1308{
1309 int err;
1310 err = sock_register(&caif_family_ops);
1311
1312 if (!err)
1313 return err;
1314
1315 return 0;
1316}
1317
1318static int __init caif_sktinit_module(void)
1319{
1320 int stat;
1321#ifdef CONFIG_DEBUG_FS
1322 debugfsdir = debugfs_create_dir("chnl_skt", NULL);
1323 if (!IS_ERR(debugfsdir)) {
1324 debugfs_create_u32("skb_inuse", S_IRUSR | S_IWUSR,
1325 debugfsdir,
1326 (u32 *) &cnt.skb_in_use);
1327 debugfs_create_u32("skb_alloc", S_IRUSR | S_IWUSR,
1328 debugfsdir,
1329 (u32 *) &cnt.skb_alloc);
1330 debugfs_create_u32("skb_free", S_IRUSR | S_IWUSR,
1331 debugfsdir,
1332 (u32 *) &cnt.skb_free);
1333 debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR,
1334 debugfsdir,
1335 (u32 *) &caif_nr_socks);
1336 debugfs_create_u32("num_open", S_IRUSR | S_IWUSR,
1337 debugfsdir,
1338 (u32 *) &cnt.num_open);
1339 debugfs_create_u32("num_close", S_IRUSR | S_IWUSR,
1340 debugfsdir,
1341 (u32 *) &cnt.num_close);
1342 debugfs_create_u32("num_init", S_IRUSR | S_IWUSR,
1343 debugfsdir,
1344 (u32 *) &cnt.num_init);
1345 debugfs_create_u32("num_init_resp", S_IRUSR | S_IWUSR,
1346 debugfsdir,
1347 (u32 *) &cnt.num_init_resp);
1348 debugfs_create_u32("num_init_fail_resp", S_IRUSR | S_IWUSR,
1349 debugfsdir,
1350 (u32 *) &cnt.num_init_fail_resp);
1351 debugfs_create_u32("num_deinit", S_IRUSR | S_IWUSR,
1352 debugfsdir,
1353 (u32 *) &cnt.num_deinit);
1354 debugfs_create_u32("num_deinit_resp", S_IRUSR | S_IWUSR,
1355 debugfsdir,
1356 (u32 *) &cnt.num_deinit_resp);
1357 debugfs_create_u32("num_remote_shutdown_ind",
1358 S_IRUSR | S_IWUSR, debugfsdir,
1359 (u32 *) &cnt.num_remote_shutdown_ind);
1360 debugfs_create_u32("num_tx_flow_off_ind", S_IRUSR | S_IWUSR,
1361 debugfsdir,
1362 (u32 *) &cnt.num_tx_flow_off_ind);
1363 debugfs_create_u32("num_tx_flow_on_ind", S_IRUSR | S_IWUSR,
1364 debugfsdir,
1365 (u32 *) &cnt.num_tx_flow_on_ind);
1366 debugfs_create_u32("num_rx_flow_off", S_IRUSR | S_IWUSR,
1367 debugfsdir,
1368 (u32 *) &cnt.num_rx_flow_off);
1369 debugfs_create_u32("num_rx_flow_on", S_IRUSR | S_IWUSR,
1370 debugfsdir,
1371 (u32 *) &cnt.num_rx_flow_on);
1372 }
1373#endif
1374 stat = af_caif_init();
1375 if (stat) {
1376 pr_err("CAIF: %s(): Failed to initialize CAIF socket layer.",
1377 __func__);
1378 return stat;
1379 }
1380 return 0;
1381}
1382
1383static void __exit caif_sktexit_module(void)
1384{
1385 sock_unregister(PF_CAIF);
1386 if (debugfsdir != NULL)
1387 debugfs_remove_recursive(debugfsdir);
1388}
1389
1390module_init(caif_sktinit_module);
1391module_exit(caif_sktexit_module);
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
new file mode 100644
index 000000000000..c873e3d4387c
--- /dev/null
+++ b/net/caif/cfcnfg.c
@@ -0,0 +1,530 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6#include <linux/kernel.h>
7#include <linux/stddef.h>
8#include <linux/slab.h>
9#include <net/caif/caif_layer.h>
10#include <net/caif/cfpkt.h>
11#include <net/caif/cfcnfg.h>
12#include <net/caif/cfctrl.h>
13#include <net/caif/cfmuxl.h>
14#include <net/caif/cffrml.h>
15#include <net/caif/cfserl.h>
16#include <net/caif/cfsrvl.h>
17
18#include <linux/module.h>
19#include <asm/atomic.h>
20
21#define MAX_PHY_LAYERS 7
22#define PHY_NAME_LEN 20
23
24#define container_obj(layr) container_of(layr, struct cfcnfg, layer)
25
26/* Information about CAIF physical interfaces held by Config Module in order
27 * to manage physical interfaces
28 */
29struct cfcnfg_phyinfo {
30 /* Pointer to the layer below the MUX (framing layer) */
31 struct cflayer *frm_layer;
32 /* Pointer to the lowest actual physical layer */
33 struct cflayer *phy_layer;
34 /* Unique identifier of the physical interface */
35 unsigned int id;
36 /* Preference of the physical in interface */
37 enum cfcnfg_phy_preference pref;
38
39 /* Reference count, number of channels using the device */
40 int phy_ref_count;
41
42 /* Information about the physical device */
43 struct dev_info dev_info;
44};
45
46struct cfcnfg {
47 struct cflayer layer;
48 struct cflayer *ctrl;
49 struct cflayer *mux;
50 u8 last_phyid;
51 struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS];
52};
53
54static void cncfg_linkup_rsp(struct cflayer *layer, u8 linkid,
55 enum cfctrl_srv serv, u8 phyid,
56 struct cflayer *adapt_layer);
57static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid,
58 struct cflayer *client_layer);
59static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid,
60 struct cflayer *adapt_layer);
61static void cfctrl_resp_func(void);
62static void cfctrl_enum_resp(void);
63
64struct cfcnfg *cfcnfg_create(void)
65{
66 struct cfcnfg *this;
67 struct cfctrl_rsp *resp;
68 /* Initiate this layer */
69 this = kmalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
70 if (!this) {
71 pr_warning("CAIF: %s(): Out of memory\n", __func__);
72 return NULL;
73 }
74 memset(this, 0, sizeof(struct cfcnfg));
75 this->mux = cfmuxl_create();
76 if (!this->mux)
77 goto out_of_mem;
78 this->ctrl = cfctrl_create();
79 if (!this->ctrl)
80 goto out_of_mem;
81 /* Initiate response functions */
82 resp = cfctrl_get_respfuncs(this->ctrl);
83 resp->enum_rsp = cfctrl_enum_resp;
84 resp->linkerror_ind = cfctrl_resp_func;
85 resp->linkdestroy_rsp = cncfg_linkdestroy_rsp;
86 resp->sleep_rsp = cfctrl_resp_func;
87 resp->wake_rsp = cfctrl_resp_func;
88 resp->restart_rsp = cfctrl_resp_func;
89 resp->radioset_rsp = cfctrl_resp_func;
90 resp->linksetup_rsp = cncfg_linkup_rsp;
91 resp->reject_rsp = cncfg_reject_rsp;
92
93 this->last_phyid = 1;
94
95 cfmuxl_set_uplayer(this->mux, this->ctrl, 0);
96 layer_set_dn(this->ctrl, this->mux);
97 layer_set_up(this->ctrl, this);
98 return this;
99out_of_mem:
100 pr_warning("CAIF: %s(): Out of memory\n", __func__);
101 kfree(this->mux);
102 kfree(this->ctrl);
103 kfree(this);
104 return NULL;
105}
106EXPORT_SYMBOL(cfcnfg_create);
107
108void cfcnfg_remove(struct cfcnfg *cfg)
109{
110 if (cfg) {
111 kfree(cfg->mux);
112 kfree(cfg->ctrl);
113 kfree(cfg);
114 }
115}
116
117static void cfctrl_resp_func(void)
118{
119}
120
121static void cfctrl_enum_resp(void)
122{
123}
124
125struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
126 enum cfcnfg_phy_preference phy_pref)
127{
128 u16 i;
129
130 /* Try to match with specified preference */
131 for (i = 1; i < MAX_PHY_LAYERS; i++) {
132 if (cnfg->phy_layers[i].id == i &&
133 cnfg->phy_layers[i].pref == phy_pref &&
134 cnfg->phy_layers[i].frm_layer != NULL) {
135 caif_assert(cnfg->phy_layers != NULL);
136 caif_assert(cnfg->phy_layers[i].id == i);
137 return &cnfg->phy_layers[i].dev_info;
138 }
139 }
140 /* Otherwise just return something */
141 for (i = 1; i < MAX_PHY_LAYERS; i++) {
142 if (cnfg->phy_layers[i].id == i) {
143 caif_assert(cnfg->phy_layers != NULL);
144 caif_assert(cnfg->phy_layers[i].id == i);
145 return &cnfg->phy_layers[i].dev_info;
146 }
147 }
148
149 return NULL;
150}
151
152static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo(struct cfcnfg *cnfg,
153 u8 phyid)
154{
155 int i;
156 /* Try to match with specified preference */
157 for (i = 0; i < MAX_PHY_LAYERS; i++)
158 if (cnfg->phy_layers[i].frm_layer != NULL &&
159 cnfg->phy_layers[i].id == phyid)
160 return &cnfg->phy_layers[i];
161 return NULL;
162}
163
164int cfcnfg_get_named(struct cfcnfg *cnfg, char *name)
165{
166 int i;
167
168 /* Try to match with specified name */
169 for (i = 0; i < MAX_PHY_LAYERS; i++) {
170 if (cnfg->phy_layers[i].frm_layer != NULL
171 && strcmp(cnfg->phy_layers[i].phy_layer->name,
172 name) == 0)
173 return cnfg->phy_layers[i].frm_layer->id;
174 }
175 return 0;
176}
177
178/*
179 * NOTE: What happens on destroy failure:
180 * 1a) No response - Too early
181 * This will not happen because enumerate has already
182 * completed.
183 * 1b) No response - FATAL
184 * Not handled, but this should be a CAIF PROTOCOL ERROR
185 * Modem error, response is really expected - this
186 * case is not really handled.
187 * 2) O/E-bit indicate error
188 * Ignored - this link is destroyed anyway.
189 * 3) Not able to match on request
190 * Not handled, but this should be a CAIF PROTOCOL ERROR
191 * 4) Link-Error - (no response)
192 * Not handled, but this should be a CAIF PROTOCOL ERROR
193 */
194
195int cfcnfg_del_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
196{
197 u8 channel_id = 0;
198 int ret = 0;
199 struct cfcnfg_phyinfo *phyinfo = NULL;
200 u8 phyid = 0;
201
202 caif_assert(adap_layer != NULL);
203 channel_id = adap_layer->id;
204 if (channel_id == 0) {
205 pr_err("CAIF: %s():adap_layer->id is 0\n", __func__);
206 ret = -ENOTCONN;
207 goto end;
208 }
209
210 if (adap_layer->dn == NULL) {
211 pr_err("CAIF: %s():adap_layer->dn is NULL\n", __func__);
212 ret = -ENODEV;
213 goto end;
214 }
215
216 if (adap_layer->dn != NULL)
217 phyid = cfsrvl_getphyid(adap_layer->dn);
218
219 phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
220 if (phyinfo == NULL) {
221 pr_warning("CAIF: %s(): No interface to send disconnect to\n",
222 __func__);
223 ret = -ENODEV;
224 goto end;
225 }
226
227 if (phyinfo->id != phyid
228 || phyinfo->phy_layer->id != phyid
229 || phyinfo->frm_layer->id != phyid) {
230
231 pr_err("CAIF: %s(): Inconsistency in phy registration\n",
232 __func__);
233 ret = -EINVAL;
234 goto end;
235 }
236
237 ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
238
239end:
240 if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 &&
241 phyinfo->phy_layer != NULL &&
242 phyinfo->phy_layer->modemcmd != NULL) {
243 phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
244 _CAIF_MODEMCMD_PHYIF_USELESS);
245 }
246 return ret;
247
248}
249EXPORT_SYMBOL(cfcnfg_del_adapt_layer);
250
251static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid,
252 struct cflayer *client_layer)
253{
254 struct cfcnfg *cnfg = container_obj(layer);
255 struct cflayer *servl;
256
257 /*
258 * 1) Remove service from the MUX layer. The MUX must
259 * guarante that no more payload sent "upwards" (receive)
260 */
261 servl = cfmuxl_remove_uplayer(cnfg->mux, linkid);
262
263 if (servl == NULL) {
264 pr_err("CAIF: %s(): PROTOCOL ERROR "
265 "- Error removing service_layer Linkid(%d)",
266 __func__, linkid);
267 return;
268 }
269 caif_assert(linkid == servl->id);
270
271 if (servl != client_layer && servl->up != client_layer) {
272 pr_err("CAIF: %s(): Error removing service_layer "
273 "Linkid(%d) %p %p",
274 __func__, linkid, (void *) servl,
275 (void *) client_layer);
276 return;
277 }
278
279 /*
280 * 2) DEINIT_RSP must guarantee that no more packets are transmitted
281 * from client (adap_layer) when it returns.
282 */
283
284 if (servl->ctrlcmd == NULL) {
285 pr_err("CAIF: %s(): Error servl->ctrlcmd == NULL", __func__);
286 return;
287 }
288
289 servl->ctrlcmd(servl, CAIF_CTRLCMD_DEINIT_RSP, 0);
290
291 /* 3) It is now safe to destroy the service layer. */
292 cfservl_destroy(servl);
293}
294
295/*
296 * NOTE: What happens on linksetup failure:
297 * 1a) No response - Too early
298 * This will not happen because enumerate is secured
299 * before using interface.
300 * 1b) No response - FATAL
301 * Not handled, but this should be a CAIF PROTOCOL ERROR
302 * Modem error, response is really expected - this case is
303 * not really handled.
304 * 2) O/E-bit indicate error
305 * Handled in cnfg_reject_rsp
306 * 3) Not able to match on request
307 * Not handled, but this should be a CAIF PROTOCOL ERROR
308 * 4) Link-Error - (no response)
309 * Not handled, but this should be a CAIF PROTOCOL ERROR
310 */
311
312int
313cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
314 struct cfctrl_link_param *param,
315 struct cflayer *adap_layer)
316{
317 struct cflayer *frml;
318 if (adap_layer == NULL) {
319 pr_err("CAIF: %s(): adap_layer is zero", __func__);
320 return -EINVAL;
321 }
322 if (adap_layer->receive == NULL) {
323 pr_err("CAIF: %s(): adap_layer->receive is NULL", __func__);
324 return -EINVAL;
325 }
326 if (adap_layer->ctrlcmd == NULL) {
327 pr_err("CAIF: %s(): adap_layer->ctrlcmd == NULL", __func__);
328 return -EINVAL;
329 }
330 frml = cnfg->phy_layers[param->phyid].frm_layer;
331 if (frml == NULL) {
332 pr_err("CAIF: %s(): Specified PHY type does not exist!",
333 __func__);
334 return -ENODEV;
335 }
336 caif_assert(param->phyid == cnfg->phy_layers[param->phyid].id);
337 caif_assert(cnfg->phy_layers[param->phyid].frm_layer->id ==
338 param->phyid);
339 caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id ==
340 param->phyid);
341 /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
342 cfctrl_enum_req(cnfg->ctrl, param->phyid);
343 cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
344 return 0;
345}
346EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
347
348static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid,
349 struct cflayer *adapt_layer)
350{
351 if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
352 adapt_layer->ctrlcmd(adapt_layer,
353 CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
354}
355
356static void
357cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv,
358 u8 phyid, struct cflayer *adapt_layer)
359{
360 struct cfcnfg *cnfg = container_obj(layer);
361 struct cflayer *servicel = NULL;
362 struct cfcnfg_phyinfo *phyinfo;
363 if (adapt_layer == NULL) {
364 pr_err("CAIF: %s(): PROTOCOL ERROR "
365 "- LinkUp Request/Response did not match\n", __func__);
366 return;
367 }
368
369 caif_assert(cnfg != NULL);
370 caif_assert(phyid != 0);
371 phyinfo = &cnfg->phy_layers[phyid];
372 caif_assert(phyinfo != NULL);
373 caif_assert(phyinfo->id == phyid);
374 caif_assert(phyinfo->phy_layer != NULL);
375 caif_assert(phyinfo->phy_layer->id == phyid);
376
377 if (phyinfo != NULL &&
378 phyinfo->phy_ref_count++ == 0 &&
379 phyinfo->phy_layer != NULL &&
380 phyinfo->phy_layer->modemcmd != NULL) {
381 caif_assert(phyinfo->phy_layer->id == phyid);
382 phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
383 _CAIF_MODEMCMD_PHYIF_USEFULL);
384
385 }
386 adapt_layer->id = linkid;
387
388 switch (serv) {
389 case CFCTRL_SRV_VEI:
390 servicel = cfvei_create(linkid, &phyinfo->dev_info);
391 break;
392 case CFCTRL_SRV_DATAGRAM:
393 servicel = cfdgml_create(linkid, &phyinfo->dev_info);
394 break;
395 case CFCTRL_SRV_RFM:
396 servicel = cfrfml_create(linkid, &phyinfo->dev_info);
397 break;
398 case CFCTRL_SRV_UTIL:
399 servicel = cfutill_create(linkid, &phyinfo->dev_info);
400 break;
401 case CFCTRL_SRV_VIDEO:
402 servicel = cfvidl_create(linkid, &phyinfo->dev_info);
403 break;
404 case CFCTRL_SRV_DBG:
405 servicel = cfdbgl_create(linkid, &phyinfo->dev_info);
406 break;
407 default:
408 pr_err("CAIF: %s(): Protocol error. "
409 "Link setup response - unknown channel type\n",
410 __func__);
411 return;
412 }
413 if (!servicel) {
414 pr_warning("CAIF: %s(): Out of memory\n", __func__);
415 return;
416 }
417 layer_set_dn(servicel, cnfg->mux);
418 cfmuxl_set_uplayer(cnfg->mux, servicel, linkid);
419 layer_set_up(servicel, adapt_layer);
420 layer_set_dn(adapt_layer, servicel);
421 servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
422}
423
424void
425cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
426 void *dev, struct cflayer *phy_layer, u16 *phyid,
427 enum cfcnfg_phy_preference pref,
428 bool fcs, bool stx)
429{
430 struct cflayer *frml;
431 struct cflayer *phy_driver = NULL;
432 int i;
433
434
435 if (cnfg->phy_layers[cnfg->last_phyid].frm_layer == NULL) {
436 *phyid = cnfg->last_phyid;
437
438 /* range: * 1..(MAX_PHY_LAYERS-1) */
439 cnfg->last_phyid =
440 (cnfg->last_phyid % (MAX_PHY_LAYERS - 1)) + 1;
441 } else {
442 *phyid = 0;
443 for (i = 1; i < MAX_PHY_LAYERS; i++) {
444 if (cnfg->phy_layers[i].frm_layer == NULL) {
445 *phyid = i;
446 break;
447 }
448 }
449 }
450 if (*phyid == 0) {
451 pr_err("CAIF: %s(): No Available PHY ID\n", __func__);
452 return;
453 }
454
455 switch (phy_type) {
456 case CFPHYTYPE_FRAG:
457 phy_driver =
458 cfserl_create(CFPHYTYPE_FRAG, *phyid, stx);
459 if (!phy_driver) {
460 pr_warning("CAIF: %s(): Out of memory\n", __func__);
461 return;
462 }
463
464 break;
465 case CFPHYTYPE_CAIF:
466 phy_driver = NULL;
467 break;
468 default:
469 pr_err("CAIF: %s(): %d", __func__, phy_type);
470 return;
471 break;
472 }
473
474 phy_layer->id = *phyid;
475 cnfg->phy_layers[*phyid].pref = pref;
476 cnfg->phy_layers[*phyid].id = *phyid;
477 cnfg->phy_layers[*phyid].dev_info.id = *phyid;
478 cnfg->phy_layers[*phyid].dev_info.dev = dev;
479 cnfg->phy_layers[*phyid].phy_layer = phy_layer;
480 cnfg->phy_layers[*phyid].phy_ref_count = 0;
481 phy_layer->type = phy_type;
482 frml = cffrml_create(*phyid, fcs);
483 if (!frml) {
484 pr_warning("CAIF: %s(): Out of memory\n", __func__);
485 return;
486 }
487 cnfg->phy_layers[*phyid].frm_layer = frml;
488 cfmuxl_set_dnlayer(cnfg->mux, frml, *phyid);
489 layer_set_up(frml, cnfg->mux);
490
491 if (phy_driver != NULL) {
492 phy_driver->id = *phyid;
493 layer_set_dn(frml, phy_driver);
494 layer_set_up(phy_driver, frml);
495 layer_set_dn(phy_driver, phy_layer);
496 layer_set_up(phy_layer, phy_driver);
497 } else {
498 layer_set_dn(frml, phy_layer);
499 layer_set_up(phy_layer, frml);
500 }
501}
502EXPORT_SYMBOL(cfcnfg_add_phy_layer);
503
504int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
505{
506 struct cflayer *frml, *frml_dn;
507 u16 phyid;
508 phyid = phy_layer->id;
509 caif_assert(phyid == cnfg->phy_layers[phyid].id);
510 caif_assert(phy_layer == cnfg->phy_layers[phyid].phy_layer);
511 caif_assert(phy_layer->id == phyid);
512 caif_assert(cnfg->phy_layers[phyid].frm_layer->id == phyid);
513
514 memset(&cnfg->phy_layers[phy_layer->id], 0,
515 sizeof(struct cfcnfg_phyinfo));
516 frml = cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id);
517 frml_dn = frml->dn;
518 cffrml_set_uplayer(frml, NULL);
519 cffrml_set_dnlayer(frml, NULL);
520 kfree(frml);
521
522 if (phy_layer != frml_dn) {
523 layer_set_up(frml_dn, NULL);
524 layer_set_dn(frml_dn, NULL);
525 kfree(frml_dn);
526 }
527 layer_set_up(phy_layer, NULL);
528 return 0;
529}
530EXPORT_SYMBOL(cfcnfg_del_phy_layer);
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
new file mode 100644
index 000000000000..11f80140f3cb
--- /dev/null
+++ b/net/caif/cfctrl.c
@@ -0,0 +1,664 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/spinlock.h>
9#include <linux/slab.h>
10#include <net/caif/caif_layer.h>
11#include <net/caif/cfpkt.h>
12#include <net/caif/cfctrl.h>
13
14#define container_obj(layr) container_of(layr, struct cfctrl, serv.layer)
15#define UTILITY_NAME_LENGTH 16
16#define CFPKT_CTRL_PKT_LEN 20
17
18
19#ifdef CAIF_NO_LOOP
20static int handle_loop(struct cfctrl *ctrl,
21 int cmd, struct cfpkt *pkt){
22 return CAIF_FAILURE;
23}
24#else
25static int handle_loop(struct cfctrl *ctrl,
26 int cmd, struct cfpkt *pkt);
27#endif
28static int cfctrl_recv(struct cflayer *layr, struct cfpkt *pkt);
29static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
30 int phyid);
31
32
33struct cflayer *cfctrl_create(void)
34{
35 struct cfctrl *this =
36 kmalloc(sizeof(struct cfctrl), GFP_ATOMIC);
37 if (!this) {
38 pr_warning("CAIF: %s(): Out of memory\n", __func__);
39 return NULL;
40 }
41 caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
42 memset(this, 0, sizeof(*this));
43 spin_lock_init(&this->info_list_lock);
44 atomic_set(&this->req_seq_no, 1);
45 atomic_set(&this->rsp_seq_no, 1);
46 this->serv.dev_info.id = 0xff;
47 this->serv.layer.id = 0;
48 this->serv.layer.receive = cfctrl_recv;
49 sprintf(this->serv.layer.name, "ctrl");
50 this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
51 spin_lock_init(&this->loop_linkid_lock);
52 this->loop_linkid = 1;
53 return &this->serv.layer;
54}
55
56static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2)
57{
58 bool eq =
59 p1->linktype == p2->linktype &&
60 p1->priority == p2->priority &&
61 p1->phyid == p2->phyid &&
62 p1->endpoint == p2->endpoint && p1->chtype == p2->chtype;
63
64 if (!eq)
65 return false;
66
67 switch (p1->linktype) {
68 case CFCTRL_SRV_VEI:
69 return true;
70 case CFCTRL_SRV_DATAGRAM:
71 return p1->u.datagram.connid == p2->u.datagram.connid;
72 case CFCTRL_SRV_RFM:
73 return
74 p1->u.rfm.connid == p2->u.rfm.connid &&
75 strcmp(p1->u.rfm.volume, p2->u.rfm.volume) == 0;
76 case CFCTRL_SRV_UTIL:
77 return
78 p1->u.utility.fifosize_kb == p2->u.utility.fifosize_kb
79 && p1->u.utility.fifosize_bufs ==
80 p2->u.utility.fifosize_bufs
81 && strcmp(p1->u.utility.name, p2->u.utility.name) == 0
82 && p1->u.utility.paramlen == p2->u.utility.paramlen
83 && memcmp(p1->u.utility.params, p2->u.utility.params,
84 p1->u.utility.paramlen) == 0;
85
86 case CFCTRL_SRV_VIDEO:
87 return p1->u.video.connid == p2->u.video.connid;
88 case CFCTRL_SRV_DBG:
89 return true;
90 case CFCTRL_SRV_DECM:
91 return false;
92 default:
93 return false;
94 }
95 return false;
96}
97
98bool cfctrl_req_eq(struct cfctrl_request_info *r1,
99 struct cfctrl_request_info *r2)
100{
101 if (r1->cmd != r2->cmd)
102 return false;
103 if (r1->cmd == CFCTRL_CMD_LINK_SETUP)
104 return param_eq(&r1->param, &r2->param);
105 else
106 return r1->channel_id == r2->channel_id;
107}
108
109/* Insert request at the end */
110void cfctrl_insert_req(struct cfctrl *ctrl,
111 struct cfctrl_request_info *req)
112{
113 struct cfctrl_request_info *p;
114 spin_lock(&ctrl->info_list_lock);
115 req->next = NULL;
116 atomic_inc(&ctrl->req_seq_no);
117 req->sequence_no = atomic_read(&ctrl->req_seq_no);
118 if (ctrl->first_req == NULL) {
119 ctrl->first_req = req;
120 spin_unlock(&ctrl->info_list_lock);
121 return;
122 }
123 p = ctrl->first_req;
124 while (p->next != NULL)
125 p = p->next;
126 p->next = req;
127 spin_unlock(&ctrl->info_list_lock);
128}
129
130static void cfctrl_insert_req2(struct cfctrl *ctrl, enum cfctrl_cmd cmd,
131 u8 linkid, struct cflayer *user_layer)
132{
133 struct cfctrl_request_info *req = kmalloc(sizeof(*req), GFP_KERNEL);
134 if (!req) {
135 pr_warning("CAIF: %s(): Out of memory\n", __func__);
136 return;
137 }
138 req->client_layer = user_layer;
139 req->cmd = cmd;
140 req->channel_id = linkid;
141 cfctrl_insert_req(ctrl, req);
142}
143
144/* Compare and remove request */
145struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
146 struct cfctrl_request_info *req)
147{
148 struct cfctrl_request_info *p;
149 struct cfctrl_request_info *ret;
150
151 spin_lock(&ctrl->info_list_lock);
152 if (ctrl->first_req == NULL) {
153 spin_unlock(&ctrl->info_list_lock);
154 return NULL;
155 }
156
157 if (cfctrl_req_eq(req, ctrl->first_req)) {
158 ret = ctrl->first_req;
159 caif_assert(ctrl->first_req);
160 atomic_set(&ctrl->rsp_seq_no,
161 ctrl->first_req->sequence_no);
162 ctrl->first_req = ctrl->first_req->next;
163 spin_unlock(&ctrl->info_list_lock);
164 return ret;
165 }
166
167 p = ctrl->first_req;
168
169 while (p->next != NULL) {
170 if (cfctrl_req_eq(req, p->next)) {
171 pr_warning("CAIF: %s(): Requests are not "
172 "received in order\n",
173 __func__);
174 ret = p->next;
175 atomic_set(&ctrl->rsp_seq_no,
176 p->next->sequence_no);
177 p->next = p->next->next;
178 spin_unlock(&ctrl->info_list_lock);
179 return ret;
180 }
181 p = p->next;
182 }
183 spin_unlock(&ctrl->info_list_lock);
184
185 pr_warning("CAIF: %s(): Request does not match\n",
186 __func__);
187 return NULL;
188}
189
190struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer)
191{
192 struct cfctrl *this = container_obj(layer);
193 return &this->res;
194}
195
196void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn)
197{
198 this->dn = dn;
199}
200
201void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up)
202{
203 this->up = up;
204}
205
206static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl)
207{
208 info->hdr_len = 0;
209 info->channel_id = cfctrl->serv.layer.id;
210 info->dev_info = &cfctrl->serv.dev_info;
211}
212
213void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
214{
215 struct cfctrl *cfctrl = container_obj(layer);
216 int ret;
217 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
218 if (!pkt) {
219 pr_warning("CAIF: %s(): Out of memory\n", __func__);
220 return;
221 }
222 caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
223 init_info(cfpkt_info(pkt), cfctrl);
224 cfpkt_info(pkt)->dev_info->id = physlinkid;
225 cfctrl->serv.dev_info.id = physlinkid;
226 cfpkt_addbdy(pkt, CFCTRL_CMD_ENUM);
227 cfpkt_addbdy(pkt, physlinkid);
228 ret =
229 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
230 if (ret < 0) {
231 pr_err("CAIF: %s(): Could not transmit enum message\n",
232 __func__);
233 cfpkt_destroy(pkt);
234 }
235}
236
237void cfctrl_linkup_request(struct cflayer *layer,
238 struct cfctrl_link_param *param,
239 struct cflayer *user_layer)
240{
241 struct cfctrl *cfctrl = container_obj(layer);
242 u32 tmp32;
243 u16 tmp16;
244 u8 tmp8;
245 struct cfctrl_request_info *req;
246 int ret;
247 char utility_name[16];
248 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
249 if (!pkt) {
250 pr_warning("CAIF: %s(): Out of memory\n", __func__);
251 return;
252 }
253 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
254 cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype);
255 cfpkt_addbdy(pkt, (param->priority << 3) + param->phyid);
256 cfpkt_addbdy(pkt, param->endpoint & 0x03);
257
258 switch (param->linktype) {
259 case CFCTRL_SRV_VEI:
260 break;
261 case CFCTRL_SRV_VIDEO:
262 cfpkt_addbdy(pkt, (u8) param->u.video.connid);
263 break;
264 case CFCTRL_SRV_DBG:
265 break;
266 case CFCTRL_SRV_DATAGRAM:
267 tmp32 = cpu_to_le32(param->u.datagram.connid);
268 cfpkt_add_body(pkt, &tmp32, 4);
269 break;
270 case CFCTRL_SRV_RFM:
271 /* Construct a frame, convert DatagramConnectionID to network
272 * format long and copy it out...
273 */
274 tmp32 = cpu_to_le32(param->u.rfm.connid);
275 cfpkt_add_body(pkt, &tmp32, 4);
276 /* Add volume name, including zero termination... */
277 cfpkt_add_body(pkt, param->u.rfm.volume,
278 strlen(param->u.rfm.volume) + 1);
279 break;
280 case CFCTRL_SRV_UTIL:
281 tmp16 = cpu_to_le16(param->u.utility.fifosize_kb);
282 cfpkt_add_body(pkt, &tmp16, 2);
283 tmp16 = cpu_to_le16(param->u.utility.fifosize_bufs);
284 cfpkt_add_body(pkt, &tmp16, 2);
285 memset(utility_name, 0, sizeof(utility_name));
286 strncpy(utility_name, param->u.utility.name,
287 UTILITY_NAME_LENGTH - 1);
288 cfpkt_add_body(pkt, utility_name, UTILITY_NAME_LENGTH);
289 tmp8 = param->u.utility.paramlen;
290 cfpkt_add_body(pkt, &tmp8, 1);
291 cfpkt_add_body(pkt, param->u.utility.params,
292 param->u.utility.paramlen);
293 break;
294 default:
295 pr_warning("CAIF: %s():Request setup of bad link type = %d\n",
296 __func__, param->linktype);
297 }
298 req = kmalloc(sizeof(*req), GFP_KERNEL);
299 if (!req) {
300 pr_warning("CAIF: %s(): Out of memory\n", __func__);
301 return;
302 }
303 memset(req, 0, sizeof(*req));
304 req->client_layer = user_layer;
305 req->cmd = CFCTRL_CMD_LINK_SETUP;
306 req->param = *param;
307 cfctrl_insert_req(cfctrl, req);
308 init_info(cfpkt_info(pkt), cfctrl);
309 cfpkt_info(pkt)->dev_info->id = param->phyid;
310 ret =
311 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
312 if (ret < 0) {
313 pr_err("CAIF: %s(): Could not transmit linksetup request\n",
314 __func__);
315 cfpkt_destroy(pkt);
316 }
317}
318
319int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
320 struct cflayer *client)
321{
322 int ret;
323 struct cfctrl *cfctrl = container_obj(layer);
324 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
325 if (!pkt) {
326 pr_warning("CAIF: %s(): Out of memory\n", __func__);
327 return -ENOMEM;
328 }
329 cfctrl_insert_req2(cfctrl, CFCTRL_CMD_LINK_DESTROY, channelid, client);
330 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY);
331 cfpkt_addbdy(pkt, channelid);
332 init_info(cfpkt_info(pkt), cfctrl);
333 ret =
334 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
335 if (ret < 0) {
336 pr_err("CAIF: %s(): Could not transmit link-down request\n",
337 __func__);
338 cfpkt_destroy(pkt);
339 }
340 return ret;
341}
342
343void cfctrl_sleep_req(struct cflayer *layer)
344{
345 int ret;
346 struct cfctrl *cfctrl = container_obj(layer);
347 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
348 if (!pkt) {
349 pr_warning("CAIF: %s(): Out of memory\n", __func__);
350 return;
351 }
352 cfpkt_addbdy(pkt, CFCTRL_CMD_SLEEP);
353 init_info(cfpkt_info(pkt), cfctrl);
354 ret =
355 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
356 if (ret < 0)
357 cfpkt_destroy(pkt);
358}
359
360void cfctrl_wake_req(struct cflayer *layer)
361{
362 int ret;
363 struct cfctrl *cfctrl = container_obj(layer);
364 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
365 if (!pkt) {
366 pr_warning("CAIF: %s(): Out of memory\n", __func__);
367 return;
368 }
369 cfpkt_addbdy(pkt, CFCTRL_CMD_WAKE);
370 init_info(cfpkt_info(pkt), cfctrl);
371 ret =
372 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
373 if (ret < 0)
374 cfpkt_destroy(pkt);
375}
376
377void cfctrl_getstartreason_req(struct cflayer *layer)
378{
379 int ret;
380 struct cfctrl *cfctrl = container_obj(layer);
381 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
382 if (!pkt) {
383 pr_warning("CAIF: %s(): Out of memory\n", __func__);
384 return;
385 }
386 cfpkt_addbdy(pkt, CFCTRL_CMD_START_REASON);
387 init_info(cfpkt_info(pkt), cfctrl);
388 ret =
389 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
390 if (ret < 0)
391 cfpkt_destroy(pkt);
392}
393
394
395static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
396{
397 u8 cmdrsp;
398 u8 cmd;
399 int ret = -1;
400 u16 tmp16;
401 u8 len;
402 u8 param[255];
403 u8 linkid;
404 struct cfctrl *cfctrl = container_obj(layer);
405 struct cfctrl_request_info rsp, *req;
406
407
408 cfpkt_extr_head(pkt, &cmdrsp, 1);
409 cmd = cmdrsp & CFCTRL_CMD_MASK;
410 if (cmd != CFCTRL_CMD_LINK_ERR
411 && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) {
412 if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) {
413 pr_info("CAIF: %s() CAIF Protocol error:"
414 "Response bit not set\n", __func__);
415 goto error;
416 }
417 }
418
419 switch (cmd) {
420 case CFCTRL_CMD_LINK_SETUP:
421 {
422 enum cfctrl_srv serv;
423 enum cfctrl_srv servtype;
424 u8 endpoint;
425 u8 physlinkid;
426 u8 prio;
427 u8 tmp;
428 u32 tmp32;
429 u8 *cp;
430 int i;
431 struct cfctrl_link_param linkparam;
432 memset(&linkparam, 0, sizeof(linkparam));
433
434 cfpkt_extr_head(pkt, &tmp, 1);
435
436 serv = tmp & CFCTRL_SRV_MASK;
437 linkparam.linktype = serv;
438
439 servtype = tmp >> 4;
440 linkparam.chtype = servtype;
441
442 cfpkt_extr_head(pkt, &tmp, 1);
443 physlinkid = tmp & 0x07;
444 prio = tmp >> 3;
445
446 linkparam.priority = prio;
447 linkparam.phyid = physlinkid;
448 cfpkt_extr_head(pkt, &endpoint, 1);
449 linkparam.endpoint = endpoint & 0x03;
450
451 switch (serv) {
452 case CFCTRL_SRV_VEI:
453 case CFCTRL_SRV_DBG:
454 /* Link ID */
455 cfpkt_extr_head(pkt, &linkid, 1);
456 break;
457 case CFCTRL_SRV_VIDEO:
458 cfpkt_extr_head(pkt, &tmp, 1);
459 linkparam.u.video.connid = tmp;
460 /* Link ID */
461 cfpkt_extr_head(pkt, &linkid, 1);
462 break;
463
464 case CFCTRL_SRV_DATAGRAM:
465 cfpkt_extr_head(pkt, &tmp32, 4);
466 linkparam.u.datagram.connid =
467 le32_to_cpu(tmp32);
468 /* Link ID */
469 cfpkt_extr_head(pkt, &linkid, 1);
470 break;
471 case CFCTRL_SRV_RFM:
472 /* Construct a frame, convert
473 * DatagramConnectionID
474 * to network format long and copy it out...
475 */
476 cfpkt_extr_head(pkt, &tmp32, 4);
477 linkparam.u.rfm.connid =
478 le32_to_cpu(tmp32);
479 cp = (u8 *) linkparam.u.rfm.volume;
480 for (cfpkt_extr_head(pkt, &tmp, 1);
481 cfpkt_more(pkt) && tmp != '\0';
482 cfpkt_extr_head(pkt, &tmp, 1))
483 *cp++ = tmp;
484 *cp = '\0';
485
486 /* Link ID */
487 cfpkt_extr_head(pkt, &linkid, 1);
488
489 break;
490 case CFCTRL_SRV_UTIL:
491 /* Construct a frame, convert
492 * DatagramConnectionID
493 * to network format long and copy it out...
494 */
495 /* Fifosize KB */
496 cfpkt_extr_head(pkt, &tmp16, 2);
497 linkparam.u.utility.fifosize_kb =
498 le16_to_cpu(tmp16);
499 /* Fifosize bufs */
500 cfpkt_extr_head(pkt, &tmp16, 2);
501 linkparam.u.utility.fifosize_bufs =
502 le16_to_cpu(tmp16);
503 /* name */
504 cp = (u8 *) linkparam.u.utility.name;
505 caif_assert(sizeof(linkparam.u.utility.name)
506 >= UTILITY_NAME_LENGTH);
507 for (i = 0;
508 i < UTILITY_NAME_LENGTH
509 && cfpkt_more(pkt); i++) {
510 cfpkt_extr_head(pkt, &tmp, 1);
511 *cp++ = tmp;
512 }
513 /* Length */
514 cfpkt_extr_head(pkt, &len, 1);
515 linkparam.u.utility.paramlen = len;
516 /* Param Data */
517 cp = linkparam.u.utility.params;
518 while (cfpkt_more(pkt) && len--) {
519 cfpkt_extr_head(pkt, &tmp, 1);
520 *cp++ = tmp;
521 }
522 /* Link ID */
523 cfpkt_extr_head(pkt, &linkid, 1);
524 /* Length */
525 cfpkt_extr_head(pkt, &len, 1);
526 /* Param Data */
527 cfpkt_extr_head(pkt, &param, len);
528 break;
529 default:
530 pr_warning("CAIF: %s(): Request setup "
531 "- invalid link type (%d)",
532 __func__, serv);
533 goto error;
534 }
535
536 rsp.cmd = cmd;
537 rsp.param = linkparam;
538 req = cfctrl_remove_req(cfctrl, &rsp);
539
540 if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) ||
541 cfpkt_erroneous(pkt)) {
542 pr_err("CAIF: %s(): Invalid O/E bit or parse "
543 "error on CAIF control channel",
544 __func__);
545 cfctrl->res.reject_rsp(cfctrl->serv.layer.up,
546 0,
547 req ? req->client_layer
548 : NULL);
549 } else {
550 cfctrl->res.linksetup_rsp(cfctrl->serv.
551 layer.up, linkid,
552 serv, physlinkid,
553 req ? req->
554 client_layer : NULL);
555 }
556
557 if (req != NULL)
558 kfree(req);
559 }
560 break;
561 case CFCTRL_CMD_LINK_DESTROY:
562 cfpkt_extr_head(pkt, &linkid, 1);
563 rsp.cmd = cmd;
564 rsp.channel_id = linkid;
565 req = cfctrl_remove_req(cfctrl, &rsp);
566 cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid,
567 req ? req->client_layer : NULL);
568 if (req != NULL)
569 kfree(req);
570 break;
571 case CFCTRL_CMD_LINK_ERR:
572 pr_err("CAIF: %s(): Frame Error Indication received\n",
573 __func__);
574 cfctrl->res.linkerror_ind();
575 break;
576 case CFCTRL_CMD_ENUM:
577 cfctrl->res.enum_rsp();
578 break;
579 case CFCTRL_CMD_SLEEP:
580 cfctrl->res.sleep_rsp();
581 break;
582 case CFCTRL_CMD_WAKE:
583 cfctrl->res.wake_rsp();
584 break;
585 case CFCTRL_CMD_LINK_RECONF:
586 cfctrl->res.restart_rsp();
587 break;
588 case CFCTRL_CMD_RADIO_SET:
589 cfctrl->res.radioset_rsp();
590 break;
591 default:
592 pr_err("CAIF: %s(): Unrecognized Control Frame\n", __func__);
593 goto error;
594 break;
595 }
596 ret = 0;
597error:
598 cfpkt_destroy(pkt);
599 return ret;
600}
601
602static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
603 int phyid)
604{
605 struct cfctrl *this = container_obj(layr);
606 switch (ctrl) {
607 case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
608 case CAIF_CTRLCMD_FLOW_OFF_IND:
609 spin_lock(&this->info_list_lock);
610 if (this->first_req != NULL) {
611 pr_warning("CAIF: %s(): Received flow off in "
612 "control layer", __func__);
613 }
614 spin_unlock(&this->info_list_lock);
615 break;
616 default:
617 break;
618 }
619}
620
621#ifndef CAIF_NO_LOOP
622static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt)
623{
624 static int last_linkid;
625 u8 linkid, linktype, tmp;
626 switch (cmd) {
627 case CFCTRL_CMD_LINK_SETUP:
628 spin_lock(&ctrl->loop_linkid_lock);
629 for (linkid = last_linkid + 1; linkid < 255; linkid++)
630 if (!ctrl->loop_linkused[linkid])
631 goto found;
632 for (linkid = last_linkid - 1; linkid > 0; linkid--)
633 if (!ctrl->loop_linkused[linkid])
634 goto found;
635 spin_unlock(&ctrl->loop_linkid_lock);
636 return -EINVAL;
637found:
638 if (!ctrl->loop_linkused[linkid])
639 ctrl->loop_linkused[linkid] = 1;
640
641 last_linkid = linkid;
642
643 cfpkt_add_trail(pkt, &linkid, 1);
644 spin_unlock(&ctrl->loop_linkid_lock);
645 cfpkt_peek_head(pkt, &linktype, 1);
646 if (linktype == CFCTRL_SRV_UTIL) {
647 tmp = 0x01;
648 cfpkt_add_trail(pkt, &tmp, 1);
649 cfpkt_add_trail(pkt, &tmp, 1);
650 }
651 break;
652
653 case CFCTRL_CMD_LINK_DESTROY:
654 spin_lock(&ctrl->loop_linkid_lock);
655 cfpkt_peek_head(pkt, &linkid, 1);
656 ctrl->loop_linkused[linkid] = 0;
657 spin_unlock(&ctrl->loop_linkid_lock);
658 break;
659 default:
660 break;
661 }
662 return CAIF_SUCCESS;
663}
664#endif
diff --git a/net/caif/cfdbgl.c b/net/caif/cfdbgl.c
new file mode 100644
index 000000000000..ab6b6dc34cf8
--- /dev/null
+++ b/net/caif/cfdbgl.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/slab.h>
9#include <net/caif/caif_layer.h>
10#include <net/caif/cfsrvl.h>
11#include <net/caif/cfpkt.h>
12
13static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt);
14static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt);
15
16struct cflayer *cfdbgl_create(u8 channel_id, struct dev_info *dev_info)
17{
18 struct cfsrvl *dbg = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
19 if (!dbg) {
20 pr_warning("CAIF: %s(): Out of memory\n", __func__);
21 return NULL;
22 }
23 caif_assert(offsetof(struct cfsrvl, layer) == 0);
24 memset(dbg, 0, sizeof(struct cfsrvl));
25 cfsrvl_init(dbg, channel_id, dev_info);
26 dbg->layer.receive = cfdbgl_receive;
27 dbg->layer.transmit = cfdbgl_transmit;
28 snprintf(dbg->layer.name, CAIF_LAYER_NAME_SZ - 1, "dbg%d", channel_id);
29 return &dbg->layer;
30}
31
32static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt)
33{
34 return layr->up->receive(layr->up, pkt);
35}
36
37static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt)
38{
39 return layr->dn->transmit(layr->dn, pkt);
40}
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c
new file mode 100644
index 000000000000..53194840ecb6
--- /dev/null
+++ b/net/caif/cfdgml.c
@@ -0,0 +1,108 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/spinlock.h>
9#include <linux/slab.h>
10#include <net/caif/caif_layer.h>
11#include <net/caif/cfsrvl.h>
12#include <net/caif/cfpkt.h>
13
14#define container_obj(layr) ((struct cfsrvl *) layr)
15
16#define DGM_CMD_BIT 0x80
17#define DGM_FLOW_OFF 0x81
18#define DGM_FLOW_ON 0x80
19#define DGM_CTRL_PKT_SIZE 1
20
21static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt);
22static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt);
23
24struct cflayer *cfdgml_create(u8 channel_id, struct dev_info *dev_info)
25{
26 struct cfsrvl *dgm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
27 if (!dgm) {
28 pr_warning("CAIF: %s(): Out of memory\n", __func__);
29 return NULL;
30 }
31 caif_assert(offsetof(struct cfsrvl, layer) == 0);
32 memset(dgm, 0, sizeof(struct cfsrvl));
33 cfsrvl_init(dgm, channel_id, dev_info);
34 dgm->layer.receive = cfdgml_receive;
35 dgm->layer.transmit = cfdgml_transmit;
36 snprintf(dgm->layer.name, CAIF_LAYER_NAME_SZ - 1, "dgm%d", channel_id);
37 dgm->layer.name[CAIF_LAYER_NAME_SZ - 1] = '\0';
38 return &dgm->layer;
39}
40
41static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt)
42{
43 u8 cmd = -1;
44 u8 dgmhdr[3];
45 int ret;
46 caif_assert(layr->up != NULL);
47 caif_assert(layr->receive != NULL);
48 caif_assert(layr->ctrlcmd != NULL);
49
50 if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
51 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
52 cfpkt_destroy(pkt);
53 return -EPROTO;
54 }
55
56 if ((cmd & DGM_CMD_BIT) == 0) {
57 if (cfpkt_extr_head(pkt, &dgmhdr, 3) < 0) {
58 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
59 cfpkt_destroy(pkt);
60 return -EPROTO;
61 }
62 ret = layr->up->receive(layr->up, pkt);
63 return ret;
64 }
65
66 switch (cmd) {
67 case DGM_FLOW_OFF: /* FLOW OFF */
68 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0);
69 cfpkt_destroy(pkt);
70 return 0;
71 case DGM_FLOW_ON: /* FLOW ON */
72 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0);
73 cfpkt_destroy(pkt);
74 return 0;
75 default:
76 cfpkt_destroy(pkt);
77 pr_info("CAIF: %s(): Unknown datagram control %d (0x%x)\n",
78 __func__, cmd, cmd);
79 return -EPROTO;
80 }
81}
82
83static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
84{
85 u32 zero = 0;
86 struct caif_payload_info *info;
87 struct cfsrvl *service = container_obj(layr);
88 int ret;
89 if (!cfsrvl_ready(service, &ret))
90 return ret;
91
92 cfpkt_add_head(pkt, &zero, 4);
93
94 /* Add info for MUX-layer to route the packet out. */
95 info = cfpkt_info(pkt);
96 info->channel_id = service->layer.id;
97 /* To optimize alignment, we add up the size of CAIF header
98 * before payload.
99 */
100 info->hdr_len = 4;
101 info->dev_info = &service->dev_info;
102 ret = layr->dn->transmit(layr->dn, pkt);
103 if (ret < 0) {
104 u32 tmp32;
105 cfpkt_extr_head(pkt, &tmp32, 4);
106 }
107 return ret;
108}
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
new file mode 100644
index 000000000000..e86a4ca3b217
--- /dev/null
+++ b/net/caif/cffrml.c
@@ -0,0 +1,151 @@
1/*
2 * CAIF Framing Layer.
3 *
4 * Copyright (C) ST-Ericsson AB 2010
5 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
6 * License terms: GNU General Public License (GPL) version 2
7 */
8
9#include <linux/stddef.h>
10#include <linux/spinlock.h>
11#include <linux/slab.h>
12#include <linux/crc-ccitt.h>
13#include <net/caif/caif_layer.h>
14#include <net/caif/cfpkt.h>
15#include <net/caif/cffrml.h>
16
17#define container_obj(layr) container_of(layr, struct cffrml, layer)
18
19struct cffrml {
20 struct cflayer layer;
21 bool dofcs; /* !< FCS active */
22};
23
24static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
25static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
26static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
27 int phyid);
28
29static u32 cffrml_rcv_error;
30static u32 cffrml_rcv_checsum_error;
31struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
32{
33 struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
34 if (!this) {
35 pr_warning("CAIF: %s(): Out of memory\n", __func__);
36 return NULL;
37 }
38 caif_assert(offsetof(struct cffrml, layer) == 0);
39
40 memset(this, 0, sizeof(struct cflayer));
41 this->layer.receive = cffrml_receive;
42 this->layer.transmit = cffrml_transmit;
43 this->layer.ctrlcmd = cffrml_ctrlcmd;
44 snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid);
45 this->dofcs = use_fcs;
46 this->layer.id = phyid;
47 return (struct cflayer *) this;
48}
49
50void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
51{
52 this->up = up;
53}
54
55void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn)
56{
57 this->dn = dn;
58}
59
60static u16 cffrml_checksum(u16 chks, void *buf, u16 len)
61{
62 /* FIXME: FCS should be moved to glue in order to use OS-Specific
63 * solutions
64 */
65 return crc_ccitt(chks, buf, len);
66}
67
68static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
69{
70 u16 tmp;
71 u16 len;
72 u16 hdrchks;
73 u16 pktchks;
74 struct cffrml *this;
75 this = container_obj(layr);
76
77 cfpkt_extr_head(pkt, &tmp, 2);
78 len = le16_to_cpu(tmp);
79
80 /* Subtract for FCS on length if FCS is not used. */
81 if (!this->dofcs)
82 len -= 2;
83
84 if (cfpkt_setlen(pkt, len) < 0) {
85 ++cffrml_rcv_error;
86 pr_err("CAIF: %s():Framing length error (%d)\n", __func__, len);
87 cfpkt_destroy(pkt);
88 return -EPROTO;
89 }
90 /*
91 * Don't do extract if FCS is false, rather do setlen - then we don't
92 * get a cache-miss.
93 */
94 if (this->dofcs) {
95 cfpkt_extr_trail(pkt, &tmp, 2);
96 hdrchks = le16_to_cpu(tmp);
97 pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
98 if (pktchks != hdrchks) {
99 cfpkt_add_trail(pkt, &tmp, 2);
100 ++cffrml_rcv_error;
101 ++cffrml_rcv_checsum_error;
102 pr_info("CAIF: %s(): Frame checksum error "
103 "(0x%x != 0x%x)\n", __func__, hdrchks, pktchks);
104 return -EILSEQ;
105 }
106 }
107 if (cfpkt_erroneous(pkt)) {
108 ++cffrml_rcv_error;
109 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
110 cfpkt_destroy(pkt);
111 return -EPROTO;
112 }
113 return layr->up->receive(layr->up, pkt);
114}
115
116static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
117{
118 int tmp;
119 u16 chks;
120 u16 len;
121 int ret;
122 struct cffrml *this = container_obj(layr);
123 if (this->dofcs) {
124 chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
125 tmp = cpu_to_le16(chks);
126 cfpkt_add_trail(pkt, &tmp, 2);
127 } else {
128 cfpkt_pad_trail(pkt, 2);
129 }
130 len = cfpkt_getlen(pkt);
131 tmp = cpu_to_le16(len);
132 cfpkt_add_head(pkt, &tmp, 2);
133 cfpkt_info(pkt)->hdr_len += 2;
134 if (cfpkt_erroneous(pkt)) {
135 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
136 return -EPROTO;
137 }
138 ret = layr->dn->transmit(layr->dn, pkt);
139 if (ret < 0) {
140 /* Remove header on faulty packet. */
141 cfpkt_extr_head(pkt, &tmp, 2);
142 }
143 return ret;
144}
145
146static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
147 int phyid)
148{
149 if (layr->up->ctrlcmd)
150 layr->up->ctrlcmd(layr->up, ctrl, layr->id);
151}
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c
new file mode 100644
index 000000000000..6fb9f9e96cf8
--- /dev/null
+++ b/net/caif/cfmuxl.c
@@ -0,0 +1,246 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6#include <linux/stddef.h>
7#include <linux/spinlock.h>
8#include <linux/slab.h>
9#include <net/caif/cfpkt.h>
10#include <net/caif/cfmuxl.h>
11#include <net/caif/cfsrvl.h>
12#include <net/caif/cffrml.h>
13
14#define container_obj(layr) container_of(layr, struct cfmuxl, layer)
15
16#define CAIF_CTRL_CHANNEL 0
17#define UP_CACHE_SIZE 8
18#define DN_CACHE_SIZE 8
19
20struct cfmuxl {
21 struct cflayer layer;
22 struct list_head srvl_list;
23 struct list_head frml_list;
24 struct cflayer *up_cache[UP_CACHE_SIZE];
25 struct cflayer *dn_cache[DN_CACHE_SIZE];
26 /*
27 * Set when inserting or removing downwards layers.
28 */
29 spinlock_t transmit_lock;
30
31 /*
32 * Set when inserting or removing upwards layers.
33 */
34 spinlock_t receive_lock;
35
36};
37
38static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt);
39static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt);
40static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
41 int phyid);
42static struct cflayer *get_up(struct cfmuxl *muxl, u16 id);
43
44struct cflayer *cfmuxl_create(void)
45{
46 struct cfmuxl *this = kmalloc(sizeof(struct cfmuxl), GFP_ATOMIC);
47 if (!this)
48 return NULL;
49 memset(this, 0, sizeof(*this));
50 this->layer.receive = cfmuxl_receive;
51 this->layer.transmit = cfmuxl_transmit;
52 this->layer.ctrlcmd = cfmuxl_ctrlcmd;
53 INIT_LIST_HEAD(&this->srvl_list);
54 INIT_LIST_HEAD(&this->frml_list);
55 spin_lock_init(&this->transmit_lock);
56 spin_lock_init(&this->receive_lock);
57 snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "mux");
58 return &this->layer;
59}
60
61int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid)
62{
63 struct cfmuxl *muxl = container_obj(layr);
64 spin_lock(&muxl->receive_lock);
65 list_add(&up->node, &muxl->srvl_list);
66 spin_unlock(&muxl->receive_lock);
67 return 0;
68}
69
70bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid)
71{
72 struct list_head *node;
73 struct cflayer *layer;
74 struct cfmuxl *muxl = container_obj(layr);
75 bool match = false;
76 spin_lock(&muxl->receive_lock);
77
78 list_for_each(node, &muxl->srvl_list) {
79 layer = list_entry(node, struct cflayer, node);
80 if (cfsrvl_phyid_match(layer, phyid)) {
81 match = true;
82 break;
83 }
84
85 }
86 spin_unlock(&muxl->receive_lock);
87 return match;
88}
89
90u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id)
91{
92 struct cflayer *up;
93 int phyid;
94 struct cfmuxl *muxl = container_obj(layr);
95 spin_lock(&muxl->receive_lock);
96 up = get_up(muxl, channel_id);
97 if (up != NULL)
98 phyid = cfsrvl_getphyid(up);
99 else
100 phyid = 0;
101 spin_unlock(&muxl->receive_lock);
102 return phyid;
103}
104
105int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid)
106{
107 struct cfmuxl *muxl = (struct cfmuxl *) layr;
108 spin_lock(&muxl->transmit_lock);
109 list_add(&dn->node, &muxl->frml_list);
110 spin_unlock(&muxl->transmit_lock);
111 return 0;
112}
113
114static struct cflayer *get_from_id(struct list_head *list, u16 id)
115{
116 struct list_head *node;
117 struct cflayer *layer;
118 list_for_each(node, list) {
119 layer = list_entry(node, struct cflayer, node);
120 if (layer->id == id)
121 return layer;
122 }
123 return NULL;
124}
125
126struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid)
127{
128 struct cfmuxl *muxl = container_obj(layr);
129 struct cflayer *dn;
130 spin_lock(&muxl->transmit_lock);
131 memset(muxl->dn_cache, 0, sizeof(muxl->dn_cache));
132 dn = get_from_id(&muxl->frml_list, phyid);
133 if (dn == NULL) {
134 spin_unlock(&muxl->transmit_lock);
135 return NULL;
136 }
137 list_del(&dn->node);
138 caif_assert(dn != NULL);
139 spin_unlock(&muxl->transmit_lock);
140 return dn;
141}
142
143/* Invariant: lock is taken */
144static struct cflayer *get_up(struct cfmuxl *muxl, u16 id)
145{
146 struct cflayer *up;
147 int idx = id % UP_CACHE_SIZE;
148 up = muxl->up_cache[idx];
149 if (up == NULL || up->id != id) {
150 up = get_from_id(&muxl->srvl_list, id);
151 muxl->up_cache[idx] = up;
152 }
153 return up;
154}
155
156/* Invariant: lock is taken */
157static struct cflayer *get_dn(struct cfmuxl *muxl, struct dev_info *dev_info)
158{
159 struct cflayer *dn;
160 int idx = dev_info->id % DN_CACHE_SIZE;
161 dn = muxl->dn_cache[idx];
162 if (dn == NULL || dn->id != dev_info->id) {
163 dn = get_from_id(&muxl->frml_list, dev_info->id);
164 muxl->dn_cache[idx] = dn;
165 }
166 return dn;
167}
168
169struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id)
170{
171 struct cflayer *up;
172 struct cfmuxl *muxl = container_obj(layr);
173 spin_lock(&muxl->receive_lock);
174 up = get_up(muxl, id);
175 memset(muxl->up_cache, 0, sizeof(muxl->up_cache));
176 list_del(&up->node);
177 spin_unlock(&muxl->receive_lock);
178 return up;
179}
180
181static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt)
182{
183 int ret;
184 struct cfmuxl *muxl = container_obj(layr);
185 u8 id;
186 struct cflayer *up;
187 if (cfpkt_extr_head(pkt, &id, 1) < 0) {
188 pr_err("CAIF: %s(): erroneous Caif Packet\n", __func__);
189 cfpkt_destroy(pkt);
190 return -EPROTO;
191 }
192
193 spin_lock(&muxl->receive_lock);
194 up = get_up(muxl, id);
195 spin_unlock(&muxl->receive_lock);
196 if (up == NULL) {
197 pr_info("CAIF: %s():Received data on unknown link ID = %d "
198 "(0x%x) up == NULL", __func__, id, id);
199 cfpkt_destroy(pkt);
200 /*
201 * Don't return ERROR, since modem misbehaves and sends out
202 * flow on before linksetup response.
203 */
204 return /* CFGLU_EPROT; */ 0;
205 }
206
207 ret = up->receive(up, pkt);
208 return ret;
209}
210
211static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt)
212{
213 int ret;
214 struct cfmuxl *muxl = container_obj(layr);
215 u8 linkid;
216 struct cflayer *dn;
217 struct caif_payload_info *info = cfpkt_info(pkt);
218 dn = get_dn(muxl, cfpkt_info(pkt)->dev_info);
219 if (dn == NULL) {
220 pr_warning("CAIF: %s(): Send data on unknown phy "
221 "ID = %d (0x%x)\n",
222 __func__, info->dev_info->id, info->dev_info->id);
223 return -ENOTCONN;
224 }
225 info->hdr_len += 1;
226 linkid = info->channel_id;
227 cfpkt_add_head(pkt, &linkid, 1);
228 ret = dn->transmit(dn, pkt);
229 /* Remove MUX protocol header upon error. */
230 if (ret < 0)
231 cfpkt_extr_head(pkt, &linkid, 1);
232 return ret;
233}
234
235static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
236 int phyid)
237{
238 struct cfmuxl *muxl = container_obj(layr);
239 struct list_head *node;
240 struct cflayer *layer;
241 list_for_each(node, &muxl->srvl_list) {
242 layer = list_entry(node, struct cflayer, node);
243 if (cfsrvl_phyid_match(layer, phyid))
244 layer->ctrlcmd(layer, ctrl, phyid);
245 }
246}
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
new file mode 100644
index 000000000000..83fff2ff6658
--- /dev/null
+++ b/net/caif/cfpkt_skbuff.c
@@ -0,0 +1,571 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/string.h>
8#include <linux/skbuff.h>
9#include <linux/hardirq.h>
10#include <net/caif/cfpkt.h>
11
12#define PKT_PREFIX CAIF_NEEDED_HEADROOM
13#define PKT_POSTFIX CAIF_NEEDED_TAILROOM
14#define PKT_LEN_WHEN_EXTENDING 128
15#define PKT_ERROR(pkt, errmsg) do { \
16 cfpkt_priv(pkt)->erronous = true; \
17 skb_reset_tail_pointer(&pkt->skb); \
18 pr_warning("CAIF: " errmsg);\
19 } while (0)
20
21struct cfpktq {
22 struct sk_buff_head head;
23 atomic_t count;
24 /* Lock protects count updates */
25 spinlock_t lock;
26};
27
28/*
29 * net/caif/ is generic and does not
30 * understand SKB, so we do this typecast
31 */
32struct cfpkt {
33 struct sk_buff skb;
34};
35
36/* Private data inside SKB */
37struct cfpkt_priv_data {
38 struct dev_info dev_info;
39 bool erronous;
40};
41
42inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt)
43{
44 return (struct cfpkt_priv_data *) pkt->skb.cb;
45}
46
47inline bool is_erronous(struct cfpkt *pkt)
48{
49 return cfpkt_priv(pkt)->erronous;
50}
51
52inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt)
53{
54 return &pkt->skb;
55}
56
57inline struct cfpkt *skb_to_pkt(struct sk_buff *skb)
58{
59 return (struct cfpkt *) skb;
60}
61
62
63struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt)
64{
65 struct cfpkt *pkt = skb_to_pkt(nativepkt);
66 cfpkt_priv(pkt)->erronous = false;
67 return pkt;
68}
69EXPORT_SYMBOL(cfpkt_fromnative);
70
71void *cfpkt_tonative(struct cfpkt *pkt)
72{
73 return (void *) pkt;
74}
75EXPORT_SYMBOL(cfpkt_tonative);
76
77static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx)
78{
79 struct sk_buff *skb;
80
81 if (likely(in_interrupt()))
82 skb = alloc_skb(len + pfx, GFP_ATOMIC);
83 else
84 skb = alloc_skb(len + pfx, GFP_KERNEL);
85
86 if (unlikely(skb == NULL))
87 return NULL;
88
89 skb_reserve(skb, pfx);
90 return skb_to_pkt(skb);
91}
92
93inline struct cfpkt *cfpkt_create(u16 len)
94{
95 return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
96}
97EXPORT_SYMBOL(cfpkt_create);
98
99void cfpkt_destroy(struct cfpkt *pkt)
100{
101 struct sk_buff *skb = pkt_to_skb(pkt);
102 kfree_skb(skb);
103}
104EXPORT_SYMBOL(cfpkt_destroy);
105
106inline bool cfpkt_more(struct cfpkt *pkt)
107{
108 struct sk_buff *skb = pkt_to_skb(pkt);
109 return skb->len > 0;
110}
111EXPORT_SYMBOL(cfpkt_more);
112
113int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len)
114{
115 struct sk_buff *skb = pkt_to_skb(pkt);
116 if (skb_headlen(skb) >= len) {
117 memcpy(data, skb->data, len);
118 return 0;
119 }
120 return !cfpkt_extr_head(pkt, data, len) &&
121 !cfpkt_add_head(pkt, data, len);
122}
123EXPORT_SYMBOL(cfpkt_peek_head);
124
125int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len)
126{
127 struct sk_buff *skb = pkt_to_skb(pkt);
128 u8 *from;
129 if (unlikely(is_erronous(pkt)))
130 return -EPROTO;
131
132 if (unlikely(len > skb->len)) {
133 PKT_ERROR(pkt, "cfpkt_extr_head read beyond end of packet\n");
134 return -EPROTO;
135 }
136
137 if (unlikely(len > skb_headlen(skb))) {
138 if (unlikely(skb_linearize(skb) != 0)) {
139 PKT_ERROR(pkt, "cfpkt_extr_head linearize failed\n");
140 return -EPROTO;
141 }
142 }
143 from = skb_pull(skb, len);
144 from -= len;
145 memcpy(data, from, len);
146 return 0;
147}
148EXPORT_SYMBOL(cfpkt_extr_head);
149
150int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len)
151{
152 struct sk_buff *skb = pkt_to_skb(pkt);
153 u8 *data = dta;
154 u8 *from;
155 if (unlikely(is_erronous(pkt)))
156 return -EPROTO;
157
158 if (unlikely(skb_linearize(skb) != 0)) {
159 PKT_ERROR(pkt, "cfpkt_extr_trail linearize failed\n");
160 return -EPROTO;
161 }
162 if (unlikely(skb->data + len > skb_tail_pointer(skb))) {
163 PKT_ERROR(pkt, "cfpkt_extr_trail read beyond end of packet\n");
164 return -EPROTO;
165 }
166 from = skb_tail_pointer(skb) - len;
167 skb_trim(skb, skb->len - len);
168 memcpy(data, from, len);
169 return 0;
170}
171EXPORT_SYMBOL(cfpkt_extr_trail);
172
173int cfpkt_pad_trail(struct cfpkt *pkt, u16 len)
174{
175 return cfpkt_add_body(pkt, NULL, len);
176}
177EXPORT_SYMBOL(cfpkt_pad_trail);
178
179int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len)
180{
181 struct sk_buff *skb = pkt_to_skb(pkt);
182 struct sk_buff *lastskb;
183 u8 *to;
184 u16 addlen = 0;
185
186
187 if (unlikely(is_erronous(pkt)))
188 return -EPROTO;
189
190 lastskb = skb;
191
192 /* Check whether we need to add space at the tail */
193 if (unlikely(skb_tailroom(skb) < len)) {
194 if (likely(len < PKT_LEN_WHEN_EXTENDING))
195 addlen = PKT_LEN_WHEN_EXTENDING;
196 else
197 addlen = len;
198 }
199
200 /* Check whether we need to change the SKB before writing to the tail */
201 if (unlikely((addlen > 0) || skb_cloned(skb) || skb_shared(skb))) {
202
203 /* Make sure data is writable */
204 if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) {
205 PKT_ERROR(pkt, "cfpkt_add_body: cow failed\n");
206 return -EPROTO;
207 }
208 /*
209 * Is the SKB non-linear after skb_cow_data()? If so, we are
210 * going to add data to the last SKB, so we need to adjust
211 * lengths of the top SKB.
212 */
213 if (lastskb != skb) {
214 pr_warning("CAIF: %s(): Packet is non-linear\n",
215 __func__);
216 skb->len += len;
217 skb->data_len += len;
218 }
219 }
220
221 /* All set to put the last SKB and optionally write data there. */
222 to = skb_put(lastskb, len);
223 if (likely(data))
224 memcpy(to, data, len);
225 return 0;
226}
227EXPORT_SYMBOL(cfpkt_add_body);
228
229inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data)
230{
231 return cfpkt_add_body(pkt, &data, 1);
232}
233EXPORT_SYMBOL(cfpkt_addbdy);
234
235int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
236{
237 struct sk_buff *skb = pkt_to_skb(pkt);
238 struct sk_buff *lastskb;
239 u8 *to;
240 const u8 *data = data2;
241 if (unlikely(is_erronous(pkt)))
242 return -EPROTO;
243 if (unlikely(skb_headroom(skb) < len)) {
244 PKT_ERROR(pkt, "cfpkt_add_head: no headroom\n");
245 return -EPROTO;
246 }
247
248 /* Make sure data is writable */
249 if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) {
250 PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n");
251 return -EPROTO;
252 }
253
254 to = skb_push(skb, len);
255 memcpy(to, data, len);
256 return 0;
257}
258EXPORT_SYMBOL(cfpkt_add_head);
259
260inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len)
261{
262 return cfpkt_add_body(pkt, data, len);
263}
264EXPORT_SYMBOL(cfpkt_add_trail);
265
266inline u16 cfpkt_getlen(struct cfpkt *pkt)
267{
268 struct sk_buff *skb = pkt_to_skb(pkt);
269 return skb->len;
270}
271EXPORT_SYMBOL(cfpkt_getlen);
272
273inline u16 cfpkt_iterate(struct cfpkt *pkt,
274 u16 (*iter_func)(u16, void *, u16),
275 u16 data)
276{
277 /*
278 * Don't care about the performance hit of linearizing,
279 * Checksum should not be used on high-speed interfaces anyway.
280 */
281 if (unlikely(is_erronous(pkt)))
282 return -EPROTO;
283 if (unlikely(skb_linearize(&pkt->skb) != 0)) {
284 PKT_ERROR(pkt, "cfpkt_iterate: linearize failed\n");
285 return -EPROTO;
286 }
287 return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt));
288}
289EXPORT_SYMBOL(cfpkt_iterate);
290
291int cfpkt_setlen(struct cfpkt *pkt, u16 len)
292{
293 struct sk_buff *skb = pkt_to_skb(pkt);
294
295
296 if (unlikely(is_erronous(pkt)))
297 return -EPROTO;
298
299 if (likely(len <= skb->len)) {
300 if (unlikely(skb->data_len))
301 ___pskb_trim(skb, len);
302 else
303 skb_trim(skb, len);
304
305 return cfpkt_getlen(pkt);
306 }
307
308 /* Need to expand SKB */
309 if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len)))
310 PKT_ERROR(pkt, "cfpkt_setlen: skb_pad_trail failed\n");
311
312 return cfpkt_getlen(pkt);
313}
314EXPORT_SYMBOL(cfpkt_setlen);
315
316struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len)
317{
318 struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
319 if (unlikely(data != NULL))
320 cfpkt_add_body(pkt, data, len);
321 return pkt;
322}
323EXPORT_SYMBOL(cfpkt_create_uplink);
324
325struct cfpkt *cfpkt_append(struct cfpkt *dstpkt,
326 struct cfpkt *addpkt,
327 u16 expectlen)
328{
329 struct sk_buff *dst = pkt_to_skb(dstpkt);
330 struct sk_buff *add = pkt_to_skb(addpkt);
331 u16 addlen = skb_headlen(add);
332 u16 neededtailspace;
333 struct sk_buff *tmp;
334 u16 dstlen;
335 u16 createlen;
336 if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) {
337 cfpkt_destroy(addpkt);
338 return dstpkt;
339 }
340 if (expectlen > addlen)
341 neededtailspace = expectlen;
342 else
343 neededtailspace = addlen;
344
345 if (dst->tail + neededtailspace > dst->end) {
346 /* Create a dumplicate of 'dst' with more tail space */
347 dstlen = skb_headlen(dst);
348 createlen = dstlen + neededtailspace;
349 tmp = pkt_to_skb(
350 cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX));
351 if (!tmp)
352 return NULL;
353 skb_set_tail_pointer(tmp, dstlen);
354 tmp->len = dstlen;
355 memcpy(tmp->data, dst->data, dstlen);
356 cfpkt_destroy(dstpkt);
357 dst = tmp;
358 }
359 memcpy(skb_tail_pointer(dst), add->data, skb_headlen(add));
360 cfpkt_destroy(addpkt);
361 dst->tail += addlen;
362 dst->len += addlen;
363 return skb_to_pkt(dst);
364}
365EXPORT_SYMBOL(cfpkt_append);
366
367struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
368{
369 struct sk_buff *skb2;
370 struct sk_buff *skb = pkt_to_skb(pkt);
371 u8 *split = skb->data + pos;
372 u16 len2nd = skb_tail_pointer(skb) - split;
373
374 if (unlikely(is_erronous(pkt)))
375 return NULL;
376
377 if (skb->data + pos > skb_tail_pointer(skb)) {
378 PKT_ERROR(pkt,
379 "cfpkt_split: trying to split beyond end of packet");
380 return NULL;
381 }
382
383 /* Create a new packet for the second part of the data */
384 skb2 = pkt_to_skb(
385 cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
386 PKT_PREFIX));
387
388 if (skb2 == NULL)
389 return NULL;
390
391 /* Reduce the length of the original packet */
392 skb_set_tail_pointer(skb, pos);
393 skb->len = pos;
394
395 memcpy(skb2->data, split, len2nd);
396 skb2->tail += len2nd;
397 skb2->len += len2nd;
398 return skb_to_pkt(skb2);
399}
400EXPORT_SYMBOL(cfpkt_split);
401
402char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen)
403{
404 struct sk_buff *skb = pkt_to_skb(pkt);
405 char *p = buf;
406 int i;
407
408 /*
409 * Sanity check buffer length, it needs to be at least as large as
410 * the header info: ~=50+ bytes
411 */
412 if (buflen < 50)
413 return NULL;
414
415 snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [",
416 is_erronous(pkt) ? "ERRONOUS-SKB" :
417 (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"),
418 skb,
419 (long) skb->len,
420 (long) (skb_tail_pointer(skb) - skb->data),
421 (long) skb->data_len,
422 (long) (skb->data - skb->head),
423 (long) (skb_tail_pointer(skb) - skb->head));
424 p = buf + strlen(buf);
425
426 for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) {
427 if (p > buf + buflen - 10) {
428 sprintf(p, "...");
429 p = buf + strlen(buf);
430 break;
431 }
432 sprintf(p, "%02x,", skb->data[i]);
433 p = buf + strlen(buf);
434 }
435 sprintf(p, "]\n");
436 return buf;
437}
438EXPORT_SYMBOL(cfpkt_log_pkt);
439
440int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen)
441{
442 struct sk_buff *skb = pkt_to_skb(pkt);
443 struct sk_buff *lastskb;
444
445 caif_assert(buf != NULL);
446 if (unlikely(is_erronous(pkt)))
447 return -EPROTO;
448 /* Make sure SKB is writable */
449 if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) {
450 PKT_ERROR(pkt, "cfpkt_raw_append: skb_cow_data failed\n");
451 return -EPROTO;
452 }
453
454 if (unlikely(skb_linearize(skb) != 0)) {
455 PKT_ERROR(pkt, "cfpkt_raw_append: linearize failed\n");
456 return -EPROTO;
457 }
458
459 if (unlikely(skb_tailroom(skb) < buflen)) {
460 PKT_ERROR(pkt, "cfpkt_raw_append: buffer too short - failed\n");
461 return -EPROTO;
462 }
463
464 *buf = skb_put(skb, buflen);
465 return 1;
466}
467EXPORT_SYMBOL(cfpkt_raw_append);
468
469int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen)
470{
471 struct sk_buff *skb = pkt_to_skb(pkt);
472
473 caif_assert(buf != NULL);
474 if (unlikely(is_erronous(pkt)))
475 return -EPROTO;
476
477 if (unlikely(buflen > skb->len)) {
478 PKT_ERROR(pkt, "cfpkt_raw_extract: buflen too large "
479 "- failed\n");
480 return -EPROTO;
481 }
482
483 if (unlikely(buflen > skb_headlen(skb))) {
484 if (unlikely(skb_linearize(skb) != 0)) {
485 PKT_ERROR(pkt, "cfpkt_raw_extract: linearize failed\n");
486 return -EPROTO;
487 }
488 }
489
490 *buf = skb->data;
491 skb_pull(skb, buflen);
492
493 return 1;
494}
495EXPORT_SYMBOL(cfpkt_raw_extract);
496
497inline bool cfpkt_erroneous(struct cfpkt *pkt)
498{
499 return cfpkt_priv(pkt)->erronous;
500}
501EXPORT_SYMBOL(cfpkt_erroneous);
502
503struct cfpktq *cfpktq_create(void)
504{
505 struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC);
506 if (!q)
507 return NULL;
508 skb_queue_head_init(&q->head);
509 atomic_set(&q->count, 0);
510 spin_lock_init(&q->lock);
511 return q;
512}
513EXPORT_SYMBOL(cfpktq_create);
514
515void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio)
516{
517 atomic_inc(&pktq->count);
518 spin_lock(&pktq->lock);
519 skb_queue_tail(&pktq->head, pkt_to_skb(pkt));
520 spin_unlock(&pktq->lock);
521
522}
523EXPORT_SYMBOL(cfpkt_queue);
524
525struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq)
526{
527 struct cfpkt *tmp;
528 spin_lock(&pktq->lock);
529 tmp = skb_to_pkt(skb_peek(&pktq->head));
530 spin_unlock(&pktq->lock);
531 return tmp;
532}
533EXPORT_SYMBOL(cfpkt_qpeek);
534
535struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq)
536{
537 struct cfpkt *pkt;
538 spin_lock(&pktq->lock);
539 pkt = skb_to_pkt(skb_dequeue(&pktq->head));
540 if (pkt) {
541 atomic_dec(&pktq->count);
542 caif_assert(atomic_read(&pktq->count) >= 0);
543 }
544 spin_unlock(&pktq->lock);
545 return pkt;
546}
547EXPORT_SYMBOL(cfpkt_dequeue);
548
549int cfpkt_qcount(struct cfpktq *pktq)
550{
551 return atomic_read(&pktq->count);
552}
553EXPORT_SYMBOL(cfpkt_qcount);
554
555struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt)
556{
557 struct cfpkt *clone;
558 clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC));
559 /* Free original packet. */
560 cfpkt_destroy(pkt);
561 if (!clone)
562 return NULL;
563 return clone;
564}
565EXPORT_SYMBOL(cfpkt_clone_release);
566
567struct caif_payload_info *cfpkt_info(struct cfpkt *pkt)
568{
569 return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb;
570}
571EXPORT_SYMBOL(cfpkt_info);
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c
new file mode 100644
index 000000000000..cd2830fec935
--- /dev/null
+++ b/net/caif/cfrfml.c
@@ -0,0 +1,108 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/spinlock.h>
9#include <linux/slab.h>
10#include <net/caif/caif_layer.h>
11#include <net/caif/cfsrvl.h>
12#include <net/caif/cfpkt.h>
13
14#define container_obj(layr) container_of(layr, struct cfsrvl, layer)
15
16#define RFM_SEGMENTATION_BIT 0x01
17#define RFM_PAYLOAD 0x00
18#define RFM_CMD_BIT 0x80
19#define RFM_FLOW_OFF 0x81
20#define RFM_FLOW_ON 0x80
21#define RFM_SET_PIN 0x82
22#define RFM_CTRL_PKT_SIZE 1
23
24static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt);
25static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt);
26static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl);
27
28struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info)
29{
30 struct cfsrvl *rfm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
31 if (!rfm) {
32 pr_warning("CAIF: %s(): Out of memory\n", __func__);
33 return NULL;
34 }
35 caif_assert(offsetof(struct cfsrvl, layer) == 0);
36 memset(rfm, 0, sizeof(struct cfsrvl));
37 cfsrvl_init(rfm, channel_id, dev_info);
38 rfm->layer.modemcmd = cfservl_modemcmd;
39 rfm->layer.receive = cfrfml_receive;
40 rfm->layer.transmit = cfrfml_transmit;
41 snprintf(rfm->layer.name, CAIF_LAYER_NAME_SZ, "rfm%d", channel_id);
42 return &rfm->layer;
43}
44
45static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
46{
47 return -EPROTO;
48}
49
50static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt)
51{
52 u8 tmp;
53 bool segmented;
54 int ret;
55 caif_assert(layr->up != NULL);
56 caif_assert(layr->receive != NULL);
57
58 /*
59 * RFM is taking care of segmentation and stripping of
60 * segmentation bit.
61 */
62 if (cfpkt_extr_head(pkt, &tmp, 1) < 0) {
63 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
64 cfpkt_destroy(pkt);
65 return -EPROTO;
66 }
67 segmented = tmp & RFM_SEGMENTATION_BIT;
68 caif_assert(!segmented);
69
70 ret = layr->up->receive(layr->up, pkt);
71 return ret;
72}
73
74static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt)
75{
76 u8 tmp = 0;
77 int ret;
78 struct cfsrvl *service = container_obj(layr);
79
80 caif_assert(layr->dn != NULL);
81 caif_assert(layr->dn->transmit != NULL);
82
83 if (!cfsrvl_ready(service, &ret))
84 return ret;
85
86 if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
87 pr_err("CAIF: %s():Packet too large - size=%d\n",
88 __func__, cfpkt_getlen(pkt));
89 return -EOVERFLOW;
90 }
91 if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
92 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
93 return -EPROTO;
94 }
95
96 /* Add info for MUX-layer to route the packet out. */
97 cfpkt_info(pkt)->channel_id = service->layer.id;
98 /*
99 * To optimize alignment, we add up the size of CAIF header before
100 * payload.
101 */
102 cfpkt_info(pkt)->hdr_len = 1;
103 cfpkt_info(pkt)->dev_info = &service->dev_info;
104 ret = layr->dn->transmit(layr->dn, pkt);
105 if (ret < 0)
106 cfpkt_extr_head(pkt, &tmp, 1);
107 return ret;
108}
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
new file mode 100644
index 000000000000..06029ea2da2f
--- /dev/null
+++ b/net/caif/cfserl.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/spinlock.h>
9#include <linux/slab.h>
10#include <net/caif/caif_layer.h>
11#include <net/caif/cfpkt.h>
12#include <net/caif/cfserl.h>
13
14#define container_obj(layr) ((struct cfserl *) layr)
15
16#define CFSERL_STX 0x02
17#define CAIF_MINIUM_PACKET_SIZE 4
18struct cfserl {
19 struct cflayer layer;
20 struct cfpkt *incomplete_frm;
21 /* Protects parallel processing of incoming packets */
22 spinlock_t sync;
23 bool usestx;
24};
25#define STXLEN(layr) (layr->usestx ? 1 : 0)
26
27static int cfserl_receive(struct cflayer *layr, struct cfpkt *pkt);
28static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt);
29static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
30 int phyid);
31
32struct cflayer *cfserl_create(int type, int instance, bool use_stx)
33{
34 struct cfserl *this = kmalloc(sizeof(struct cfserl), GFP_ATOMIC);
35 if (!this) {
36 pr_warning("CAIF: %s(): Out of memory\n", __func__);
37 return NULL;
38 }
39 caif_assert(offsetof(struct cfserl, layer) == 0);
40 memset(this, 0, sizeof(struct cfserl));
41 this->layer.receive = cfserl_receive;
42 this->layer.transmit = cfserl_transmit;
43 this->layer.ctrlcmd = cfserl_ctrlcmd;
44 this->layer.type = type;
45 this->usestx = use_stx;
46 spin_lock_init(&this->sync);
47 snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "ser1");
48 return &this->layer;
49}
50
51static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
52{
53 struct cfserl *layr = container_obj(l);
54 u16 pkt_len;
55 struct cfpkt *pkt = NULL;
56 struct cfpkt *tail_pkt = NULL;
57 u8 tmp8;
58 u16 tmp;
59 u8 stx = CFSERL_STX;
60 int ret;
61 u16 expectlen = 0;
62 caif_assert(newpkt != NULL);
63 spin_lock(&layr->sync);
64
65 if (layr->incomplete_frm != NULL) {
66
67 layr->incomplete_frm =
68 cfpkt_append(layr->incomplete_frm, newpkt, expectlen);
69 pkt = layr->incomplete_frm;
70 } else {
71 pkt = newpkt;
72 }
73 layr->incomplete_frm = NULL;
74
75 do {
76 /* Search for STX at start of pkt if STX is used */
77 if (layr->usestx) {
78 cfpkt_extr_head(pkt, &tmp8, 1);
79 if (tmp8 != CFSERL_STX) {
80 while (cfpkt_more(pkt)
81 && tmp8 != CFSERL_STX) {
82 cfpkt_extr_head(pkt, &tmp8, 1);
83 }
84 if (!cfpkt_more(pkt)) {
85 cfpkt_destroy(pkt);
86 layr->incomplete_frm = NULL;
87 spin_unlock(&layr->sync);
88 return -EPROTO;
89 }
90 }
91 }
92
93 pkt_len = cfpkt_getlen(pkt);
94
95 /*
96 * pkt_len is the accumulated length of the packet data
97 * we have received so far.
98 * Exit if frame doesn't hold length.
99 */
100
101 if (pkt_len < 2) {
102 if (layr->usestx)
103 cfpkt_add_head(pkt, &stx, 1);
104 layr->incomplete_frm = pkt;
105 spin_unlock(&layr->sync);
106 return 0;
107 }
108
109 /*
110 * Find length of frame.
111 * expectlen is the length we need for a full frame.
112 */
113 cfpkt_peek_head(pkt, &tmp, 2);
114 expectlen = le16_to_cpu(tmp) + 2;
115 /*
116 * Frame error handling
117 */
118 if (expectlen < CAIF_MINIUM_PACKET_SIZE
119 || expectlen > CAIF_MAX_FRAMESIZE) {
120 if (!layr->usestx) {
121 if (pkt != NULL)
122 cfpkt_destroy(pkt);
123 layr->incomplete_frm = NULL;
124 expectlen = 0;
125 spin_unlock(&layr->sync);
126 return -EPROTO;
127 }
128 continue;
129 }
130
131 if (pkt_len < expectlen) {
132 /* Too little received data */
133 if (layr->usestx)
134 cfpkt_add_head(pkt, &stx, 1);
135 layr->incomplete_frm = pkt;
136 spin_unlock(&layr->sync);
137 return 0;
138 }
139
140 /*
141 * Enough data for at least one frame.
142 * Split the frame, if too long
143 */
144 if (pkt_len > expectlen)
145 tail_pkt = cfpkt_split(pkt, expectlen);
146 else
147 tail_pkt = NULL;
148
149 /* Send the first part of packet upwards.*/
150 spin_unlock(&layr->sync);
151 ret = layr->layer.up->receive(layr->layer.up, pkt);
152 spin_lock(&layr->sync);
153 if (ret == -EILSEQ) {
154 if (layr->usestx) {
155 if (tail_pkt != NULL)
156 pkt = cfpkt_append(pkt, tail_pkt, 0);
157
158 /* Start search for next STX if frame failed */
159 continue;
160 } else {
161 cfpkt_destroy(pkt);
162 pkt = NULL;
163 }
164 }
165
166 pkt = tail_pkt;
167
168 } while (pkt != NULL);
169
170 spin_unlock(&layr->sync);
171 return 0;
172}
173
174static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt)
175{
176 struct cfserl *layr = container_obj(layer);
177 int ret;
178 u8 tmp8 = CFSERL_STX;
179 if (layr->usestx)
180 cfpkt_add_head(newpkt, &tmp8, 1);
181 ret = layer->dn->transmit(layer->dn, newpkt);
182 if (ret < 0)
183 cfpkt_extr_head(newpkt, &tmp8, 1);
184
185 return ret;
186}
187
188static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
189 int phyid)
190{
191 layr->up->ctrlcmd(layr->up, ctrl, phyid);
192}
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
new file mode 100644
index 000000000000..d470c51c6431
--- /dev/null
+++ b/net/caif/cfsrvl.c
@@ -0,0 +1,185 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/kernel.h>
8#include <linux/types.h>
9#include <linux/errno.h>
10#include <linux/slab.h>
11#include <net/caif/caif_layer.h>
12#include <net/caif/cfsrvl.h>
13#include <net/caif/cfpkt.h>
14
15#define SRVL_CTRL_PKT_SIZE 1
16#define SRVL_FLOW_OFF 0x81
17#define SRVL_FLOW_ON 0x80
18#define SRVL_SET_PIN 0x82
19#define SRVL_CTRL_PKT_SIZE 1
20
21#define container_obj(layr) container_of(layr, struct cfsrvl, layer)
22
23static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
24 int phyid)
25{
26 struct cfsrvl *service = container_obj(layr);
27 caif_assert(layr->up != NULL);
28 caif_assert(layr->up->ctrlcmd != NULL);
29 switch (ctrl) {
30 case CAIF_CTRLCMD_INIT_RSP:
31 service->open = true;
32 layr->up->ctrlcmd(layr->up, ctrl, phyid);
33 break;
34 case CAIF_CTRLCMD_DEINIT_RSP:
35 case CAIF_CTRLCMD_INIT_FAIL_RSP:
36 service->open = false;
37 layr->up->ctrlcmd(layr->up, ctrl, phyid);
38 break;
39 case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
40 if (phyid != service->dev_info.id)
41 break;
42 if (service->modem_flow_on)
43 layr->up->ctrlcmd(layr->up,
44 CAIF_CTRLCMD_FLOW_OFF_IND, phyid);
45 service->phy_flow_on = false;
46 break;
47 case _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND:
48 if (phyid != service->dev_info.id)
49 return;
50 if (service->modem_flow_on) {
51 layr->up->ctrlcmd(layr->up,
52 CAIF_CTRLCMD_FLOW_ON_IND,
53 phyid);
54 }
55 service->phy_flow_on = true;
56 break;
57 case CAIF_CTRLCMD_FLOW_OFF_IND:
58 if (service->phy_flow_on) {
59 layr->up->ctrlcmd(layr->up,
60 CAIF_CTRLCMD_FLOW_OFF_IND, phyid);
61 }
62 service->modem_flow_on = false;
63 break;
64 case CAIF_CTRLCMD_FLOW_ON_IND:
65 if (service->phy_flow_on) {
66 layr->up->ctrlcmd(layr->up,
67 CAIF_CTRLCMD_FLOW_ON_IND, phyid);
68 }
69 service->modem_flow_on = true;
70 break;
71 case _CAIF_CTRLCMD_PHYIF_DOWN_IND:
72 /* In case interface is down, let's fake a remove shutdown */
73 layr->up->ctrlcmd(layr->up,
74 CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, phyid);
75 break;
76 case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
77 layr->up->ctrlcmd(layr->up, ctrl, phyid);
78 break;
79 default:
80 pr_warning("CAIF: %s(): "
81 "Unexpected ctrl in cfsrvl (%d)\n", __func__, ctrl);
82 /* We have both modem and phy flow on, send flow on */
83 layr->up->ctrlcmd(layr->up, ctrl, phyid);
84 service->phy_flow_on = true;
85 break;
86 }
87}
88
89static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
90{
91 struct cfsrvl *service = container_obj(layr);
92 caif_assert(layr != NULL);
93 caif_assert(layr->dn != NULL);
94 caif_assert(layr->dn->transmit != NULL);
95 switch (ctrl) {
96 case CAIF_MODEMCMD_FLOW_ON_REQ:
97 {
98 struct cfpkt *pkt;
99 struct caif_payload_info *info;
100 u8 flow_on = SRVL_FLOW_ON;
101 pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
102 if (!pkt) {
103 pr_warning("CAIF: %s(): Out of memory\n",
104 __func__);
105 return -ENOMEM;
106 }
107
108 if (cfpkt_add_head(pkt, &flow_on, 1) < 0) {
109 pr_err("CAIF: %s(): Packet is erroneous!\n",
110 __func__);
111 cfpkt_destroy(pkt);
112 return -EPROTO;
113 }
114 info = cfpkt_info(pkt);
115 info->channel_id = service->layer.id;
116 info->hdr_len = 1;
117 info->dev_info = &service->dev_info;
118 return layr->dn->transmit(layr->dn, pkt);
119 }
120 case CAIF_MODEMCMD_FLOW_OFF_REQ:
121 {
122 struct cfpkt *pkt;
123 struct caif_payload_info *info;
124 u8 flow_off = SRVL_FLOW_OFF;
125 pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
126 if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
127 pr_err("CAIF: %s(): Packet is erroneous!\n",
128 __func__);
129 cfpkt_destroy(pkt);
130 return -EPROTO;
131 }
132 info = cfpkt_info(pkt);
133 info->channel_id = service->layer.id;
134 info->hdr_len = 1;
135 info->dev_info = &service->dev_info;
136 return layr->dn->transmit(layr->dn, pkt);
137 }
138 default:
139 break;
140 }
141 return -EINVAL;
142}
143
144void cfservl_destroy(struct cflayer *layer)
145{
146 kfree(layer);
147}
148
149void cfsrvl_init(struct cfsrvl *service,
150 u8 channel_id,
151 struct dev_info *dev_info)
152{
153 caif_assert(offsetof(struct cfsrvl, layer) == 0);
154 service->open = false;
155 service->modem_flow_on = true;
156 service->phy_flow_on = true;
157 service->layer.id = channel_id;
158 service->layer.ctrlcmd = cfservl_ctrlcmd;
159 service->layer.modemcmd = cfservl_modemcmd;
160 service->dev_info = *dev_info;
161}
162
163bool cfsrvl_ready(struct cfsrvl *service, int *err)
164{
165 if (service->open && service->modem_flow_on && service->phy_flow_on)
166 return true;
167 if (!service->open) {
168 *err = -ENOTCONN;
169 return false;
170 }
171 caif_assert(!(service->modem_flow_on && service->phy_flow_on));
172 *err = -EAGAIN;
173 return false;
174}
175u8 cfsrvl_getphyid(struct cflayer *layer)
176{
177 struct cfsrvl *servl = container_obj(layer);
178 return servl->dev_info.id;
179}
180
181bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
182{
183 struct cfsrvl *servl = container_obj(layer);
184 return servl->dev_info.id == phyid;
185}
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c
new file mode 100644
index 000000000000..5fd2c9ea8b42
--- /dev/null
+++ b/net/caif/cfutill.c
@@ -0,0 +1,115 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/kernel.h>
8#include <linux/types.h>
9#include <linux/slab.h>
10#include <linux/errno.h>
11#include <net/caif/caif_layer.h>
12#include <net/caif/cfsrvl.h>
13#include <net/caif/cfpkt.h>
14
15#define container_obj(layr) ((struct cfsrvl *) layr)
16#define UTIL_PAYLOAD 0x00
17#define UTIL_CMD_BIT 0x80
18#define UTIL_REMOTE_SHUTDOWN 0x82
19#define UTIL_FLOW_OFF 0x81
20#define UTIL_FLOW_ON 0x80
21#define UTIL_CTRL_PKT_SIZE 1
22static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt);
23static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt);
24
25struct cflayer *cfutill_create(u8 channel_id, struct dev_info *dev_info)
26{
27 struct cfsrvl *util = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
28 if (!util) {
29 pr_warning("CAIF: %s(): Out of memory\n", __func__);
30 return NULL;
31 }
32 caif_assert(offsetof(struct cfsrvl, layer) == 0);
33 memset(util, 0, sizeof(struct cfsrvl));
34 cfsrvl_init(util, channel_id, dev_info);
35 util->layer.receive = cfutill_receive;
36 util->layer.transmit = cfutill_transmit;
37 snprintf(util->layer.name, CAIF_LAYER_NAME_SZ - 1, "util1");
38 return &util->layer;
39}
40
41static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt)
42{
43 u8 cmd = -1;
44 struct cfsrvl *service = container_obj(layr);
45 caif_assert(layr != NULL);
46 caif_assert(layr->up != NULL);
47 caif_assert(layr->up->receive != NULL);
48 caif_assert(layr->up->ctrlcmd != NULL);
49 if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
50 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
51 cfpkt_destroy(pkt);
52 return -EPROTO;
53 }
54
55 switch (cmd) {
56 case UTIL_PAYLOAD:
57 return layr->up->receive(layr->up, pkt);
58 case UTIL_FLOW_OFF:
59 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0);
60 cfpkt_destroy(pkt);
61 return 0;
62 case UTIL_FLOW_ON:
63 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0);
64 cfpkt_destroy(pkt);
65 return 0;
66 case UTIL_REMOTE_SHUTDOWN: /* Remote Shutdown Request */
67 pr_err("CAIF: %s(): REMOTE SHUTDOWN REQUEST RECEIVED\n",
68 __func__);
69 layr->ctrlcmd(layr, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, 0);
70 service->open = false;
71 cfpkt_destroy(pkt);
72 return 0;
73 default:
74 cfpkt_destroy(pkt);
75 pr_warning("CAIF: %s(): Unknown service control %d (0x%x)\n",
76 __func__, cmd, cmd);
77 return -EPROTO;
78 }
79}
80
81static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt)
82{
83 u8 zero = 0;
84 struct caif_payload_info *info;
85 int ret;
86 struct cfsrvl *service = container_obj(layr);
87 caif_assert(layr != NULL);
88 caif_assert(layr->dn != NULL);
89 caif_assert(layr->dn->transmit != NULL);
90 if (!cfsrvl_ready(service, &ret))
91 return ret;
92
93 if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
94 pr_err("CAIF: %s(): packet too large size=%d\n",
95 __func__, cfpkt_getlen(pkt));
96 return -EOVERFLOW;
97 }
98
99 cfpkt_add_head(pkt, &zero, 1);
100 /* Add info for MUX-layer to route the packet out. */
101 info = cfpkt_info(pkt);
102 info->channel_id = service->layer.id;
103 /*
104 * To optimize alignment, we add up the size of CAIF header before
105 * payload.
106 */
107 info->hdr_len = 1;
108 info->dev_info = &service->dev_info;
109 ret = layr->dn->transmit(layr->dn, pkt);
110 if (ret < 0) {
111 u32 tmp32;
112 cfpkt_extr_head(pkt, &tmp32, 4);
113 }
114 return ret;
115}
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
new file mode 100644
index 000000000000..0fd827f49491
--- /dev/null
+++ b/net/caif/cfveil.c
@@ -0,0 +1,107 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/stddef.h>
8#include <linux/slab.h>
9#include <net/caif/caif_layer.h>
10#include <net/caif/cfsrvl.h>
11#include <net/caif/cfpkt.h>
12
13#define VEI_PAYLOAD 0x00
14#define VEI_CMD_BIT 0x80
15#define VEI_FLOW_OFF 0x81
16#define VEI_FLOW_ON 0x80
17#define VEI_SET_PIN 0x82
18#define VEI_CTRL_PKT_SIZE 1
19#define container_obj(layr) container_of(layr, struct cfsrvl, layer)
20
21static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt);
22static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt);
23
24struct cflayer *cfvei_create(u8 channel_id, struct dev_info *dev_info)
25{
26 struct cfsrvl *vei = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
27 if (!vei) {
28 pr_warning("CAIF: %s(): Out of memory\n", __func__);
29 return NULL;
30 }
31 caif_assert(offsetof(struct cfsrvl, layer) == 0);
32 memset(vei, 0, sizeof(struct cfsrvl));
33 cfsrvl_init(vei, channel_id, dev_info);
34 vei->layer.receive = cfvei_receive;
35 vei->layer.transmit = cfvei_transmit;
36 snprintf(vei->layer.name, CAIF_LAYER_NAME_SZ - 1, "vei%d", channel_id);
37 return &vei->layer;
38}
39
40static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt)
41{
42 u8 cmd;
43 int ret;
44 caif_assert(layr->up != NULL);
45 caif_assert(layr->receive != NULL);
46 caif_assert(layr->ctrlcmd != NULL);
47
48
49 if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
50 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
51 cfpkt_destroy(pkt);
52 return -EPROTO;
53 }
54 switch (cmd) {
55 case VEI_PAYLOAD:
56 ret = layr->up->receive(layr->up, pkt);
57 return ret;
58 case VEI_FLOW_OFF:
59 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0);
60 cfpkt_destroy(pkt);
61 return 0;
62 case VEI_FLOW_ON:
63 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0);
64 cfpkt_destroy(pkt);
65 return 0;
66 case VEI_SET_PIN: /* SET RS232 PIN */
67 cfpkt_destroy(pkt);
68 return 0;
69 default: /* SET RS232 PIN */
70 pr_warning("CAIF: %s():Unknown VEI control packet %d (0x%x)!\n",
71 __func__, cmd, cmd);
72 cfpkt_destroy(pkt);
73 return -EPROTO;
74 }
75}
76
77static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
78{
79 u8 tmp = 0;
80 struct caif_payload_info *info;
81 int ret;
82 struct cfsrvl *service = container_obj(layr);
83 if (!cfsrvl_ready(service, &ret))
84 return ret;
85 caif_assert(layr->dn != NULL);
86 caif_assert(layr->dn->transmit != NULL);
87 if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
88 pr_warning("CAIF: %s(): Packet too large - size=%d\n",
89 __func__, cfpkt_getlen(pkt));
90 return -EOVERFLOW;
91 }
92
93 if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
94 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
95 return -EPROTO;
96 }
97
98 /* Add info-> for MUX-layer to route the packet out. */
99 info = cfpkt_info(pkt);
100 info->channel_id = service->layer.id;
101 info->hdr_len = 1;
102 info->dev_info = &service->dev_info;
103 ret = layr->dn->transmit(layr->dn, pkt);
104 if (ret < 0)
105 cfpkt_extr_head(pkt, &tmp, 1);
106 return ret;
107}
diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c
new file mode 100644
index 000000000000..89ad4ea239f1
--- /dev/null
+++ b/net/caif/cfvidl.c
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/kernel.h>
8#include <linux/types.h>
9#include <linux/slab.h>
10#include <linux/errno.h>
11#include <net/caif/caif_layer.h>
12#include <net/caif/cfsrvl.h>
13#include <net/caif/cfpkt.h>
14
15#define container_obj(layr) ((struct cfsrvl *) layr)
16
17static int cfvidl_receive(struct cflayer *layr, struct cfpkt *pkt);
18static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt);
19
20struct cflayer *cfvidl_create(u8 channel_id, struct dev_info *dev_info)
21{
22 struct cfsrvl *vid = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
23 if (!vid) {
24 pr_warning("CAIF: %s(): Out of memory\n", __func__);
25 return NULL;
26 }
27 caif_assert(offsetof(struct cfsrvl, layer) == 0);
28
29 memset(vid, 0, sizeof(struct cfsrvl));
30 cfsrvl_init(vid, channel_id, dev_info);
31 vid->layer.receive = cfvidl_receive;
32 vid->layer.transmit = cfvidl_transmit;
33 snprintf(vid->layer.name, CAIF_LAYER_NAME_SZ - 1, "vid1");
34 return &vid->layer;
35}
36
37static int cfvidl_receive(struct cflayer *layr, struct cfpkt *pkt)
38{
39 u32 videoheader;
40 if (cfpkt_extr_head(pkt, &videoheader, 4) < 0) {
41 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
42 cfpkt_destroy(pkt);
43 return -EPROTO;
44 }
45 return layr->up->receive(layr->up, pkt);
46}
47
48static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt)
49{
50 struct cfsrvl *service = container_obj(layr);
51 struct caif_payload_info *info;
52 u32 videoheader = 0;
53 int ret;
54 if (!cfsrvl_ready(service, &ret))
55 return ret;
56 cfpkt_add_head(pkt, &videoheader, 4);
57 /* Add info for MUX-layer to route the packet out */
58 info = cfpkt_info(pkt);
59 info->channel_id = service->layer.id;
60 info->dev_info = &service->dev_info;
61 ret = layr->dn->transmit(layr->dn, pkt);
62 if (ret < 0)
63 cfpkt_extr_head(pkt, &videoheader, 4);
64 return ret;
65}
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
new file mode 100644
index 000000000000..f622ff1d39ba
--- /dev/null
+++ b/net/caif/chnl_net.c
@@ -0,0 +1,451 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Authors: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * Daniel Martensson / Daniel.Martensson@stericsson.com
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#include <linux/version.h>
9#include <linux/fs.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/netdevice.h>
13#include <linux/if_ether.h>
14#include <linux/moduleparam.h>
15#include <linux/ip.h>
16#include <linux/sched.h>
17#include <linux/sockios.h>
18#include <linux/caif/if_caif.h>
19#include <net/rtnetlink.h>
20#include <net/caif/caif_layer.h>
21#include <net/caif/cfcnfg.h>
22#include <net/caif/cfpkt.h>
23#include <net/caif/caif_dev.h>
24
25#define CAIF_CONNECT_TIMEOUT 30
26#define SIZE_MTU 1500
27#define SIZE_MTU_MAX 4080
28#define SIZE_MTU_MIN 68
29#define CAIF_NET_DEFAULT_QUEUE_LEN 500
30
31#undef pr_debug
32#define pr_debug pr_warning
33
34/*This list is protected by the rtnl lock. */
35static LIST_HEAD(chnl_net_list);
36
37MODULE_LICENSE("GPL");
38MODULE_ALIAS_RTNL_LINK("caif");
39
40struct chnl_net {
41 struct cflayer chnl;
42 struct net_device_stats stats;
43 struct caif_connect_request conn_req;
44 struct list_head list_field;
45 struct net_device *netdev;
46 char name[256];
47 wait_queue_head_t netmgmt_wq;
48 /* Flow status to remember and control the transmission. */
49 bool flowenabled;
50 bool pending_close;
51};
52
53static void robust_list_del(struct list_head *delete_node)
54{
55 struct list_head *list_node;
56 struct list_head *n;
57 ASSERT_RTNL();
58 list_for_each_safe(list_node, n, &chnl_net_list) {
59 if (list_node == delete_node) {
60 list_del(list_node);
61 break;
62 }
63 }
64}
65
66static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
67{
68 struct sk_buff *skb;
69 struct chnl_net *priv = NULL;
70 int pktlen;
71 int err = 0;
72
73 priv = container_of(layr, struct chnl_net, chnl);
74
75 if (!priv)
76 return -EINVAL;
77
78 /* Get length of CAIF packet. */
79 pktlen = cfpkt_getlen(pkt);
80
81 skb = (struct sk_buff *) cfpkt_tonative(pkt);
82 /* Pass some minimum information and
83 * send the packet to the net stack.
84 */
85 skb->dev = priv->netdev;
86 skb->protocol = htons(ETH_P_IP);
87
88 /* If we change the header in loop mode, the checksum is corrupted. */
89 if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
90 skb->ip_summed = CHECKSUM_UNNECESSARY;
91 else
92 skb->ip_summed = CHECKSUM_NONE;
93
94 /* FIXME: Drivers should call this in tasklet context. */
95 if (in_interrupt())
96 netif_rx(skb);
97 else
98 netif_rx_ni(skb);
99
100 /* Update statistics. */
101 priv->netdev->stats.rx_packets++;
102 priv->netdev->stats.rx_bytes += pktlen;
103
104 return err;
105}
106
107static int delete_device(struct chnl_net *dev)
108{
109 ASSERT_RTNL();
110 if (dev->netdev)
111 unregister_netdevice(dev->netdev);
112 return 0;
113}
114
115static void close_work(struct work_struct *work)
116{
117 struct chnl_net *dev = NULL;
118 struct list_head *list_node;
119 struct list_head *_tmp;
120 rtnl_lock();
121 list_for_each_safe(list_node, _tmp, &chnl_net_list) {
122 dev = list_entry(list_node, struct chnl_net, list_field);
123 if (!dev->pending_close)
124 continue;
125 list_del(list_node);
126 delete_device(dev);
127 }
128 rtnl_unlock();
129}
130static DECLARE_WORK(close_worker, close_work);
131
132static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
133 int phyid)
134{
135 struct chnl_net *priv;
136 pr_debug("CAIF: %s(): NET flowctrl func called flow: %s.\n",
137 __func__,
138 flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" :
139 flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" :
140 flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" :
141 flow == CAIF_CTRLCMD_DEINIT_RSP ? "CLOSE/DEINIT" :
142 flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "OPEN_FAIL" :
143 flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ?
144 "REMOTE_SHUTDOWN" : "UKNOWN CTRL COMMAND");
145
146 priv = container_of(layr, struct chnl_net, chnl);
147
148 switch (flow) {
149 case CAIF_CTRLCMD_FLOW_OFF_IND:
150 case CAIF_CTRLCMD_DEINIT_RSP:
151 case CAIF_CTRLCMD_INIT_FAIL_RSP:
152 case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
153 priv->flowenabled = false;
154 netif_tx_disable(priv->netdev);
155 pr_warning("CAIF: %s(): done\n", __func__);
156 priv->pending_close = 1;
157 schedule_work(&close_worker);
158 break;
159 case CAIF_CTRLCMD_FLOW_ON_IND:
160 case CAIF_CTRLCMD_INIT_RSP:
161 priv->flowenabled = true;
162 netif_wake_queue(priv->netdev);
163 wake_up_interruptible(&priv->netmgmt_wq);
164 break;
165 default:
166 break;
167 }
168}
169
170static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
171{
172 struct chnl_net *priv;
173 struct cfpkt *pkt = NULL;
174 int len;
175 int result = -1;
176 /* Get our private data. */
177 priv = netdev_priv(dev);
178
179 if (skb->len > priv->netdev->mtu) {
180 pr_warning("CAIF: %s(): Size of skb exceeded MTU\n", __func__);
181 return -ENOSPC;
182 }
183
184 if (!priv->flowenabled) {
185 pr_debug("CAIF: %s(): dropping packets flow off\n", __func__);
186 return NETDEV_TX_BUSY;
187 }
188
189 if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
190 swap(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
191
192 /* Store original SKB length. */
193 len = skb->len;
194
195 pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb);
196
197 pr_debug("CAIF: %s(): transmit inst %s %d,%p\n",
198 __func__, dev->name, priv->chnl.dn->id, &priv->chnl.dn);
199
200 /* Send the packet down the stack. */
201 result = priv->chnl.dn->transmit(priv->chnl.dn, pkt);
202 if (result) {
203 if (result == -EAGAIN)
204 result = NETDEV_TX_BUSY;
205 return result;
206 }
207
208 /* Update statistics. */
209 dev->stats.tx_packets++;
210 dev->stats.tx_bytes += len;
211
212 return NETDEV_TX_OK;
213}
214
215static int chnl_net_open(struct net_device *dev)
216{
217 struct chnl_net *priv = NULL;
218 int result = -1;
219 ASSERT_RTNL();
220
221 priv = netdev_priv(dev);
222 pr_debug("CAIF: %s(): dev name: %s\n", __func__, priv->name);
223
224 if (!priv) {
225 pr_debug("CAIF: %s(): chnl_net_open: no priv\n", __func__);
226 return -ENODEV;
227 }
228 result = caif_connect_client(&priv->conn_req, &priv->chnl);
229 if (result != 0) {
230 pr_debug("CAIF: %s(): err: "
231 "Unable to register and open device, Err:%d\n",
232 __func__,
233 result);
234 return -ENODEV;
235 }
236 result = wait_event_interruptible(priv->netmgmt_wq, priv->flowenabled);
237
238 if (result == -ERESTARTSYS) {
239 pr_debug("CAIF: %s(): wait_event_interruptible"
240 " woken by a signal\n", __func__);
241 return -ERESTARTSYS;
242 } else
243 pr_debug("CAIF: %s(): Flow on recieved\n", __func__);
244
245 return 0;
246}
247
248static int chnl_net_stop(struct net_device *dev)
249{
250 struct chnl_net *priv;
251 int result = -1;
252 ASSERT_RTNL();
253 priv = netdev_priv(dev);
254
255 result = caif_disconnect_client(&priv->chnl);
256 if (result != 0) {
257 pr_debug("CAIF: %s(): chnl_net_stop: err: "
258 "Unable to STOP device, Err:%d\n",
259 __func__, result);
260 return -EBUSY;
261 }
262 result = wait_event_interruptible(priv->netmgmt_wq,
263 !priv->flowenabled);
264
265 if (result == -ERESTARTSYS) {
266 pr_debug("CAIF: %s(): wait_event_interruptible woken by"
267 " signal, signal_pending(current) = %d\n",
268 __func__,
269 signal_pending(current));
270 } else {
271 pr_debug("CAIF: %s(): disconnect received\n", __func__);
272
273 }
274
275 return 0;
276}
277
278static int chnl_net_init(struct net_device *dev)
279{
280 struct chnl_net *priv;
281 ASSERT_RTNL();
282 priv = netdev_priv(dev);
283 strncpy(priv->name, dev->name, sizeof(priv->name));
284 return 0;
285}
286
287static void chnl_net_uninit(struct net_device *dev)
288{
289 struct chnl_net *priv;
290 ASSERT_RTNL();
291 priv = netdev_priv(dev);
292 robust_list_del(&priv->list_field);
293}
294
295static const struct net_device_ops netdev_ops = {
296 .ndo_open = chnl_net_open,
297 .ndo_stop = chnl_net_stop,
298 .ndo_init = chnl_net_init,
299 .ndo_uninit = chnl_net_uninit,
300 .ndo_start_xmit = chnl_net_start_xmit,
301};
302
303static void ipcaif_net_setup(struct net_device *dev)
304{
305 struct chnl_net *priv;
306 dev->netdev_ops = &netdev_ops;
307 dev->destructor = free_netdev;
308 dev->flags |= IFF_NOARP;
309 dev->flags |= IFF_POINTOPOINT;
310 dev->needed_headroom = CAIF_NEEDED_HEADROOM;
311 dev->needed_tailroom = CAIF_NEEDED_TAILROOM;
312 dev->mtu = SIZE_MTU;
313 dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN;
314
315 priv = netdev_priv(dev);
316 priv->chnl.receive = chnl_recv_cb;
317 priv->chnl.ctrlcmd = chnl_flowctrl_cb;
318 priv->netdev = dev;
319 priv->conn_req.protocol = CAIFPROTO_DATAGRAM;
320 priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW;
321 priv->conn_req.priority = CAIF_PRIO_LOW;
322 /* Insert illegal value */
323 priv->conn_req.sockaddr.u.dgm.connection_id = -1;
324 priv->flowenabled = false;
325
326 ASSERT_RTNL();
327 init_waitqueue_head(&priv->netmgmt_wq);
328 list_add(&priv->list_field, &chnl_net_list);
329}
330
331
332static int ipcaif_fill_info(struct sk_buff *skb, const struct net_device *dev)
333{
334 struct chnl_net *priv;
335 u8 loop;
336 priv = netdev_priv(dev);
337 NLA_PUT_U32(skb, IFLA_CAIF_IPV4_CONNID,
338 priv->conn_req.sockaddr.u.dgm.connection_id);
339 NLA_PUT_U32(skb, IFLA_CAIF_IPV6_CONNID,
340 priv->conn_req.sockaddr.u.dgm.connection_id);
341 loop = priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP;
342 NLA_PUT_U8(skb, IFLA_CAIF_LOOPBACK, loop);
343
344
345 return 0;
346nla_put_failure:
347 return -EMSGSIZE;
348
349}
350
351static void caif_netlink_parms(struct nlattr *data[],
352 struct caif_connect_request *conn_req)
353{
354 if (!data) {
355 pr_warning("CAIF: %s: no params data found\n", __func__);
356 return;
357 }
358 if (data[IFLA_CAIF_IPV4_CONNID])
359 conn_req->sockaddr.u.dgm.connection_id =
360 nla_get_u32(data[IFLA_CAIF_IPV4_CONNID]);
361 if (data[IFLA_CAIF_IPV6_CONNID])
362 conn_req->sockaddr.u.dgm.connection_id =
363 nla_get_u32(data[IFLA_CAIF_IPV6_CONNID]);
364 if (data[IFLA_CAIF_LOOPBACK]) {
365 if (nla_get_u8(data[IFLA_CAIF_LOOPBACK]))
366 conn_req->protocol = CAIFPROTO_DATAGRAM_LOOP;
367 else
368 conn_req->protocol = CAIFPROTO_DATAGRAM;
369 }
370}
371
372static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
373 struct nlattr *tb[], struct nlattr *data[])
374{
375 int ret;
376 struct chnl_net *caifdev;
377 ASSERT_RTNL();
378 caifdev = netdev_priv(dev);
379 caif_netlink_parms(data, &caifdev->conn_req);
380 ret = register_netdevice(dev);
381 if (ret)
382 pr_warning("CAIF: %s(): device rtml registration failed\n",
383 __func__);
384 return ret;
385}
386
387static int ipcaif_changelink(struct net_device *dev, struct nlattr *tb[],
388 struct nlattr *data[])
389{
390 struct chnl_net *caifdev;
391 ASSERT_RTNL();
392 caifdev = netdev_priv(dev);
393 caif_netlink_parms(data, &caifdev->conn_req);
394 netdev_state_change(dev);
395 return 0;
396}
397
398static size_t ipcaif_get_size(const struct net_device *dev)
399{
400 return
401 /* IFLA_CAIF_IPV4_CONNID */
402 nla_total_size(4) +
403 /* IFLA_CAIF_IPV6_CONNID */
404 nla_total_size(4) +
405 /* IFLA_CAIF_LOOPBACK */
406 nla_total_size(2) +
407 0;
408}
409
410static const struct nla_policy ipcaif_policy[IFLA_CAIF_MAX + 1] = {
411 [IFLA_CAIF_IPV4_CONNID] = { .type = NLA_U32 },
412 [IFLA_CAIF_IPV6_CONNID] = { .type = NLA_U32 },
413 [IFLA_CAIF_LOOPBACK] = { .type = NLA_U8 }
414};
415
416
417static struct rtnl_link_ops ipcaif_link_ops __read_mostly = {
418 .kind = "caif",
419 .priv_size = sizeof(struct chnl_net),
420 .setup = ipcaif_net_setup,
421 .maxtype = IFLA_CAIF_MAX,
422 .policy = ipcaif_policy,
423 .newlink = ipcaif_newlink,
424 .changelink = ipcaif_changelink,
425 .get_size = ipcaif_get_size,
426 .fill_info = ipcaif_fill_info,
427
428};
429
430static int __init chnl_init_module(void)
431{
432 return rtnl_link_register(&ipcaif_link_ops);
433}
434
435static void __exit chnl_exit_module(void)
436{
437 struct chnl_net *dev = NULL;
438 struct list_head *list_node;
439 struct list_head *_tmp;
440 rtnl_link_unregister(&ipcaif_link_ops);
441 rtnl_lock();
442 list_for_each_safe(list_node, _tmp, &chnl_net_list) {
443 dev = list_entry(list_node, struct chnl_net, list_field);
444 list_del(list_node);
445 delete_device(dev);
446 }
447 rtnl_unlock();
448}
449
450module_init(chnl_init_module);
451module_exit(chnl_exit_module);