Merge tag 'mailbox-v4.17' of git://git.linaro.org/landing-teams/working/fujitsu/integ...
[linux-2.6-microblaze.git] / net / core / sock.c
index 85b0b64..6444525 100644 (file)
@@ -1049,16 +1049,18 @@ set_rcvbuf:
                break;
 
        case SO_ZEROCOPY:
-               if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
+               if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6) {
+                       if (sk->sk_protocol != IPPROTO_TCP)
+                               ret = -ENOTSUPP;
+               } else if (sk->sk_family != PF_RDS) {
                        ret = -ENOTSUPP;
-               else if (sk->sk_protocol != IPPROTO_TCP)
-                       ret = -ENOTSUPP;
-               else if (sk->sk_state != TCP_CLOSE)
-                       ret = -EBUSY;
-               else if (val < 0 || val > 1)
-                       ret = -EINVAL;
-               else
-                       sock_valbool_flag(sk, SOCK_ZEROCOPY, valbool);
+               }
+               if (!ret) {
+                       if (val < 0 || val > 1)
+                               ret = -EINVAL;
+                       else
+                               sock_valbool_flag(sk, SOCK_ZEROCOPY, valbool);
+               }
                break;
 
        default:
@@ -1274,7 +1276,8 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
        {
                char address[128];
 
-               if (sock->ops->getname(sock, (struct sockaddr *)address, &lv, 2))
+               lv = sock->ops->getname(sock, (struct sockaddr *)address, 2);
+               if (lv < 0)
                        return -ENOTCONN;
                if (lv < len)
                        return -EINVAL;
@@ -1773,7 +1776,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
        u32 max_segs = 1;
 
        sk_dst_set(sk, dst);
-       sk->sk_route_caps = dst->dev->features;
+       sk->sk_route_caps = dst->dev->features | sk->sk_route_forced_caps;
        if (sk->sk_route_caps & NETIF_F_GSO)
                sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
        sk->sk_route_caps &= ~sk->sk_route_nocaps;
@@ -2234,6 +2237,67 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)
 }
 EXPORT_SYMBOL(sk_page_frag_refill);
 
+int sk_alloc_sg(struct sock *sk, int len, struct scatterlist *sg,
+               int sg_start, int *sg_curr_index, unsigned int *sg_curr_size,
+               int first_coalesce)
+{
+       int sg_curr = *sg_curr_index, use = 0, rc = 0;
+       unsigned int size = *sg_curr_size;
+       struct page_frag *pfrag;
+       struct scatterlist *sge;
+
+       len -= size;
+       pfrag = sk_page_frag(sk);
+
+       while (len > 0) {
+               unsigned int orig_offset;
+
+               if (!sk_page_frag_refill(sk, pfrag)) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+
+               use = min_t(int, len, pfrag->size - pfrag->offset);
+
+               if (!sk_wmem_schedule(sk, use)) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+
+               sk_mem_charge(sk, use);
+               size += use;
+               orig_offset = pfrag->offset;
+               pfrag->offset += use;
+
+               sge = sg + sg_curr - 1;
+               if (sg_curr > first_coalesce && sg_page(sg) == pfrag->page &&
+                   sg->offset + sg->length == orig_offset) {
+                       sg->length += use;
+               } else {
+                       sge = sg + sg_curr;
+                       sg_unmark_end(sge);
+                       sg_set_page(sge, pfrag->page, use, orig_offset);
+                       get_page(pfrag->page);
+                       sg_curr++;
+
+                       if (sg_curr == MAX_SKB_FRAGS)
+                               sg_curr = 0;
+
+                       if (sg_curr == sg_start) {
+                               rc = -ENOSPC;
+                               break;
+                       }
+               }
+
+               len -= use;
+       }
+out:
+       *sg_curr_size = size;
+       *sg_curr_index = sg_curr;
+       return rc;
+}
+EXPORT_SYMBOL(sk_alloc_sg);
+
 static void __lock_sock(struct sock *sk)
        __releases(&sk->sk_lock.slock)
        __acquires(&sk->sk_lock.slock)
@@ -2497,7 +2561,7 @@ int sock_no_accept(struct socket *sock, struct socket *newsock, int flags,
 EXPORT_SYMBOL(sock_no_accept);
 
 int sock_no_getname(struct socket *sock, struct sockaddr *saddr,
-                   int *len, int peer)
+                   int peer)
 {
        return -EOPNOTSUPP;
 }
@@ -3390,7 +3454,7 @@ static const struct file_operations proto_seq_fops = {
 
 static __net_init int proto_init_net(struct net *net)
 {
-       if (!proc_create("protocols", S_IRUGO, net->proc_net, &proto_seq_fops))
+       if (!proc_create("protocols", 0444, net->proc_net, &proto_seq_fops))
                return -ENOMEM;
 
        return 0;