From 8749373dce7849eb9c11b39cb575db43f588c4c9 Mon Sep 17 00:00:00 2001 From: Mohit Khanna Date: Sun, 27 Aug 2017 23:26:44 -0700 Subject: [PATCH] qcacld-3.0: set gso_size for non linear tcp packets Currently, OL/TXRX is unable to handle non TSO packets which are non-linear. These packets have skb->gso_size as zero since they are not jumbo packets and dont need to be TSOed. However, TSO code can handle such packets. The current code assumes that non TSO packets will be linear. This may case an incorrect memory access leading to a crash. Fill in gso_size for non-linear TCP packets if it is zero. This lets the TSO logic handle these packets for CE transmission. Change-Id: I75c7759e1a35c462966a2d925db6f537670ad72f CRs-Fixed: 2100254 --- core/hdd/inc/wlan_hdd_tx_rx.h | 12 ++++++++++++ core/hdd/src/wlan_hdd_softap_tx_rx.c | 2 ++ core/hdd/src/wlan_hdd_tx_rx.c | 2 ++ 3 files changed, 16 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h index 1018d7d4c9fd..21e045bb5a24 100644 --- a/core/hdd/inc/wlan_hdd_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -167,4 +167,16 @@ static inline void netif_trans_update(struct net_device *dev) __func__, jiffies) #endif +static inline void +hdd_skb_fill_gso_size (struct net_device *dev, + struct sk_buff *skb) { + if (skb_cloned(skb) && skb_is_nonlinear(skb) && + skb_shinfo(skb)->gso_size == 0 && + ip_hdr(skb)->protocol == IPPROTO_TCP) { + skb_shinfo(skb)->gso_size = dev->mtu - + ((skb_transport_header(skb) - skb_network_header(skb)) + + tcp_hdrlen(skb)); + } +} + #endif /* end #if !defined(WLAN_HDD_TX_RX_H) */ diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index c25c8a40b238..bbb2e8e7c6df 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -253,6 +253,8 @@ static inline struct sk_buff *hdd_skb_orphan(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); #endif + hdd_skb_fill_gso_size(adapter->dev, skb); + nskb = skb_unshare(skb, GFP_ATOMIC); #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 19, 0)) if (unlikely(hdd_ctx->config->tx_orphan_enable) && (nskb == skb)) { diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index a2645b6851b2..6ac3021617de 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -332,6 +332,8 @@ static inline struct sk_buff *hdd_skb_orphan(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); #endif + hdd_skb_fill_gso_size(adapter->dev, skb); + nskb = skb_unshare(skb, GFP_ATOMIC); #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 19, 0)) if (unlikely(hdd_ctx->config->tx_orphan_enable) && (nskb == skb)) {