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/caif/caif_socket.c | |
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/caif/caif_socket.c')
-rw-r--r-- | net/caif/caif_socket.c | 54 |
1 files changed, 36 insertions, 18 deletions
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: |