Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 238965b7 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller
Browse files

net/af_iucv: build proper skbs for HiperTransport



The HiperSockets-based transport path in af_iucv is still too closely
entangled with qeth.
With commit a647a025 ("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: a647a025 ("s390/qeth: speed-up L3 IQD xmit")
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fdbf6326
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -14,6 +14,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>
@@ -347,14 +348,14 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
	if (imsg)
		memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message));

	skb_push(skb, ETH_HLEN);
	memset(skb->data, 0, ETH_HLEN);

	skb->dev = iucv->hs_dev;
	if (!skb->dev) {
		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 +368,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 +469,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;
@@ -1133,7 +1138,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) {