From 33685bb27f53c4630d5e01a04ff9427d0e462b81 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Tue, 28 May 2019 14:53:11 +0530 Subject: [PATCH] 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 --- net/qrtr/qrtr.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 8f2320410e38..7c2b9d925af5 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -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 #include @@ -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);