aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSjur Braendeland <sjur.brandeland@stericsson.com>2010-06-17 02:55:40 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-20 22:46:06 -0400
commit2aa40aef9debc77d55cc87a50d335b6fe97fbeb0 (patch)
tree0dccf47cf6cb861c7efa72601fab9511760c7e74
parenta7da1f55a826c621251874e7684c234972fc3216 (diff)
caif: Use link layer MTU instead of fixed MTU
Previously CAIF supported maximum transfer size of ~4050. The transfer size is now calculated dynamically based on the link layers mtu size. Signed-off-by: Sjur Braendeland@stericsson.com Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/caif/caif_serial.c1
-rw-r--r--include/net/caif/caif_dev.h8
-rw-r--r--include/net/caif/caif_layer.h6
-rw-r--r--include/net/caif/cfcnfg.h16
-rw-r--r--net/caif/caif_dev.c12
-rw-r--r--net/caif/caif_socket.c54
-rw-r--r--net/caif/cfcnfg.c44
-rw-r--r--net/caif/cfctrl.c6
-rw-r--r--net/caif/cfdgml.c5
-rw-r--r--net/caif/cfpkt_skbuff.c4
-rw-r--r--net/caif/cfserl.c7
-rw-r--r--net/caif/cfsrvl.c1
-rw-r--r--net/caif/cfutill.c6
-rw-r--r--net/caif/cfveil.c5
-rw-r--r--net/caif/chnl_net.c67
15 files changed, 173 insertions, 69 deletions
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 3e706f00a0d3..3df0c0f8b8bf 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -403,7 +403,6 @@ static void caifdev_setup(struct net_device *dev)
403 dev->type = ARPHRD_CAIF; 403 dev->type = ARPHRD_CAIF;
404 dev->flags = IFF_POINTOPOINT | IFF_NOARP; 404 dev->flags = IFF_POINTOPOINT | IFF_NOARP;
405 dev->mtu = CAIF_MAX_MTU; 405 dev->mtu = CAIF_MAX_MTU;
406 dev->hard_header_len = CAIF_NEEDED_HEADROOM;
407 dev->tx_queue_len = 0; 406 dev->tx_queue_len = 0;
408 dev->destructor = free_netdev; 407 dev->destructor = free_netdev;
409 skb_queue_head_init(&serdev->head); 408 skb_queue_head_init(&serdev->head);
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
index 318ab9478a44..6da573c75d54 100644
--- a/include/net/caif/caif_dev.h
+++ b/include/net/caif/caif_dev.h
@@ -50,6 +50,9 @@ struct caif_connect_request {
50 * @client_layer: User implementation of client layer. This layer 50 * @client_layer: User implementation of client layer. This layer
51 * MUST have receive and control callback functions 51 * MUST have receive and control callback functions
52 * implemented. 52 * implemented.
53 * @ifindex: Link layer interface index used for this connection.
54 * @headroom: Head room needed by CAIF protocol.
55 * @tailroom: Tail room needed by CAIF protocol.
53 * 56 *
54 * This function connects a CAIF channel. The Client must implement 57 * This function connects a CAIF channel. The Client must implement
55 * the struct cflayer. This layer represents the Client layer and holds 58 * the struct cflayer. This layer represents the Client layer and holds
@@ -59,8 +62,9 @@ struct caif_connect_request {
59 * E.g. CAIF Socket will call this function for each socket it connects 62 * E.g. CAIF Socket will call this function for each socket it connects
60 * and have one client_layer instance for each socket. 63 * and have one client_layer instance for each socket.
61 */ 64 */
62int caif_connect_client(struct caif_connect_request *config, 65int caif_connect_client(struct caif_connect_request *conn_req,
63 struct cflayer *client_layer); 66 struct cflayer *client_layer, int *ifindex,
67 int *headroom, int *tailroom);
64 68
65/** 69/**
66 * caif_disconnect_client - Disconnects a client from the CAIF stack. 70 * caif_disconnect_client - Disconnects a client from the CAIF stack.
diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h
index 25c472f0e5b8..c8b07a904e78 100644
--- a/include/net/caif/caif_layer.h
+++ b/include/net/caif/caif_layer.h
@@ -15,14 +15,8 @@ struct cfpktq;
15struct caif_payload_info; 15struct caif_payload_info;
16struct caif_packet_funcs; 16struct caif_packet_funcs;
17 17
18#define CAIF_MAX_FRAMESIZE 4096
19#define CAIF_MAX_PAYLOAD_SIZE (4096 - 64)
20#define CAIF_NEEDED_HEADROOM (10)
21#define CAIF_NEEDED_TAILROOM (2)
22 18
23#define CAIF_LAYER_NAME_SZ 16 19#define CAIF_LAYER_NAME_SZ 16
24#define CAIF_SUCCESS 1
25#define CAIF_FAILURE 0
26 20
27/** 21/**
28 * caif_assert() - Assert function for CAIF. 22 * caif_assert() - Assert function for CAIF.
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
index 9fc2fc20b884..bd646faffa47 100644
--- a/include/net/caif/cfcnfg.h
+++ b/include/net/caif/cfcnfg.h
@@ -7,6 +7,7 @@
7#ifndef CFCNFG_H_ 7#ifndef CFCNFG_H_
8#define CFCNFG_H_ 8#define CFCNFG_H_
9#include <linux/spinlock.h> 9#include <linux/spinlock.h>
10#include <linux/netdevice.h>
10#include <net/caif/caif_layer.h> 11#include <net/caif/caif_layer.h>
11#include <net/caif/cfctrl.h> 12#include <net/caif/cfctrl.h>
12 13
@@ -73,8 +74,8 @@ void cfcnfg_remove(struct cfcnfg *cfg);
73 74
74void 75void
75cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, 76cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
76 void *dev, struct cflayer *phy_layer, u16 *phyid, 77 struct net_device *dev, struct cflayer *phy_layer,
77 enum cfcnfg_phy_preference pref, 78 u16 *phyid, enum cfcnfg_phy_preference pref,
78 bool fcs, bool stx); 79 bool fcs, bool stx);
79 80
80/** 81/**
@@ -114,11 +115,18 @@ void cfcnfg_release_adap_layer(struct cflayer *adap_layer);
114 * @param: Link setup parameters. 115 * @param: Link setup parameters.
115 * @adap_layer: Specify the adaptation layer; the receive and 116 * @adap_layer: Specify the adaptation layer; the receive and
116 * flow-control functions MUST be set in the structure. 117 * flow-control functions MUST be set in the structure.
117 * 118 * @ifindex: Link layer interface index used for this connection.
119 * @proto_head: Protocol head-space needed by CAIF protocol,
120 * excluding link layer.
121 * @proto_tail: Protocol tail-space needed by CAIF protocol,
122 * excluding link layer.
118 */ 123 */
119int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, 124int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
120 struct cfctrl_link_param *param, 125 struct cfctrl_link_param *param,
121 struct cflayer *adap_layer); 126 struct cflayer *adap_layer,
127 int *ifindex,
128 int *proto_head,
129 int *proto_tail);
122 130
123/** 131/**
124 * cfcnfg_get_phyid() - Get physical ID, given type. 132 * cfcnfg_get_phyid() - Get physical ID, given type.
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index e2b86f1f5a47..0b586e9d1378 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -255,7 +255,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
255 pref = CFPHYPREF_HIGH_BW; 255 pref = CFPHYPREF_HIGH_BW;
256 break; 256 break;
257 } 257 }
258 258 dev_hold(dev);
259 cfcnfg_add_phy_layer(get_caif_conf(), 259 cfcnfg_add_phy_layer(get_caif_conf(),
260 phy_type, 260 phy_type,
261 dev, 261 dev,
@@ -285,6 +285,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
285 caifd->layer.up->ctrlcmd(caifd->layer.up, 285 caifd->layer.up->ctrlcmd(caifd->layer.up,
286 _CAIF_CTRLCMD_PHYIF_DOWN_IND, 286 _CAIF_CTRLCMD_PHYIF_DOWN_IND,
287 caifd->layer.id); 287 caifd->layer.id);
288 might_sleep();
288 res = wait_event_interruptible_timeout(caifd->event, 289 res = wait_event_interruptible_timeout(caifd->event,
289 atomic_read(&caifd->in_use) == 0, 290 atomic_read(&caifd->in_use) == 0,
290 TIMEOUT); 291 TIMEOUT);
@@ -300,6 +301,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
300 "Unregistering an active CAIF device: %s\n", 301 "Unregistering an active CAIF device: %s\n",
301 __func__, dev->name); 302 __func__, dev->name);
302 cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer); 303 cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer);
304 dev_put(dev);
303 atomic_set(&caifd->state, what); 305 atomic_set(&caifd->state, what);
304 break; 306 break;
305 307
@@ -326,7 +328,8 @@ struct cfcnfg *get_caif_conf(void)
326EXPORT_SYMBOL(get_caif_conf); 328EXPORT_SYMBOL(get_caif_conf);
327 329
328int caif_connect_client(struct caif_connect_request *conn_req, 330int caif_connect_client(struct caif_connect_request *conn_req,
329 struct cflayer *client_layer) 331 struct cflayer *client_layer, int *ifindex,
332 int *headroom, int *tailroom)
330{ 333{
331 struct cfctrl_link_param param; 334 struct cfctrl_link_param param;
332 int ret; 335 int ret;
@@ -334,8 +337,9 @@ int caif_connect_client(struct caif_connect_request *conn_req,
334 if (ret) 337 if (ret)
335 return ret; 338 return ret;
336 /* Hook up the adaptation layer. */ 339 /* Hook up the adaptation layer. */
337 return cfcnfg_add_adaptation_layer(get_caif_conf(), 340 return cfcnfg_add_adaptation_layer(get_caif_conf(), &param,
338 &param, client_layer); 341 client_layer, ifindex,
342 headroom, tailroom);
339} 343}
340EXPORT_SYMBOL(caif_connect_client); 344EXPORT_SYMBOL(caif_connect_client);
341 345
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 848ae755cdd6..8ce904786116 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -28,8 +28,8 @@
28MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
29MODULE_ALIAS_NETPROTO(AF_CAIF); 29MODULE_ALIAS_NETPROTO(AF_CAIF);
30 30
31#define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10) 31#define CAIF_DEF_SNDBUF (4096*10)
32#define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100) 32#define CAIF_DEF_RCVBUF (4096*100)
33 33
34/* 34/*
35 * CAIF state is re-using the TCP socket states. 35 * CAIF state is re-using the TCP socket states.
@@ -76,6 +76,7 @@ struct caifsock {
76 struct caif_connect_request conn_req; 76 struct caif_connect_request conn_req;
77 struct mutex readlock; 77 struct mutex readlock;
78 struct dentry *debugfs_socket_dir; 78 struct dentry *debugfs_socket_dir;
79 int headroom, tailroom, maxframe;
79}; 80};
80 81
81static int rx_flow_is_on(struct caifsock *cf_sk) 82static int rx_flow_is_on(struct caifsock *cf_sk)
@@ -594,23 +595,32 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock,
594 goto err; 595 goto err;
595 noblock = msg->msg_flags & MSG_DONTWAIT; 596 noblock = msg->msg_flags & MSG_DONTWAIT;
596 597
597 buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM;
598
599 timeo = sock_sndtimeo(sk, noblock); 598 timeo = sock_sndtimeo(sk, noblock);
600 timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), 599 timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk),
601 1, timeo, &ret); 600 1, timeo, &ret);
602 601
602 if (ret)
603 goto err;
603 ret = -EPIPE; 604 ret = -EPIPE;
604 if (cf_sk->sk.sk_state != CAIF_CONNECTED || 605 if (cf_sk->sk.sk_state != CAIF_CONNECTED ||
605 sock_flag(sk, SOCK_DEAD) || 606 sock_flag(sk, SOCK_DEAD) ||
606 (sk->sk_shutdown & RCV_SHUTDOWN)) 607 (sk->sk_shutdown & RCV_SHUTDOWN))
607 goto err; 608 goto err;
608 609
610 /* Error if trying to write more than maximum frame size. */
611 ret = -EMSGSIZE;
612 if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM)
613 goto err;
614
615 buffer_size = len + cf_sk->headroom + cf_sk->tailroom;
616
609 ret = -ENOMEM; 617 ret = -ENOMEM;
610 skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); 618 skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret);
611 if (!skb) 619
620 if (!skb || skb_tailroom(skb) < buffer_size)
612 goto err; 621 goto err;
613 skb_reserve(skb, CAIF_NEEDED_HEADROOM); 622
623 skb_reserve(skb, cf_sk->headroom);
614 624
615 ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); 625 ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
616 626
@@ -641,7 +651,6 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
641 long timeo; 651 long timeo;
642 652
643 err = -EOPNOTSUPP; 653 err = -EOPNOTSUPP;
644
645 if (unlikely(msg->msg_flags&MSG_OOB)) 654 if (unlikely(msg->msg_flags&MSG_OOB))
646 goto out_err; 655 goto out_err;
647 656
@@ -658,8 +667,8 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
658 667
659 size = len-sent; 668 size = len-sent;
660 669
661 if (size > CAIF_MAX_PAYLOAD_SIZE) 670 if (size > cf_sk->maxframe)
662 size = CAIF_MAX_PAYLOAD_SIZE; 671 size = cf_sk->maxframe;
663 672
664 /* If size is more than half of sndbuf, chop up message */ 673 /* If size is more than half of sndbuf, chop up message */
665 if (size > ((sk->sk_sndbuf >> 1) - 64)) 674 if (size > ((sk->sk_sndbuf >> 1) - 64))
@@ -669,14 +678,14 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
669 size = SKB_MAX_ALLOC; 678 size = SKB_MAX_ALLOC;
670 679
671 skb = sock_alloc_send_skb(sk, 680 skb = sock_alloc_send_skb(sk,
672 size + CAIF_NEEDED_HEADROOM 681 size + cf_sk->headroom +
673 + CAIF_NEEDED_TAILROOM, 682 cf_sk->tailroom,
674 msg->msg_flags&MSG_DONTWAIT, 683 msg->msg_flags&MSG_DONTWAIT,
675 &err); 684 &err);
676 if (skb == NULL) 685 if (skb == NULL)
677 goto out_err; 686 goto out_err;
678 687
679 skb_reserve(skb, CAIF_NEEDED_HEADROOM); 688 skb_reserve(skb, cf_sk->headroom);
680 /* 689 /*
681 * If you pass two values to the sock_alloc_send_skb 690 * If you pass two values to the sock_alloc_send_skb
682 * it tries to grab the large buffer with GFP_NOFS 691 * it tries to grab the large buffer with GFP_NOFS
@@ -817,17 +826,15 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
817 struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 826 struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
818 long timeo; 827 long timeo;
819 int err; 828 int err;
829 int ifindex, headroom, tailroom;
830 struct net_device *dev;
831
820 lock_sock(sk); 832 lock_sock(sk);
821 833
822 err = -EAFNOSUPPORT; 834 err = -EAFNOSUPPORT;
823 if (uaddr->sa_family != AF_CAIF) 835 if (uaddr->sa_family != AF_CAIF)
824 goto out; 836 goto out;
825 837
826 err = -ESOCKTNOSUPPORT;
827 if (unlikely(!(sk->sk_type == SOCK_STREAM &&
828 cf_sk->sk.sk_protocol == CAIFPROTO_AT) &&
829 sk->sk_type != SOCK_SEQPACKET))
830 goto out;
831 switch (sock->state) { 838 switch (sock->state) {
832 case SS_UNCONNECTED: 839 case SS_UNCONNECTED:
833 /* Normal case, a fresh connect */ 840 /* Normal case, a fresh connect */
@@ -883,12 +890,23 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
883 dbfs_atomic_inc(&cnt.num_connect_req); 890 dbfs_atomic_inc(&cnt.num_connect_req);
884 cf_sk->layer.receive = caif_sktrecv_cb; 891 cf_sk->layer.receive = caif_sktrecv_cb;
885 err = caif_connect_client(&cf_sk->conn_req, 892 err = caif_connect_client(&cf_sk->conn_req,
886 &cf_sk->layer); 893 &cf_sk->layer, &ifindex, &headroom, &tailroom);
887 if (err < 0) { 894 if (err < 0) {
888 cf_sk->sk.sk_socket->state = SS_UNCONNECTED; 895 cf_sk->sk.sk_socket->state = SS_UNCONNECTED;
889 cf_sk->sk.sk_state = CAIF_DISCONNECTED; 896 cf_sk->sk.sk_state = CAIF_DISCONNECTED;
890 goto out; 897 goto out;
891 } 898 }
899 dev = dev_get_by_index(sock_net(sk), ifindex);
900 cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom);
901 cf_sk->tailroom = tailroom;
902 cf_sk->maxframe = dev->mtu - (headroom + tailroom);
903 dev_put(dev);
904 if (cf_sk->maxframe < 1) {
905 pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n",
906 __func__, dev->mtu);
907 err = -ENODEV;
908 goto out;
909 }
892 910
893 err = -EINPROGRESS; 911 err = -EINPROGRESS;
894wait_connect: 912wait_connect:
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index cff2dcb9efe4..1c29189b344d 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -6,6 +6,7 @@
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/stddef.h> 7#include <linux/stddef.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/netdevice.h>
9#include <net/caif/caif_layer.h> 10#include <net/caif/caif_layer.h>
10#include <net/caif/cfpkt.h> 11#include <net/caif/cfpkt.h>
11#include <net/caif/cfcnfg.h> 12#include <net/caif/cfcnfg.h>
@@ -42,6 +43,15 @@ struct cfcnfg_phyinfo {
42 43
43 /* Information about the physical device */ 44 /* Information about the physical device */
44 struct dev_info dev_info; 45 struct dev_info dev_info;
46
47 /* Interface index */
48 int ifindex;
49
50 /* Use Start of frame extension */
51 bool use_stx;
52
53 /* Use Start of frame checksum */
54 bool use_fcs;
45}; 55};
46 56
47struct cfcnfg { 57struct cfcnfg {
@@ -249,9 +259,20 @@ static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
249{ 259{
250} 260}
251 261
262int protohead[CFCTRL_SRV_MASK] = {
263 [CFCTRL_SRV_VEI] = 4,
264 [CFCTRL_SRV_DATAGRAM] = 7,
265 [CFCTRL_SRV_UTIL] = 4,
266 [CFCTRL_SRV_RFM] = 3,
267 [CFCTRL_SRV_DBG] = 3,
268};
269
252int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, 270int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
253 struct cfctrl_link_param *param, 271 struct cfctrl_link_param *param,
254 struct cflayer *adap_layer) 272 struct cflayer *adap_layer,
273 int *ifindex,
274 int *proto_head,
275 int *proto_tail)
255{ 276{
256 struct cflayer *frml; 277 struct cflayer *frml;
257 if (adap_layer == NULL) { 278 if (adap_layer == NULL) {
@@ -277,6 +298,14 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
277 param->phyid); 298 param->phyid);
278 caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id == 299 caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id ==
279 param->phyid); 300 param->phyid);
301
302 *ifindex = cnfg->phy_layers[param->phyid].ifindex;
303 *proto_head =
304 protohead[param->linktype]+
305 (cnfg->phy_layers[param->phyid].use_stx ? 1 : 0);
306
307 *proto_tail = 2;
308
280 /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ 309 /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
281 cfctrl_enum_req(cnfg->ctrl, param->phyid); 310 cfctrl_enum_req(cnfg->ctrl, param->phyid);
282 return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); 311 return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
@@ -298,6 +327,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
298 struct cfcnfg *cnfg = container_obj(layer); 327 struct cfcnfg *cnfg = container_obj(layer);
299 struct cflayer *servicel = NULL; 328 struct cflayer *servicel = NULL;
300 struct cfcnfg_phyinfo *phyinfo; 329 struct cfcnfg_phyinfo *phyinfo;
330 struct net_device *netdev;
331
301 if (adapt_layer == NULL) { 332 if (adapt_layer == NULL) {
302 pr_debug("CAIF: %s(): link setup response " 333 pr_debug("CAIF: %s(): link setup response "
303 "but no client exist, send linkdown back\n", 334 "but no client exist, send linkdown back\n",
@@ -329,8 +360,9 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
329 servicel = cfdgml_create(channel_id, &phyinfo->dev_info); 360 servicel = cfdgml_create(channel_id, &phyinfo->dev_info);
330 break; 361 break;
331 case CFCTRL_SRV_RFM: 362 case CFCTRL_SRV_RFM:
363 netdev = phyinfo->dev_info.dev;
332 servicel = cfrfml_create(channel_id, &phyinfo->dev_info, 364 servicel = cfrfml_create(channel_id, &phyinfo->dev_info,
333 RFM_FRAGMENT_SIZE); 365 netdev->mtu);
334 break; 366 break;
335 case CFCTRL_SRV_UTIL: 367 case CFCTRL_SRV_UTIL:
336 servicel = cfutill_create(channel_id, &phyinfo->dev_info); 368 servicel = cfutill_create(channel_id, &phyinfo->dev_info);
@@ -361,8 +393,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
361 393
362void 394void
363cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, 395cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
364 void *dev, struct cflayer *phy_layer, u16 *phyid, 396 struct net_device *dev, struct cflayer *phy_layer,
365 enum cfcnfg_phy_preference pref, 397 u16 *phyid, enum cfcnfg_phy_preference pref,
366 bool fcs, bool stx) 398 bool fcs, bool stx)
367{ 399{
368 struct cflayer *frml; 400 struct cflayer *frml;
@@ -416,6 +448,10 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
416 cnfg->phy_layers[*phyid].dev_info.dev = dev; 448 cnfg->phy_layers[*phyid].dev_info.dev = dev;
417 cnfg->phy_layers[*phyid].phy_layer = phy_layer; 449 cnfg->phy_layers[*phyid].phy_layer = phy_layer;
418 cnfg->phy_layers[*phyid].phy_ref_count = 0; 450 cnfg->phy_layers[*phyid].phy_ref_count = 0;
451 cnfg->phy_layers[*phyid].ifindex = dev->ifindex;
452 cnfg->phy_layers[*phyid].use_stx = stx;
453 cnfg->phy_layers[*phyid].use_fcs = fcs;
454
419 phy_layer->type = phy_type; 455 phy_layer->type = phy_type;
420 frml = cffrml_create(*phyid, fcs); 456 frml = cffrml_create(*phyid, fcs);
421 if (!frml) { 457 if (!frml) {
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 107c4b2a311e..563145fdc4c3 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -19,7 +19,7 @@
19#ifdef CAIF_NO_LOOP 19#ifdef CAIF_NO_LOOP
20static int handle_loop(struct cfctrl *ctrl, 20static int handle_loop(struct cfctrl *ctrl,
21 int cmd, struct cfpkt *pkt){ 21 int cmd, struct cfpkt *pkt){
22 return CAIF_FAILURE; 22 return -1;
23} 23}
24#else 24#else
25static int handle_loop(struct cfctrl *ctrl, 25static int handle_loop(struct cfctrl *ctrl,
@@ -395,7 +395,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
395 cmd = cmdrsp & CFCTRL_CMD_MASK; 395 cmd = cmdrsp & CFCTRL_CMD_MASK;
396 if (cmd != CFCTRL_CMD_LINK_ERR 396 if (cmd != CFCTRL_CMD_LINK_ERR
397 && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { 397 && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) {
398 if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) 398 if (handle_loop(cfctrl, cmd, pkt) != 0)
399 cmdrsp |= CFCTRL_ERR_BIT; 399 cmdrsp |= CFCTRL_ERR_BIT;
400 } 400 }
401 401
@@ -647,6 +647,6 @@ found:
647 default: 647 default:
648 break; 648 break;
649 } 649 }
650 return CAIF_SUCCESS; 650 return 0;
651} 651}
652#endif 652#endif
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c
index 32d9f0dc8463..ed9d53aff280 100644
--- a/net/caif/cfdgml.c
+++ b/net/caif/cfdgml.c
@@ -17,6 +17,7 @@
17#define DGM_FLOW_OFF 0x81 17#define DGM_FLOW_OFF 0x81
18#define DGM_FLOW_ON 0x80 18#define DGM_FLOW_ON 0x80
19#define DGM_CTRL_PKT_SIZE 1 19#define DGM_CTRL_PKT_SIZE 1
20#define DGM_MTU 1500
20 21
21static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt); 22static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt);
22static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt); 23static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt);
@@ -89,6 +90,10 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
89 if (!cfsrvl_ready(service, &ret)) 90 if (!cfsrvl_ready(service, &ret))
90 return ret; 91 return ret;
91 92
93 /* STE Modem cannot handle more than 1500 bytes datagrams */
94 if (cfpkt_getlen(pkt) > DGM_MTU)
95 return -EMSGSIZE;
96
92 cfpkt_add_head(pkt, &zero, 4); 97 cfpkt_add_head(pkt, &zero, 4);
93 98
94 /* Add info for MUX-layer to route the packet out. */ 99 /* Add info for MUX-layer to route the packet out. */
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
index 318b0f4b416e..01f238ff2346 100644
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -9,8 +9,8 @@
9#include <linux/hardirq.h> 9#include <linux/hardirq.h>
10#include <net/caif/cfpkt.h> 10#include <net/caif/cfpkt.h>
11 11
12#define PKT_PREFIX CAIF_NEEDED_HEADROOM 12#define PKT_PREFIX 16
13#define PKT_POSTFIX CAIF_NEEDED_TAILROOM 13#define PKT_POSTFIX 2
14#define PKT_LEN_WHEN_EXTENDING 128 14#define PKT_LEN_WHEN_EXTENDING 128
15#define PKT_ERROR(pkt, errmsg) do { \ 15#define PKT_ERROR(pkt, errmsg) do { \
16 cfpkt_priv(pkt)->erronous = true; \ 16 cfpkt_priv(pkt)->erronous = true; \
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
index 965c5baace40..a11fbd68a13d 100644
--- a/net/caif/cfserl.c
+++ b/net/caif/cfserl.c
@@ -14,7 +14,8 @@
14#define container_obj(layr) ((struct cfserl *) layr) 14#define container_obj(layr) ((struct cfserl *) layr)
15 15
16#define CFSERL_STX 0x02 16#define CFSERL_STX 0x02
17#define CAIF_MINIUM_PACKET_SIZE 4 17#define SERIAL_MINIUM_PACKET_SIZE 4
18#define SERIAL_MAX_FRAMESIZE 4096
18struct cfserl { 19struct cfserl {
19 struct cflayer layer; 20 struct cflayer layer;
20 struct cfpkt *incomplete_frm; 21 struct cfpkt *incomplete_frm;
@@ -119,8 +120,8 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
119 /* 120 /*
120 * Frame error handling 121 * Frame error handling
121 */ 122 */
122 if (expectlen < CAIF_MINIUM_PACKET_SIZE 123 if (expectlen < SERIAL_MINIUM_PACKET_SIZE
123 || expectlen > CAIF_MAX_FRAMESIZE) { 124 || expectlen > SERIAL_MAX_FRAMESIZE) {
124 if (!layr->usestx) { 125 if (!layr->usestx) {
125 if (pkt != NULL) 126 if (pkt != NULL)
126 cfpkt_destroy(pkt); 127 cfpkt_destroy(pkt);
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
index 4c9f147c38af..f40939a91211 100644
--- a/net/caif/cfsrvl.c
+++ b/net/caif/cfsrvl.c
@@ -162,7 +162,6 @@ void cfservl_destroy(struct cflayer *layer)
162void cfsrvl_release(struct kref *kref) 162void cfsrvl_release(struct kref *kref)
163{ 163{
164 struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); 164 struct cfsrvl *service = container_of(kref, struct cfsrvl, ref);
165 pr_info("CAIF: %s(): enter\n", __func__);
166 kfree(service); 165 kfree(service);
167} 166}
168 167
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c
index ce525cac9064..02795aff57a4 100644
--- a/net/caif/cfutill.c
+++ b/net/caif/cfutill.c
@@ -90,12 +90,6 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt)
90 if (!cfsrvl_ready(service, &ret)) 90 if (!cfsrvl_ready(service, &ret))
91 return ret; 91 return ret;
92 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); 93 cfpkt_add_head(pkt, &zero, 1);
100 /* Add info for MUX-layer to route the packet out. */ 94 /* Add info for MUX-layer to route the packet out. */
101 info = cfpkt_info(pkt); 95 info = cfpkt_info(pkt);
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
index 637cb0eee13c..77cc09faac9a 100644
--- a/net/caif/cfveil.c
+++ b/net/caif/cfveil.c
@@ -84,11 +84,6 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
84 return ret; 84 return ret;
85 caif_assert(layr->dn != NULL); 85 caif_assert(layr->dn != NULL);
86 caif_assert(layr->dn->transmit != 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 87
93 if (cfpkt_add_head(pkt, &tmp, 1) < 0) { 88 if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
94 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); 89 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 610966abe2dc..4293e190ec53 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -23,7 +23,7 @@
23#include <net/caif/caif_dev.h> 23#include <net/caif/caif_dev.h>
24 24
25/* GPRS PDP connection has MTU to 1500 */ 25/* GPRS PDP connection has MTU to 1500 */
26#define SIZE_MTU 1500 26#define GPRS_PDP_MTU 1500
27/* 5 sec. connect timeout */ 27/* 5 sec. connect timeout */
28#define CONNECT_TIMEOUT (5 * HZ) 28#define CONNECT_TIMEOUT (5 * HZ)
29#define CAIF_NET_DEFAULT_QUEUE_LEN 500 29#define CAIF_NET_DEFAULT_QUEUE_LEN 500
@@ -232,6 +232,8 @@ static int chnl_net_open(struct net_device *dev)
232{ 232{
233 struct chnl_net *priv = NULL; 233 struct chnl_net *priv = NULL;
234 int result = -1; 234 int result = -1;
235 int llifindex, headroom, tailroom, mtu;
236 struct net_device *lldev;
235 ASSERT_RTNL(); 237 ASSERT_RTNL();
236 priv = netdev_priv(dev); 238 priv = netdev_priv(dev);
237 if (!priv) { 239 if (!priv) {
@@ -241,41 +243,88 @@ static int chnl_net_open(struct net_device *dev)
241 243
242 if (priv->state != CAIF_CONNECTING) { 244 if (priv->state != CAIF_CONNECTING) {
243 priv->state = CAIF_CONNECTING; 245 priv->state = CAIF_CONNECTING;
244 result = caif_connect_client(&priv->conn_req, &priv->chnl); 246 result = caif_connect_client(&priv->conn_req, &priv->chnl,
247 &llifindex, &headroom, &tailroom);
245 if (result != 0) { 248 if (result != 0) {
246 priv->state = CAIF_DISCONNECTED;
247 pr_debug("CAIF: %s(): err: " 249 pr_debug("CAIF: %s(): err: "
248 "Unable to register and open device," 250 "Unable to register and open device,"
249 " Err:%d\n", 251 " Err:%d\n",
250 __func__, 252 __func__,
251 result); 253 result);
252 return result; 254 goto error;
255 }
256
257 lldev = dev_get_by_index(dev_net(dev), llifindex);
258
259 if (lldev == NULL) {
260 pr_debug("CAIF: %s(): no interface?\n", __func__);
261 result = -ENODEV;
262 goto error;
263 }
264
265 dev->needed_tailroom = tailroom + lldev->needed_tailroom;
266 dev->hard_header_len = headroom + lldev->hard_header_len +
267 lldev->needed_tailroom;
268
269 /*
270 * MTU, head-room etc is not know before we have a
271 * CAIF link layer device available. MTU calculation may
272 * override initial RTNL configuration.
273 * MTU is minimum of current mtu, link layer mtu pluss
274 * CAIF head and tail, and PDP GPRS contexts max MTU.
275 */
276 mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom));
277 mtu = min_t(int, GPRS_PDP_MTU, mtu);
278 dev_set_mtu(dev, mtu);
279 dev_put(lldev);
280
281 if (mtu < 100) {
282 pr_warning("CAIF: %s(): "
283 "CAIF Interface MTU too small (%d)\n",
284 __func__, mtu);
285 result = -ENODEV;
286 goto error;
253 } 287 }
254 } 288 }
255 289
290 rtnl_unlock(); /* Release RTNL lock during connect wait */
291
256 result = wait_event_interruptible_timeout(priv->netmgmt_wq, 292 result = wait_event_interruptible_timeout(priv->netmgmt_wq,
257 priv->state != CAIF_CONNECTING, 293 priv->state != CAIF_CONNECTING,
258 CONNECT_TIMEOUT); 294 CONNECT_TIMEOUT);
259 295
296 rtnl_lock();
297
260 if (result == -ERESTARTSYS) { 298 if (result == -ERESTARTSYS) {
261 pr_debug("CAIF: %s(): wait_event_interruptible" 299 pr_debug("CAIF: %s(): wait_event_interruptible"
262 " woken by a signal\n", __func__); 300 " woken by a signal\n", __func__);
263 return -ERESTARTSYS; 301 result = -ERESTARTSYS;
302 goto error;
264 } 303 }
304
265 if (result == 0) { 305 if (result == 0) {
266 pr_debug("CAIF: %s(): connect timeout\n", __func__); 306 pr_debug("CAIF: %s(): connect timeout\n", __func__);
267 caif_disconnect_client(&priv->chnl); 307 caif_disconnect_client(&priv->chnl);
268 priv->state = CAIF_DISCONNECTED; 308 priv->state = CAIF_DISCONNECTED;
269 pr_debug("CAIF: %s(): state disconnected\n", __func__); 309 pr_debug("CAIF: %s(): state disconnected\n", __func__);
270 return -ETIMEDOUT; 310 result = -ETIMEDOUT;
311 goto error;
271 } 312 }
272 313
273 if (priv->state != CAIF_CONNECTED) { 314 if (priv->state != CAIF_CONNECTED) {
274 pr_debug("CAIF: %s(): connect failed\n", __func__); 315 pr_debug("CAIF: %s(): connect failed\n", __func__);
275 return -ECONNREFUSED; 316 result = -ECONNREFUSED;
317 goto error;
276 } 318 }
277 pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__); 319 pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__);
278 return 0; 320 return 0;
321
322error:
323 caif_disconnect_client(&priv->chnl);
324 priv->state = CAIF_DISCONNECTED;
325 pr_debug("CAIF: %s(): state disconnected\n", __func__);
326 return result;
327
279} 328}
280 329
281static int chnl_net_stop(struct net_device *dev) 330static int chnl_net_stop(struct net_device *dev)
@@ -321,9 +370,7 @@ static void ipcaif_net_setup(struct net_device *dev)
321 dev->destructor = free_netdev; 370 dev->destructor = free_netdev;
322 dev->flags |= IFF_NOARP; 371 dev->flags |= IFF_NOARP;
323 dev->flags |= IFF_POINTOPOINT; 372 dev->flags |= IFF_POINTOPOINT;
324 dev->needed_headroom = CAIF_NEEDED_HEADROOM; 373 dev->mtu = GPRS_PDP_MTU;
325 dev->needed_tailroom = CAIF_NEEDED_TAILROOM;
326 dev->mtu = SIZE_MTU;
327 dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN; 374 dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN;
328 375
329 priv = netdev_priv(dev); 376 priv = netdev_priv(dev);