Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-drm-fsl-dcu.git] / net / caif / chnl_net.c
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. */
35 static LIST_HEAD(chnl_net_list);
36
37 MODULE_LICENSE("GPL");
38 MODULE_ALIAS_RTNL_LINK("caif");
39
40 struct 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
53 static 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
66 static 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
107 static 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
115 static 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 }
130 static DECLARE_WORK(close_worker, close_work);
131
132 static 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
170 static 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
215 static 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
248 static 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
278 static 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
287 static 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
295 static 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
303 static 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
332 static 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;
346 nla_put_failure:
347         return -EMSGSIZE;
348
349 }
350
351 static 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
372 static 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
387 static 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
398 static 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
410 static 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
417 static 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
430 static int __init chnl_init_module(void)
431 {
432         return rtnl_link_register(&ipcaif_link_ops);
433 }
434
435 static 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
450 module_init(chnl_init_module);
451 module_exit(chnl_exit_module);