net: qrtr: use alloc_skb_with_frags() in rx path

net_dev_alloc() fails for high order allocations in system where memory
is fragmented and cause communication stall due to packet drops.

Use alloc_skb_with_frags() to avoid packet drops in memory fragmented case.

This change squashes the following commits from msm-4.14:
  commit 5121b211a5e6 ("net: qrtr: Use skb with fragments in memory
                        failure case")
  commit bdc91a0dae07 ("net: qrtr: use alloc_skb_with_frag() in rx path")

In addition, fix minor format issues and update the copyright.

Change-Id: I46b7e0da0ed04c9222c975ee930f0f8d9b41453b
Signed-off-by: Arun Kumar Neelakantam <aneela@codeaurora.org>
This commit is contained in:
Arun Kumar Neelakantam 2019-05-28 14:53:11 +05:30 • committed by Chris Lew
commit 33685bb27f

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015, Sony Mobile Communications Inc.
* Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2013, 2018-2019 The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
#include <linux/netlink.h>
@ -248,12 +248,15 @@ static void qrtr_node_release(struct qrtr_node *node)
*/
static void qrtr_tx_resume(struct qrtr_node *node, struct sk_buff *skb)
{
struct qrtr_ctrl_pkt *pkt = (struct qrtr_ctrl_pkt *)skb->data;
u64 remote_node = le32_to_cpu(pkt->client.node);
u32 remote_port = le32_to_cpu(pkt->client.port);
struct qrtr_ctrl_pkt pkt = {0,};
struct qrtr_tx_flow *flow;
unsigned long key;
u64 remote_node;
u32 remote_port;
skb_copy_bits(skb, 0, &pkt, sizeof(pkt));
remote_node = le32_to_cpu(pkt.client.node);
remote_port = le32_to_cpu(pkt.client.port);
key = remote_node << 32 | remote_port;
flow = radix_tree_lookup(&node->qrtr_tx_flow, key);
@ -471,14 +474,16 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
unsigned int size;
unsigned int ver;
size_t hdrlen;
int errcode;
if (len & 3)
return -EINVAL;
skb = netdev_alloc_skb(NULL, len);
skb = alloc_skb_with_frags(sizeof(*v1), len, 0, &errcode, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
skb_reserve(skb, sizeof(*v1));
cb = (struct qrtr_cb *)skb->cb;
/* Version field in v1 is little endian, so this works for both cases */
@ -528,7 +533,9 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
cb->type != QRTR_TYPE_RESUME_TX)
goto err;
skb_put_data(skb, data + hdrlen, size);
skb->data_len = size;
skb->len = size;
skb_store_bits(skb, 0, data + hdrlen, size);
qrtr_node_assign(node, cb->src_node);