diff options
author | Sjur Braendeland <sjur.brandeland@stericsson.com> | 2010-06-17 02:55:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-20 22:46:06 -0400 |
commit | 2aa40aef9debc77d55cc87a50d335b6fe97fbeb0 (patch) | |
tree | 0dccf47cf6cb861c7efa72601fab9511760c7e74 /net | |
parent | a7da1f55a826c621251874e7684c234972fc3216 (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/caif/caif_dev.c | 12 | ||||
-rw-r--r-- | net/caif/caif_socket.c | 54 | ||||
-rw-r--r-- | net/caif/cfcnfg.c | 44 | ||||
-rw-r--r-- | net/caif/cfctrl.c | 6 | ||||
-rw-r--r-- | net/caif/cfdgml.c | 5 | ||||
-rw-r--r-- | net/caif/cfpkt_skbuff.c | 4 | ||||
-rw-r--r-- | net/caif/cfserl.c | 7 | ||||
-rw-r--r-- | net/caif/cfsrvl.c | 1 | ||||
-rw-r--r-- | net/caif/cfutill.c | 6 | ||||
-rw-r--r-- | net/caif/cfveil.c | 5 | ||||
-rw-r--r-- | net/caif/chnl_net.c | 67 |
11 files changed, 155 insertions, 56 deletions
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) | |||
326 | EXPORT_SYMBOL(get_caif_conf); | 328 | EXPORT_SYMBOL(get_caif_conf); |
327 | 329 | ||
328 | int caif_connect_client(struct caif_connect_request *conn_req, | 330 | int 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(), ¶m, |
338 | ¶m, client_layer); | 341 | client_layer, ifindex, |
342 | headroom, tailroom); | ||
339 | } | 343 | } |
340 | EXPORT_SYMBOL(caif_connect_client); | 344 | EXPORT_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 @@ | |||
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | MODULE_ALIAS_NETPROTO(AF_CAIF); | 29 | MODULE_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 | ||
81 | static int rx_flow_is_on(struct caifsock *cf_sk) | 82 | static 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; |
894 | wait_connect: | 912 | wait_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 | ||
47 | struct cfcnfg { | 57 | struct cfcnfg { |
@@ -249,9 +259,20 @@ static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) | |||
249 | { | 259 | { |
250 | } | 260 | } |
251 | 261 | ||
262 | int 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 | |||
252 | int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | 270 | int 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 | ||
362 | void | 394 | void |
363 | cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, | 395 | cfcnfg_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 |
20 | static int handle_loop(struct cfctrl *ctrl, | 20 | static 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 |
25 | static int handle_loop(struct cfctrl *ctrl, | 25 | static 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 | ||
21 | static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt); | 22 | static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt); |
22 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt); | 23 | static 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 | ||
18 | struct cfserl { | 19 | struct 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) | |||
162 | void cfsrvl_release(struct kref *kref) | 162 | void 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 | |||
322 | error: | ||
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 | ||
281 | static int chnl_net_stop(struct net_device *dev) | 330 | static 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); |