net/af_iucv: build proper skbs for HiperTransport
The HiperSockets-based transport path in af_iucv is still too closely entangled with qeth. With commita647a02512
("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:a647a02512
("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>
This commit is contained in:
Родитель
fdbf632691
Коммит
238965b71b
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче