]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net/af_iucv: build proper skbs for HiperTransport
authorJulian Wiedmann <jwi@linux.ibm.com>
Tue, 18 Jun 2019 18:43:00 +0000 (20:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 27 Jan 2020 13:50:56 +0000 (14:50 +0100)
[ Upstream commit 238965b71b968dc5b3c0fe430e946f488322c4b5 ]

The HiperSockets-based transport path in af_iucv is still too closely
entangled with qeth.
With commit a647a02512ca ("s390/qeth: speed-up L3 IQD xmit"), the
relevant xmit code in qeth has begun to use skb_cow_head(). So to avoid
unnecessary skb head expansions, af_iucv must learn to
1) respect dev->needed_headroom when allocating skbs, and
2) drop the header reference before cloning the skb.

While at it, also stop hard-coding the LL-header creation stage and just
use the appropriate helper.

Fixes: a647a02512ca ("s390/qeth: speed-up L3 IQD xmit")
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/iucv/af_iucv.c

index f024914da1b2dca0815ebca9fbb09571902c6917..e07daee1227c35caca45797938e3be8071aeb3dd 100644 (file)
@@ -13,6 +13,7 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/module.h>
+#include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/errno.h>
@@ -355,6 +356,9 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
                err = -ENODEV;
                goto err_free;
        }
+
+       dev_hard_header(skb, skb->dev, ETH_P_AF_IUCV, NULL, NULL, skb->len);
+
        if (!(skb->dev->flags & IFF_UP) || !netif_carrier_ok(skb->dev)) {
                err = -ENETDOWN;
                goto err_free;
@@ -367,6 +371,8 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
                skb_trim(skb, skb->dev->mtu);
        }
        skb->protocol = cpu_to_be16(ETH_P_AF_IUCV);
+
+       __skb_header_release(skb);
        nskb = skb_clone(skb, GFP_ATOMIC);
        if (!nskb) {
                err = -ENOMEM;
@@ -466,12 +472,14 @@ static void iucv_sever_path(struct sock *sk, int with_user_data)
 /* Send controlling flags through an IUCV socket for HIPER transport */
 static int iucv_send_ctrl(struct sock *sk, u8 flags)
 {
+       struct iucv_sock *iucv = iucv_sk(sk);
        int err = 0;
        int blen;
        struct sk_buff *skb;
        u8 shutdown = 0;
 
-       blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+       blen = sizeof(struct af_iucv_trans_hdr) +
+              LL_RESERVED_SPACE(iucv->hs_dev);
        if (sk->sk_shutdown & SEND_SHUTDOWN) {
                /* controlling flags should be sent anyway */
                shutdown = sk->sk_shutdown;
@@ -1131,7 +1139,8 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg,
         * segmented records using the MSG_EOR flag), but
         * for SOCK_STREAM we might want to improve it in future */
        if (iucv->transport == AF_IUCV_TRANS_HIPER) {
-               headroom = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+               headroom = sizeof(struct af_iucv_trans_hdr) +
+                          LL_RESERVED_SPACE(iucv->hs_dev);
                linear = len;
        } else {
                if (len < PAGE_SIZE) {