diff options
| -rw-r--r-- | net/iucv/af_iucv.c | 49 | 
1 files changed, 36 insertions, 13 deletions
| diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 36eb8d1d9128..09e1694b6d34 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -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 @@ vm_bind:  		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 @@ out:  	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,12 +2505,11 @@ out:  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); +	} + +	unregister_netdevice_notifier(&afiucv_netdev_notifier);  	dev_remove_pack(&iucv_packet_type);  	sock_unregister(PF_IUCV);  	proto_unregister(&iucv_proto); | 

