From b2f6c26fa481321058ac716597c8d0c3d8069988 Mon Sep 17 00:00:00 2001 From: Arun Khandavalli Date: Thu, 18 Aug 2016 19:07:19 +0530 Subject: qcacld-3.0: Fixes for p2p from GUI/standalone * From the GUI, After change interface, only stop and de-init of adapter was getting done. The interface to be changed was not getting started. So, start the adapter from the mode since the interface was already up in the P2P device mode before the change_iface, supplicant doesn't invoke interface up on the adapter again. * In the standalone scenario, the interface up for the p2p0 comes 1st, as part of which the sme session shall be opened with sessionId 0. So, as part of indicating the management from to HDD, LIM layer tries to traverse the adapter list with the sessionId and since the wlan0 interface is also part of the linked list with the same sessid. It tries to send the management frames on the wrong interface index because of which frames were not reaching the supplicant. To migitate this issue, once the adapter is allocated, fill the session with invalid sessionId so that it can be updated with the valid sessionId once the session is created. Change-Id: I63b320aea1eb779883dfa070bad3f2057fd5c371 CRs-Fixed: 1056344 --- core/hdd/inc/wlan_hdd_main.h | 4 ++++ core/hdd/src/wlan_hdd_cfg80211.c | 16 ++++++++++++---- core/hdd/src/wlan_hdd_main.c | 10 ++++++++-- core/hdd/src/wlan_hdd_p2p.c | 3 ++- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 40242313f10e..ab0ea8af9f10 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -260,6 +260,10 @@ #define BSS_WAIT_TIMEOUT 10000 #define PRE_CAC_SSID "pre_cac_ssid" + +/* session ID invalid */ +#define HDD_SESSION_ID_INVALID 0xFF + /* * Generic asynchronous request/response support * diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index b0c9328e7445..821e88cd3910 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8345,7 +8345,7 @@ static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev, struct hdd_config *config = hdd_ctx->config; hdd_wext_state_t *wext; struct wireless_dev *wdev; - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_SUCCESS; ENTER(); @@ -8372,12 +8372,12 @@ static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev, } memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx)); hdd_set_station_ops(adapter->dev); - status = hdd_init_station_mode(adapter); wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata; wext->roamProfile.nAddIEScanLength = adapter->scan_info.scanAddIE.length; if (type == NL80211_IFTYPE_ADHOC) { + status = hdd_init_station_mode(adapter); wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS; wext->roamProfile.phyMode = hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode); @@ -8497,7 +8497,11 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, type); if (vstatus != QDF_STATUS_SUCCESS) return -EINVAL; - + if (hdd_start_adapter(pAdapter)) { + hdd_err("Failed to start adapter :%d", + pAdapter->device_mode); + return -EINVAL; + } goto done; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: @@ -8575,7 +8579,11 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, type); if (status != QDF_STATUS_SUCCESS) return status; - + if (hdd_start_adapter(pAdapter)) { + hdd_err("Failed to start adapter :%d", + pAdapter->device_mode); + return -EINVAL; + } goto done; case NL80211_IFTYPE_AP: diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 1d65118396ed..19f1099c3bce 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1618,6 +1618,12 @@ int hdd_start_adapter(hdd_adapter_t *adapter) if (ret) goto err_start_adapter; break; + case QDF_IBSS_MODE: + /* + * For IBSS interface is initialized as part of + * hdd_init_station_mode() + */ + return 0; case QDF_FTM_MODE: ret = hdd_start_ftm_adapter(adapter); if (ret) @@ -1801,7 +1807,6 @@ static int __hdd_open(struct net_device *dev) int ret; ENTER_DEV(dev); - MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, adapter->sessionId, adapter->device_mode)); @@ -3181,6 +3186,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter)) hdd_err("Interface %s wow debug_fs init failed", iface_name); + adapter->sessionId = HDD_SESSION_ID_INVALID; + return adapter; err_lro_cleanup: @@ -6281,7 +6288,6 @@ static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx, if (adapter == NULL) return ERR_PTR(-ENOSPC); - ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held); if (ret) goto err_close_adapter; diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index c5255ad23d48..02ff295d9cc5 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -2481,7 +2481,8 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, } } /* Indicate Frame Over Normal Interface */ - hddLog(LOG1, FL("Indicate Frame over NL80211 Interface")); + hddLog(LOG1, FL("Indicate Frame over NL80211 sessionid : %d, idx :%d"), + pAdapter->sessionId, pAdapter->dev->ifindex); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames, -- cgit v1.2.3 From 99286457f60483089157d30e5cd9fdc9fddece12 Mon Sep 17 00:00:00 2001 From: Arun Khandavalli Date: Mon, 22 Aug 2016 12:13:41 +0530 Subject: qcacld-3.0: Check and kickstart the modules state if they are closed There are few NL80211 commands which can be triggered from the upper layer even when the interfaces are down. Check the driver state machine when these commands gets triggered from the upper layer and start the modules if they are closed, so these commands can be honoured correctly. Change-Id: I4a1d2e95379a5e690b00eea37e80ceb8a91925fb CRs-Fixed: 1056959 --- core/hdd/src/wlan_hdd_p2p.c | 16 ++++++++++++++++ core/hdd/src/wlan_hdd_power.c | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index 02ff295d9cc5..16f3953b177d 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -2048,6 +2048,15 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, return ERR_PTR(-ENOSPC); } + /* + * Add interface can be requested from the upper layer at any time + * check the statemachine for modules state and if they are closed + * open the modules. + */ + ret = hdd_wlan_start_modules(pHddCtx, pAdapter, false); + if (ret) + return ERR_PTR(ret); + if (NL80211_IFTYPE_AP == type) { ret = hdd_start_adapter(pAdapter); if (ret) { @@ -2145,6 +2154,13 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) if (0 != status) return status; + /* + * check state machine state and kickstart modules if they are closed. + */ + status = hdd_wlan_start_modules(pHddCtx, pVirtAdapter, false); + if (status) + return status; + wlan_hdd_release_intf_addr(pHddCtx, pVirtAdapter->macAddressCurrent.bytes); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index d538ff112010..dde5cbbeba17 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1919,6 +1919,14 @@ static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, if (0 != status) return status; + mutex_lock(&pHddCtx->iface_change_lock); + if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) { + mutex_unlock(&pHddCtx->iface_change_lock); + hdd_info("Driver Module not enabled return success"); + return 0; + } + mutex_unlock(&pHddCtx->iface_change_lock); + if ((DRIVER_POWER_MODE_AUTO == !mode) && (true == pHddCtx->hdd_wlan_suspended) && (pHddCtx->config->fhostArpOffload) && @@ -2081,8 +2089,9 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) { - hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy); + struct net_device *ndev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev); int status; ENTER(); @@ -2098,17 +2107,32 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, return status; } - pAdapter = hdd_get_adapter(pHddCtx, QDF_STA_MODE); - if (NULL == pAdapter) { - hdd_err("pAdapter is NULL"); + if (!adapter) { + hdd_err("adapter is NULL"); return -ENOENT; } + /* Validate adapter sessionId */ + if (adapter->sessionId == HDD_SESSION_ID_INVALID) { + hdd_err("Adapter Session Invalid!"); + return -ENOTSUPP; + } + + mutex_lock(&pHddCtx->iface_change_lock); + if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) { + mutex_unlock(&pHddCtx->iface_change_lock); + hdd_info("Driver Module not enabled return success"); + /* Send cached data to upperlayer*/ + *dbm = adapter->hdd_stats.ClassA_stat.max_pwr; + return 0; + } + mutex_unlock(&pHddCtx->iface_change_lock); + MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_GET_TXPOWER, - pAdapter->sessionId, pAdapter->device_mode)); - wlan_hdd_get_class_astats(pAdapter); - *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr; + adapter->sessionId, adapter->device_mode)); + wlan_hdd_get_class_astats(adapter); + *dbm = adapter->hdd_stats.ClassA_stat.max_pwr; EXIT(); return 0; -- cgit v1.2.3 From 2721f942ff68ce8dcf8e51ee77fc27f3214e3296 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Wed, 24 Aug 2016 16:08:23 -0700 Subject: qcacld-3.0: Set rx_mode to be NAPI for iHelium With the introduction of rx_mode ini config, gEnableRxThread and gEnableNAPI configuration are obsolete. So remove them. Change-Id: Ida8063eff86a644ebf9c494b94bcb3396b35b6e8 CRs-Fixed: 1056091 --- config/WCNSS_qcom_cfg.ini | 10 +++------- core/hdd/inc/wlan_hdd_cfg.h | 2 ++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index 5c05d460f30c..d5b761b6ae7e 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -610,9 +610,9 @@ gReorderOffloadSupported=1 # 1 - enable(default) 0 - disable gCEClassifyEnable=1 -#Enable Rx thread -# 1 - enable 0 - disable(default) -gEnableRxThread=0 +# Enable Rx handling options +# Rx_thread=1 RPS=2(default for ROME) NAPI=4(default for ihelium) +rx_mode=4 # Enable(Tx) fastpath for data traffic. # 1 - enable(default) 0 - disable @@ -622,10 +622,6 @@ gEnableFastPath=1 # 1 - enable(default) 0 - disable gEnableIpTcpUdpChecksumOffload=1 -# Enable NAPI -# 1 - enable(default) 0 - disable -gEnableNAPI=1 - # Enable TCP Segmentation Offload # 1 - enable(default) 0 - disable TSOEnable=1 diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 0d5857fdff54..672a1297d534 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -3424,6 +3424,8 @@ enum dot11p_mode { CFG_ENABLE_NAPI) #ifdef MDM_PLATFORM #define CFG_RX_MODE_DEFAULT (0) +#elif defined(HELIUMPLUS) +#define CFG_RX_MODE_DEFAULT CFG_ENABLE_NAPI #else #define CFG_RX_MODE_DEFAULT (CFG_ENABLE_RX_THREAD | CFG_ENABLE_NAPI) #endif -- cgit v1.2.3 From bb8d451c63bd9c1bff1ccdea424149b4687405ec Mon Sep 17 00:00:00 2001 From: Ravi Joshi Date: Mon, 22 Aug 2016 10:14:52 -0700 Subject: qcacld-3.0: Drop replayed multicast packets Integration from qcacld-2.0 to qcacld-3.0 IPv6 Multicast (Neighbor Solicitation) frames are not rejected by the WLAN driver when these frames are bounced back from the AP. This causes network stack to assume the duplicate IP address on the network and fails to assign the IPv6 address. Currently, this is a workaround till the issue is root caused. Change-Id: If5d48ed903f484805e7f4be9df52582e50bd6ce5 CRs-Fixed: 748105 --- core/hdd/inc/wlan_hdd_cfg.h | 14 ++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 11 +++++++++++ core/hdd/src/wlan_hdd_tx_rx.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 672a1297d534..2d51b340304c 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -3481,6 +3481,19 @@ enum dot11p_mode { #define CFG_INDOOR_CHANNEL_SUPPORT_MAX (1) #define CFG_INDOOR_CHANNEL_SUPPORT_DEFAULT (0) +/* + * Enable filtering of replayed multicast packets + * In a typical infrastructure setup, it is quite normal to receive + * replayed multicast packets. These packets may cause more harm than + * help if not handled properly. Providing a configuration option + * to enable filtering of such packets + */ +#define CFG_FILTER_MULTICAST_REPLAY_NAME "enable_multicast_replay_filter" +#define CFG_FILTER_MULTICAST_REPLAY_MIN (0) +#define CFG_FILTER_MULTICAST_REPLAY_MAX (1) +#define CFG_FILTER_MULTICAST_REPLAY_DEFAULT (1) + + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -4141,6 +4154,7 @@ struct hdd_config { uint32_t iface_change_wait_time; enum cfg_sub_20_channel_width enable_sub_20_channel_width; bool indoor_channel_support; + bool multicast_replay_filter; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 29fc5aa8f16b..b9bebdc0e1bb 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -4007,6 +4007,14 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_INTERFACE_CHANGE_WAIT_DEFAULT, CFG_INTERFACE_CHANGE_WAIT_MIN, CFG_INTERFACE_CHANGE_WAIT_MAX), + + REG_VARIABLE(CFG_FILTER_MULTICAST_REPLAY_NAME, + WLAN_PARAM_Integer, + struct hdd_config, multicast_replay_filter, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FILTER_MULTICAST_REPLAY_DEFAULT, + CFG_FILTER_MULTICAST_REPLAY_MIN, + CFG_FILTER_MULTICAST_REPLAY_MAX), }; /** @@ -5686,6 +5694,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) hdd_info("Name = [%s] Value = [%d]", CFG_BPF_PACKET_FILTER_OFFLOAD, pHddCtx->config->bpf_packet_filter_enable); + hdd_info("Name = [%s] Value = [%d]", + CFG_FILTER_MULTICAST_REPLAY_NAME, + pHddCtx->config->multicast_replay_filter); } diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 5c4d503489a5..53bfa38f9c4e 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -851,6 +852,25 @@ int hdd_get_peer_idx(hdd_station_ctx_t *sta_ctx, struct qdf_mac_addr *addr) return INVALID_PEER_IDX; } +/* + * hdd_is_mcast_replay() - checks if pkt is multicast replay + * @skb: packet skb + * + * Return: true if replayed multicast pkt, false otherwise + */ +static bool hdd_is_mcast_replay(struct sk_buff *skb) +{ + struct ethhdr *eth; + + eth = eth_hdr(skb); + if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { + if (unlikely(ether_addr_equal(eth->h_source, + skb->dev->dev_addr))) + return true; + } + return false; +} + /** * hdd_rx_packet_cbk() - Receive packet handler * @context: pointer to HDD context @@ -926,6 +946,17 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; ++pAdapter->stats.rx_packets; pAdapter->stats.rx_bytes += skb->len; + + /* Check & drop replayed mcast packets (for IPV6) */ + if (pHddCtx->config->multicast_replay_filter && + hdd_is_mcast_replay(skb)) { + ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index]; + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO, + "%s: Dropping multicast replay pkt", __func__); + kfree_skb(skb); + return QDF_STATUS_SUCCESS; + } + #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION, -- cgit v1.2.3