From d47a415d8c41e05b2065c4715eccec9a435c9da7 Mon Sep 17 00:00:00 2001 From: Debabrata Purohit Date: Mon, 11 Mar 2019 19:13:53 +0000 Subject: [PATCH] [RAMEN9610-13159][common][MODAP-20690][9610] wlbt: NAPI: do not use GRO path in BA timer context When releasing frames from BA timer context, do not use napi_gro_receive() as that can corrupt the kernel GRO lists. Resolution: Use non-NAPI path when releasing frames from BA timer context. Change-Id: I9ac803e0a69d6eca3bb8c69e1be8bdfb152b4058 SCSC-Bug-Id: SSB-50448 Signed-off-by: Debabrata Purohit --- drivers/net/wireless/scsc/ba.c | 9 ++++----- drivers/net/wireless/scsc/ba.h | 4 ++-- drivers/net/wireless/scsc/dev.h | 2 +- drivers/net/wireless/scsc/sap_ma.c | 15 +++++++++------ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/scsc/ba.c b/drivers/net/wireless/scsc/ba.c index b268562ce354..40bb616da6af 100755 --- a/drivers/net/wireless/scsc/ba.c +++ b/drivers/net/wireless/scsc/ba.c @@ -92,14 +92,13 @@ static void slsi_rx_ba_free_buffer(struct net_device *dev, struct slsi_peer *pee * is called in the data workqueue context with the * netdev_vif mutex held. */ -void slsi_ba_process_complete(struct net_device *dev) +void slsi_ba_process_complete(struct net_device *dev, bool from_ba_timer) { struct netdev_vif *ndev_vif = netdev_priv(dev); struct sk_buff *skb; - while ((skb = slsi_skb_dequeue(&ndev_vif->ba_complete)) != NULL) { - slsi_rx_data_deliver_skb(ndev_vif->sdev, dev, skb); - } + while ((skb = slsi_skb_dequeue(&ndev_vif->ba_complete)) != NULL) + slsi_rx_data_deliver_skb(ndev_vif->sdev, dev, skb, from_ba_timer); } static void slsi_ba_signal_process_complete(struct net_device *dev) @@ -320,7 +319,7 @@ static void slsi_ba_aging_timeout_handler(unsigned long data) #ifdef CONFIG_SCSC_WLAN_RX_NAPI conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); if (conf_hip4_ver == 4) - slsi_ba_process_complete(dev); + slsi_ba_process_complete(dev, true); else slsi_ba_signal_process_complete(dev); #else diff --git a/drivers/net/wireless/scsc/ba.h b/drivers/net/wireless/scsc/ba.h index 0f977c3199a6..af442233ad7a 100755 --- a/drivers/net/wireless/scsc/ba.h +++ b/drivers/net/wireless/scsc/ba.h @@ -1,6 +1,6 @@ /***************************************************************************** * - * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved + * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved * ****************************************************************************/ @@ -16,7 +16,7 @@ void slsi_handle_blockack(struct net_device *dev, struct slsi_peer *peer, int slsi_ba_process_frame(struct net_device *dev, struct slsi_peer *peer, struct sk_buff *skb, u16 sequence_number, u16 tid); -void slsi_ba_process_complete(struct net_device *dev); +void slsi_ba_process_complete(struct net_device *dev, bool from_ba_timer); bool slsi_ba_check(struct slsi_peer *peer, u16 tid); diff --git a/drivers/net/wireless/scsc/dev.h b/drivers/net/wireless/scsc/dev.h index 186e6efc1e33..a73754f19a39 100755 --- a/drivers/net/wireless/scsc/dev.h +++ b/drivers/net/wireless/scsc/dev.h @@ -1135,7 +1135,7 @@ struct llc_snap_hdr { u16 snap_type; } __packed; -void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); +void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, bool from_ba_timer); void slsi_rx_dbg_sap_work(struct work_struct *work); void slsi_rx_netdev_data_work(struct work_struct *work); void slsi_rx_netdev_mlme_work(struct work_struct *work); diff --git a/drivers/net/wireless/scsc/sap_ma.c b/drivers/net/wireless/scsc/sap_ma.c index 26fa07b8aad8..4a09c1302ef6 100755 --- a/drivers/net/wireless/scsc/sap_ma.c +++ b/drivers/net/wireless/scsc/sap_ma.c @@ -190,7 +190,7 @@ static inline bool slsi_rx_is_amsdu(struct sk_buff *skb) return (fapi_get_u16(skb, u.ma_unitdata_ind.data_unit_descriptor) == FAPI_DATAUNITDESCRIPTOR_AMSDU); } -void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) +void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, bool from_ba_timer) { struct netdev_vif *ndev_vif = netdev_priv(dev); struct sk_buff_head msdu_list; @@ -321,7 +321,10 @@ void slsi_rx_data_deliver_skb(struct slsi_dev *sdev, struct net_device *dev, str conf_hip4_ver = scsc_wifi_get_hip_config_version(&sdev->hip4_inst.hip_control->init); if (conf_hip4_ver == 4) { #ifdef CONFIG_SCSC_WLAN_RX_NAPI_GRO - napi_gro_receive(&sdev->hip4_inst.hip_priv->napi, rx_skb); + if (!from_ba_timer) + napi_gro_receive(&sdev->hip4_inst.hip_priv->napi, rx_skb); + else + netif_receive_skb(rx_skb); #else netif_receive_skb(rx_skb); #endif @@ -412,7 +415,7 @@ static void slsi_rx_data_ind(struct slsi_dev *sdev, struct net_device *dev, stru SLSI_NET_WARN(dev, "Packet received from TDLS but no TDLS exists (seq: %x) Skip BA\n", seq_num); /* Skip BA reorder and pass the frames Up */ - slsi_rx_data_deliver_skb(sdev, dev, skb); + slsi_rx_data_deliver_skb(sdev, dev, skb, false); return; } @@ -434,7 +437,7 @@ static void slsi_rx_data_ind(struct slsi_dev *sdev, struct net_device *dev, stru return; /* Pass to next receive process */ - slsi_rx_data_deliver_skb(sdev, dev, skb); + slsi_rx_data_deliver_skb(sdev, dev, skb, false); } static int slsi_rx_data_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) @@ -484,7 +487,7 @@ static int slsi_rx_napi_process(struct slsi_dev *sdev, struct sk_buff *skb) /* SKBs in a BA session are not passed yet */ if (atomic_read(&ndev_vif->ba_flush)) { atomic_set(&ndev_vif->ba_flush, 0); - slsi_ba_process_complete(dev); + slsi_ba_process_complete(dev, false); } break; case MA_UNITDATA_CFM: @@ -521,7 +524,7 @@ void slsi_rx_netdev_data_work(struct work_struct *work) if (atomic_read(&ndev_vif->ba_flush)) { atomic_set(&ndev_vif->ba_flush, 0); - slsi_ba_process_complete(dev); + slsi_ba_process_complete(dev, false); } skb = slsi_skb_work_dequeue(w); -- 2.20.1