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

Commit 99838e60 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'af_iucv-fixes'



Julian Wiedmann says:

====================
net/af_iucv: fixes 2019-06-18

I spent a few cycles on transmit problems for af_iucv over regular
netdevices - please apply the following fixes to -net.

The first patch allows for skb allocations outside of GFP_DMA, while the
second patch respects that drivers might use skb_cow_head() and/or want
additional dev->needed_headroom.
Patch 3 is for a separate issue, where we didn't setup some of the
netdevice-specific infrastructure when running as a z/VM guest.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 48620e34 06996c1d
Loading
Loading
Loading
Loading
+36 −13
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;
@@ -588,7 +593,6 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio,

	sk->sk_destruct = iucv_sock_destruct;
	sk->sk_sndtimeo = IUCV_CONN_TIMEOUT;
	sk->sk_allocation = GFP_DMA;

	sock_reset_flag(sk, SOCK_ZAPPED);

@@ -782,6 +786,7 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
		memcpy(iucv->src_user_id, iucv_userid, 8);
		sk->sk_state = IUCV_BOUND;
		iucv->transport = AF_IUCV_TRANS_IUCV;
		sk->sk_allocation |= GFP_DMA;
		if (!iucv->msglimit)
			iucv->msglimit = IUCV_QUEUELEN_DEFAULT;
		goto done_unlock;
@@ -806,6 +811,8 @@ static int iucv_sock_autobind(struct sock *sk)
		return -EPROTO;

	memcpy(iucv->src_user_id, iucv_userid, 8);
	iucv->transport = AF_IUCV_TRANS_IUCV;
	sk->sk_allocation |= GFP_DMA;

	write_lock_bh(&iucv_sk_list.lock);
	__iucv_auto_name(iucv);
@@ -1131,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) {
@@ -1781,6 +1789,8 @@ static int iucv_callback_connreq(struct iucv_path *path,

	niucv = iucv_sk(nsk);
	iucv_sock_init(nsk, sk);
	niucv->transport = AF_IUCV_TRANS_IUCV;
	nsk->sk_allocation |= GFP_DMA;

	/* Set the new iucv_sock */
	memcpy(niucv->dst_name, ipuser + 8, 8);
@@ -2430,6 +2440,13 @@ static int afiucv_iucv_init(void)
	return err;
}

static void afiucv_iucv_exit(void)
{
	device_unregister(af_iucv_dev);
	driver_unregister(&af_iucv_driver);
	pr_iucv->iucv_unregister(&af_iucv_handler, 0);
}

static int __init afiucv_init(void)
{
	int err;
@@ -2463,11 +2480,18 @@ static int __init afiucv_init(void)
		err = afiucv_iucv_init();
		if (err)
			goto out_sock;
	} else
		register_netdevice_notifier(&afiucv_netdev_notifier);
	}

	err = register_netdevice_notifier(&afiucv_netdev_notifier);
	if (err)
		goto out_notifier;

	dev_add_pack(&iucv_packet_type);
	return 0;

out_notifier:
	if (pr_iucv)
		afiucv_iucv_exit();
out_sock:
	sock_unregister(PF_IUCV);
out_proto:
@@ -2481,11 +2505,10 @@ static int __init afiucv_init(void)
static void __exit afiucv_exit(void)
{
	if (pr_iucv) {
		device_unregister(af_iucv_dev);
		driver_unregister(&af_iucv_driver);
		pr_iucv->iucv_unregister(&af_iucv_handler, 0);
		afiucv_iucv_exit();
		symbol_put(iucv_if);
	} else
	}

	unregister_netdevice_notifier(&afiucv_netdev_notifier);
	dev_remove_pack(&iucv_packet_type);
	sock_unregister(PF_IUCV);