diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-06-24 21:18:08 -0600 |
|---|---|---|
| committer | Linux Build Service Account <lnxbuild@localhost> | 2016-06-24 21:18:08 -0600 |
| commit | b000a22b05cb6da8776c0a379bc5f79c80bd1f77 (patch) | |
| tree | fb438911a7fed96947227f7debd7d8e658d76f17 | |
| parent | c04dc51b3267acc1e64f89b79b34e6b0deddb457 (diff) | |
| parent | 9f09a9e30c496b5bf38ee5c41827f24ccf1f85a7 (diff) | |
Promotion of wlan-cld2.driver.lnx.1.0-00039.
CRs Change ID Subject
--------------------------------------------------------------------------------------------------------------
1032612 I87f82c5faf7e3c8343c8bffcb421a78c1ab47d61 qcacld-2.0: set ce_suspend to true after tasklet complet
982329 Icff3778d35ef7ea646463fe49c4335e260e9e156 qcacld-2.0: Do not trigger del sta if it is already in p
688141 I255364eb3482c046f256adc68e435233ac4e571f Release 4.0.11.106
1033307 If23398b01124638cfb266f5755fc9e45d3969ac9 qcacld-2.0: unmap buffer for CE dst ring en-queue error
1032185 I54f305319e23b1ffcbd54cc6e7dcc74d39a2e511 qcacld-2.0: Fix P2P GO Negotiation failure issue
1032098 I6c2ab331256b190fd0ce67f8fb95ed4d7cb5e61a qcacld-2.0: Dump stack only once
1018887 I71b77cfa09c5039b487e9a93490837a084314fb3 qcacld-2.0: Make OEM response events wakeable
1031468 I52d8575960e4d5bac5aa509df41c20fb846a96e6 qcacld-2.0: Reset the parameters which overrides the ACS
1030729 I38eea06360226322bb4f7fcbf810635b09da5593 qcacld-2.0: Reset card to recover from target mbox error
1032857 I7e9301323410e0e2ae456aa30da9c628dd7841c2 qcacld-2.0: Reset is_ch_avoid_in_progress correctly
688141 I52d4d2d4f1859197d836001aa961d0bf7581d3a9 Release 4.0.11.105
1027526 I0ac8b4ef01f91539852935242176e6c1f0f3ba25 qcacld-2.0: Remove startup_task from SDIO solution
1032578 I631fb202fba6bc129d03ff21cff2adef328abff2 qcacld-2.0: Do not reset short preamble support and beac
688141 I31d32b2ea9a3c85ea976d4c04c322e38ca07c07b Release 4.0.11.107
1013559 Ie963f80b3c3e5ea5e4dd0f46b3dbdbea9d6c7f49 qcacld-2.0: WAR for dfs false detection
1020119 I169e79f6033096f8d4325657dc3a94677e1ea54d qcacld-2.0: Add compile time assert for SKB CB size
Change-Id: I507fd7ac40db7c736ea795ae71069d387f7435f0
CRs-Fixed: 1032098, 688141, 1032857, 1033307, 1030729, 1020119, 1018887, 1032612, 982329, 1013559, 1032185, 1031468, 1027526, 1032578
26 files changed, 645 insertions, 102 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_hostapd.h b/CORE/HDD/inc/wlan_hdd_hostapd.h index 1e18dbf533bc..574bb75b8b6e 100644 --- a/CORE/HDD/inc/wlan_hdd_hostapd.h +++ b/CORE/HDD/inc/wlan_hdd_hostapd.h @@ -218,6 +218,7 @@ hdd_change_ch_avoidance_status(hdd_context_t *hdd_ctx, spin_lock(&hdd_ctx->sap_update_info_lock); hdd_ctx->is_ch_avoid_in_progress = value; spin_unlock(&hdd_ctx->sap_update_info_lock); + hddLog(LOG1, FL("is_ch_avoid_in_progress %d"), value); } #endif // end #if !defined( WLAN_HDD_HOSTAPD_H ) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 7e3a85a3b86c..e5cdec427b15 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -683,6 +683,11 @@ typedef struct hdd_cfg80211_state_s hdd_remain_on_chan_ctx_t* remain_on_chan_ctx; struct mutex remain_on_chan_ctx_lock; eP2PActionFrameState actionFrmState; + /* is_go_neg_ack_received flag is set to 1 when + * the pending ack for GO negotiation req is + * received. + */ + v_BOOL_t is_go_neg_ack_received; }hdd_cfg80211_state_t; diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index ebdcf9cc824e..0e7794f94521 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -14647,13 +14647,13 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, #endif status = wlan_hdd_cfg80211_start_bss(pAdapter, ¶ms->beacon, params->ssid, params->ssid_len, params->hidden_ssid); - if (status == 0) { - if (0 != wlan_hdd_set_udp_resp_offload(pAdapter, TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: set udp resp cmd failed %d", - __func__, status); - } - } + if (status == 0) { + if (0 != wlan_hdd_set_udp_resp_offload(pAdapter, TRUE)) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: set udp resp cmd failed %d", + __func__, status); + } + } + hdd_change_ch_avoidance_status(pHddCtx, false); } EXIT(); diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index c891412a9b5a..3650b56c2a2a 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -16645,12 +16645,10 @@ void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctx) if ((adapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode) && (!hdd_find_prefd_safe_chnl(hdd_ctx, adapter))) return; + hddLog(LOG1, FL("Current operation channel %d"), adapter->sessionCtx.ap.operatingChannel); - hddLog(LOG1, FL("sessionCtx.ap.sapConfig.channel %d"), - adapter->sessionCtx.ap.sapConfig.channel); - for (channel_loop = 0; channel_loop < hdd_ctx->unsafe_channel_count; channel_loop++) { @@ -16671,6 +16669,20 @@ void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctx) hddLog(LOGE, FL("Restarting SAP due to unsafe channel")); + /* SAP restart due to unsafe channel. While + * restarting the SAP, makee sure to clear + * acs_channel, channel to reset to 0. + * Otherwise these settings will override the + * ACS while restart. + */ + hdd_ctx->acs_policy.acs_channel = + AUTO_CHANNEL_SELECT; + adapter->sessionCtx.ap.sapConfig.channel = + AUTO_CHANNEL_SELECT; + + hddLog(LOG1, FL("set sapConfig.channel to %d"), + AUTO_CHANNEL_SELECT); + wlan_hdd_send_svc_nlink_msg( hdd_ctx->radio_index, WLAN_SVC_LTE_COEX_IND, diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c index e51d57f302d2..1e81402e67bd 100644 --- a/CORE/HDD/src/wlan_hdd_p2p.c +++ b/CORE/HDD/src/wlan_hdd_p2p.c @@ -1865,11 +1865,25 @@ void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess cfgState->actionFrmState = HDD_IDLE; - hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess); if( NULL == cfgState->buf ) { return; } + if (cfgState->is_go_neg_ack_received) { + + cfgState->is_go_neg_ack_received = 0 ; + /* Sometimes its possible that host may receive the ack for GO + * negotiation req after sending go negotaition confirmation, + * in such case drop the ack received for the go negotiation + * request, so that supplicant waits for the confirmation ack + * from firmware. + */ + hddLog( LOG1, FL("Drop the pending ack received in cfgState->actionFrmState %d"), + cfgState->actionFrmState); + return; + } + + hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess); /* * buf is the same pointer it passed us to send. Since we are sending @@ -2635,6 +2649,7 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, { hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ", __func__); + cfgState->is_go_neg_ack_received = 1; hdd_sendActionCnf(pAdapter, TRUE); } } diff --git a/CORE/MAC/inc/qwlan_version.h b/CORE/MAC/inc/qwlan_version.h index 01d21a4d8805..dd54648443e4 100644 --- a/CORE/MAC/inc/qwlan_version.h +++ b/CORE/MAC/inc/qwlan_version.h @@ -42,9 +42,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 11 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 104 +#define QWLAN_VERSION_BUILD 107 -#define QWLAN_VERSIONSTR "4.0.11.104" +#define QWLAN_VERSIONSTR "4.0.11.107" #define AR6320_REV1_VERSION 0x5000000 diff --git a/CORE/MAC/src/dph/dphHashTable.c b/CORE/MAC/src/dph/dphHashTable.c index a39886b02587..383fb49e1272 100644 --- a/CORE/MAC/src/dph/dphHashTable.c +++ b/CORE/MAC/src/dph/dphHashTable.c @@ -288,6 +288,7 @@ tpDphHashNode dphInitStaState(tpAniSirGlobal pMac, tSirMacAddr staAddr, #ifdef WLAN_FEATURE_11W pStaDs->last_assoc_received_time = 0; #endif + pStaDs->sta_deletion_in_progress = false; pStaDs->valid = 1; return pStaDs; } @@ -436,6 +437,7 @@ tSirRetStatus dphDeleteHashEntry(tpAniSirGlobal pMac, tSirMacAddr staAddr, tANI_ #ifdef WLAN_FEATURE_11W ptr->last_assoc_received_time = 0; #endif + ptr->sta_deletion_in_progress = false; ptr->next = 0; } else diff --git a/CORE/MAC/src/include/dphGlobal.h b/CORE/MAC/src/include/dphGlobal.h index 2d3517605be8..2ea951b08997 100644 --- a/CORE/MAC/src/include/dphGlobal.h +++ b/CORE/MAC/src/include/dphGlobal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -512,6 +512,7 @@ typedef struct sDphHashNode */ tANI_U8 isDisassocDeauthInProgress; + bool sta_deletion_in_progress; struct sDphHashNode *next; tANI_S8 del_sta_ctx_rssi; } tDphHashNode, *tpDphHashNode; diff --git a/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c b/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c index 2c1581767ce9..5db1fd513647 100644 --- a/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c +++ b/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c @@ -277,13 +277,16 @@ limTriggerSTAdeletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession pse } if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || - (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { + (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE) || + pStaDs->sta_deletion_in_progress) { /* Already in the process of deleting context for the peer */ - PELOGE(limLog(pMac, LOGE, - FL("Deletion is in progress for peer:%p"), pStaDs->staAddr);) + limLog(pMac, LOG1, + FL("Deletion is in progress (%d) for peer:%p in mlmState %d"), + pStaDs->sta_deletion_in_progress, pStaDs->staAddr, + pStaDs->mlmStaContext.mlmState); return; } - + pStaDs->sta_deletion_in_progress = true; pStaDs->mlmStaContext.disassocReason = eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; pStaDs->mlmStaContext.cleanupTrigger = eLIM_LINK_MONITORING_DISASSOC; diff --git a/CORE/MAC/src/pe/lim/limSession.c b/CORE/MAC/src/pe/lim/limSession.c index e4d3378f1b81..6fe267edca26 100644 --- a/CORE/MAC/src/pe/lim/limSession.c +++ b/CORE/MAC/src/pe/lim/limSession.c @@ -143,9 +143,18 @@ void pe_reset_protection_callback(void *ptr) vos_mem_zero(&pe_session_entry->gLimOlbcParams, sizeof(pe_session_entry->gLimOlbcParams)); - - vos_mem_zero(&pe_session_entry->beaconParams, - sizeof(pe_session_entry->beaconParams)); + /* + * Do not reset fShortPreamble and beaconInterval, as they + * are not updated. + */ + pe_session_entry->beaconParams.llaCoexist = 0; + pe_session_entry->beaconParams.llbCoexist = 0; + pe_session_entry->beaconParams.llgCoexist = 0; + pe_session_entry->beaconParams.ht20Coexist = 0; + pe_session_entry->beaconParams.llnNonGFCoexist = 0; + pe_session_entry->beaconParams.fRIFSMode = 0; + pe_session_entry->beaconParams.fLsigTXOPProtectionFullSupport = 0; + pe_session_entry->beaconParams.gHTObssMode = 0; vos_mem_zero(&mac_ctx->lim.gLimOverlap11gParams, sizeof(mac_ctx->lim.gLimOverlap11gParams)); diff --git a/CORE/SERVICES/COMMON/adf/adf_nbuf.c b/CORE/SERVICES/COMMON/adf/adf_nbuf.c index aed95aaa5184..944894f25531 100644 --- a/CORE/SERVICES/COMMON/adf/adf_nbuf.c +++ b/CORE/SERVICES/COMMON/adf/adf_nbuf.c @@ -1140,3 +1140,22 @@ int adf_nbuf_update_radiotap(struct mon_rx_status *rx_status, adf_nbuf_t nbuf, rtap_hdr_len, rtap_len - rtap_hdr_len); return rtap_len; } + +/** + * __adf_nbuf_validate_skb_cb() - validate skb CB + * + * SKB control block size limit is 48 byte, add compile time + * assert if SKB control block is exceeding 48 byte. + * + * Return: none + */ +void +__adf_nbuf_validate_skb_cb(void) +{ + /* + * Add compile time assert if SKB control block is exceeding + * 48 byte. + */ + BUILD_BUG_ON(sizeof(struct cvg_nbuf_cb) > + FIELD_SIZEOF(struct sk_buff, cb)); +} diff --git a/CORE/SERVICES/COMMON/hif_msg_based.h b/CORE/SERVICES/COMMON/hif_msg_based.h index f7143aab3d48..af339aef1248 100644 --- a/CORE/SERVICES/COMMON/hif_msg_based.h +++ b/CORE/SERVICES/COMMON/hif_msg_based.h @@ -1,5 +1,5 @@ /* - *Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + *Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -148,6 +148,14 @@ void HIFsuspendwow(HIF_DEVICE *hif_device); void HIFSetBundleMode(HIF_DEVICE *hif_device, bool enabled, int rx_bundle_cnt); #endif +#ifdef HIF_SDIO +int hif_reset_target(HIF_DEVICE *hif_device); +#else +static inline int hif_reset_target(HIF_DEVICE *hif_device) +{ + return 0; +} +#endif #ifdef __cplusplus } #endif diff --git a/CORE/SERVICES/DFS/inc/dfs.h b/CORE/SERVICES/DFS/inc/dfs.h index b424e9167f1e..52ae15f1dea4 100644 --- a/CORE/SERVICES/DFS/inc/dfs.h +++ b/CORE/SERVICES/DFS/inc/dfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2005-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -89,6 +89,7 @@ #include "dfs_interface.h" #include "_ieee80211_common.h" #include "vos_api.h" +#include "sirDebug.h" #define ATH_SUPPORT_DFS 1 #define CHANNEL_TURBO 0x00010 @@ -128,6 +129,7 @@ //#define MAX_BIN5_DUR 131 /* 105 * 1.25*/ #define MAX_BIN5_DUR 145 /* use 145 for osprey */ //conversion is already done using dfs->dur_multiplier// #define MAX_BIN5_DUR_MICROSEC 105 +#define MAX_DFS_RADAR_TYPE 256 #define DFS_MARGIN_EQUAL(a, b, margin) ((DFS_DIFF(a,b)) <= margin) #define DFS_MAX_STAGGERED_BURSTS 3 @@ -265,6 +267,7 @@ struct dfs_pulseline { #define DFS_EVENT_HW_CHIRP 0x02 /* hardware chirp */ #define DFS_EVENT_SW_CHIRP 0x04 /* software chirp */ + /* * Use this only if the event has CHECKCHIRP set. */ @@ -298,6 +301,7 @@ struct dfs_event { #pragma pack(pop, dfs_event) #endif +#define DFS_FILTER_DEFAULT_PRI 1000000 #define DFS_AR_MAX_ACK_RADAR_DUR 511 #define DFS_AR_MAX_NUM_PEAKS 3 #define DFS_AR_ARQ_SIZE 2048 /* 8K AR events for buffer size */ @@ -569,10 +573,13 @@ struct ath_dfs { /* dfs_radarf - One filter for each radar pulse type */ struct dfs_filtertype *dfs_radarf[DFS_MAX_RADAR_TYPES]; + struct dfs_filtertype *dfs_dc_radarf[DFS_MAX_RADAR_TYPES]; struct dfs_info dfs_rinfo; /* State vars for radar processing */ struct dfs_bin5radars *dfs_b5radars;/* array of bin5 radar events */ int8_t **dfs_radartable; /* map of radar durs to filter types */ + /* map of dc radar durs to filter types */ + int8_t **dfs_dc_radartable; #ifndef ATH_DFS_RADAR_DETECTION_ONLY struct dfs_nolelem *dfs_nol; /* Non occupancy list for radar */ int dfs_nol_count; /* How many items? */ diff --git a/CORE/SERVICES/DFS/src/dfs.c b/CORE/SERVICES/DFS/src/dfs.c index 313671fc2d05..8677cc29ee21 100644 --- a/CORE/SERVICES/DFS/src/dfs.c +++ b/CORE/SERVICES/DFS/src/dfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2002-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -344,7 +344,7 @@ dfs_attach(struct ieee80211com *ic) dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; - /* Allocate memory for radar filters */ + /* Allocate memory for radar filters */ for (n=0; n<DFS_MAX_RADAR_TYPES; n++) { dfs->dfs_radarf[n] = (struct dfs_filtertype *)OS_MALLOC(NULL, sizeof(struct dfs_filtertype),GFP_ATOMIC); if (dfs->dfs_radarf[n] == NULL) { @@ -357,7 +357,23 @@ dfs_attach(struct ieee80211com *ic) goto bad1; } } - /* Allocate memory for radar table */ + + /* Allocate memory for dc radar filters */ + for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { + dfs->dfs_dc_radarf[n] = + (struct dfs_filtertype *)OS_MALLOC(NULL, + sizeof(struct dfs_filtertype), GFP_ATOMIC); + if (!(dfs->dfs_dc_radarf[n])) { + DFS_PRINTK("%s: cannot allocate memory for dc radar filter types\n", + __func__); + goto bad1; + } + vos_mem_zero(dfs->dfs_dc_radarf[n], sizeof(struct dfs_filtertype)); + if (0 != dfs_alloc_mem_filter(dfs->dfs_radarf[n])) + goto bad4; + } + + /* Allocate memory for radar table */ dfs->dfs_radartable = (int8_t **)OS_MALLOC(NULL, 256*sizeof(int8_t *), GFP_ATOMIC); if (dfs->dfs_radartable == NULL) { DFS_PRINTK("%s: cannot allocate memory for radar table\n", @@ -374,6 +390,26 @@ dfs_attach(struct ieee80211com *ic) } } + /* Allocate memory for dc radar table */ + dfs->dfs_dc_radartable = (int8_t **)OS_MALLOC(NULL, + MAX_DFS_RADAR_TYPE * sizeof(int8_t *), + GFP_ATOMIC); + if (!dfs->dfs_dc_radartable) { + DFS_PRINTK("%s: cannot allocate memory for radar table\n", + __func__); + goto bad2; + } + for (n = 0; n < MAX_DFS_RADAR_TYPE; n++) { + dfs->dfs_dc_radartable[n] = OS_MALLOC(NULL, + DFS_MAX_RADAR_OVERLAP * sizeof(int8_t), + GFP_ATOMIC); + if (!(dfs->dfs_dc_radartable[n])) { + DFS_PRINTK("%s: cannot allocate memory for dc radar table entry\n", + __func__); + goto bad3; + } + } + if (usenol == 0) DFS_PRINTK("%s: NOL disabled\n", __func__); else if (usenol == 2) @@ -411,9 +447,19 @@ dfs_attach(struct ieee80211com *ic) dfs->ath_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; return 0; +bad3: + OS_FREE(dfs->dfs_dc_radartable); + dfs->dfs_dc_radartable = NULL; bad2: OS_FREE(dfs->dfs_radartable); dfs->dfs_radartable = NULL; +bad4: + for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { + if (!(dfs->dfs_dc_radarf[n])) { + OS_FREE(dfs->dfs_dc_radarf[n]); + dfs->dfs_dc_radarf[n] = NULL; + } + } bad1: for (n=0; n<DFS_MAX_RADAR_TYPES; n++) { if (dfs->dfs_radarf[n] != NULL) { @@ -519,6 +565,14 @@ dfs_detach(struct ieee80211com *ic) dfs->dfs_radarf[n] = NULL; } } + for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { + if (!(dfs->dfs_dc_radarf[n])) { + dfs_free_filter(dfs->dfs_dc_radarf[n]); + OS_FREE(dfs->dfs_dc_radarf[n]); + dfs->dfs_dc_radarf[n] = NULL; + } + } + if (dfs->dfs_radartable != NULL) { @@ -535,6 +589,17 @@ dfs_detach(struct ieee80211com *ic) #endif } + if (!(dfs->dfs_dc_radartable)) { + for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { + if (!(dfs->dfs_dc_radartable[n])) { + OS_FREE(dfs->dfs_dc_radartable[n]); + dfs->dfs_dc_radartable[n] = NULL; + } + } + OS_FREE(dfs->dfs_dc_radartable); + dfs->dfs_dc_radartable = NULL; + } + if (dfs->dfs_b5radars != NULL) { OS_FREE(dfs->dfs_b5radars); dfs->dfs_b5radars=NULL; diff --git a/CORE/SERVICES/DFS/src/dfs_debug.c b/CORE/SERVICES/DFS/src/dfs_debug.c index d948f1598bfc..efe88520852a 100644 --- a/CORE/SERVICES/DFS/src/dfs_debug.c +++ b/CORE/SERVICES/DFS/src/dfs_debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2002-2013, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -109,7 +109,8 @@ dfs_print_filters(struct ath_dfs *dfs) ft = dfs->dfs_radarf[i]; if((ft->ft_numfilters > DFS_MAX_NUM_RADAR_FILTERS) || (!ft->ft_numfilters)) continue; - DFS_PRINTK("===========ft->ft_numfilters=%u===========\n", ft->ft_numfilters); + DFS_PRINTK("===========ft->ft_numfilters=%u===========\n", + ft->ft_numfilters); for (j=0; j<ft->ft_numfilters; j++) { rf = ft->ft_filters[j]; DFS_PRINTK("filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n",j, rf->rf_pulseid, @@ -117,6 +118,26 @@ dfs_print_filters(struct ath_dfs *dfs) } } } + + for (i=0; i < DFS_MAX_RADAR_TYPES; i++) { + if (dfs->dfs_dc_radarf[i]) + continue; + + ft = dfs->dfs_dc_radarf[i]; + if ((ft->ft_numfilters > DFS_MAX_NUM_RADAR_FILTERS) || + (!ft->ft_numfilters)) + continue; + DFS_PRINTK("===========DC ft->ft_numfilters=%u===========\n", + ft->ft_numfilters); + for (j = 0; j < ft->ft_numfilters; j++) { + rf = ft->ft_filters[j]; + DFS_PRINTK("DC filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n", + j, rf->rf_pulseid, rf->rf_numpulses, rf->rf_minpri, + rf->rf_maxpri, rf->rf_threshold, rf->rf_filterlen, + rf->rf_mindur, rf->rf_maxdur); + } + } + } void dfs_print_activity(struct ath_dfs *dfs) diff --git a/CORE/SERVICES/DFS/src/dfs_init.c b/CORE/SERVICES/DFS/src/dfs_init.c index 59e4bbf11400..b85b5a8a29a4 100644 --- a/CORE/SERVICES/DFS/src/dfs_init.c +++ b/CORE/SERVICES/DFS/src/dfs_init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2002-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -115,6 +115,22 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) } } } + for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) { + if (dfs->dfs_dc_radarf[i] == NULL) + continue; + + ft = dfs->dfs_dc_radarf[i]; + for (j = 0; j < ft->ft_numfilters; j++) { + rf = ft->ft_filters[j]; + dl = &(rf->rf_dl); + if (dl == NULL) + continue; + + OS_MEMZERO(dl, sizeof(struct dfs_delayline)); + dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; + } + } + for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) { OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]), sizeof(struct dfs_bin5elem)*DFS_MAX_B5_SIZE); dfs->dfs_b5radars[i].br_firstelem = 0; @@ -230,6 +246,12 @@ int dfs_init_radar_filters(struct ieee80211com *ic, for (i=0;i<DFS_MAX_RADAR_OVERLAP; i++) (dfs->dfs_radartable[n])[i] = -1; } + /* Clear dc filter type table */ + for (n = 0; n < 256; n++) { + for (i = 0;i < DFS_MAX_RADAR_OVERLAP; i++) + (dfs->dfs_dc_radartable[n])[i] = -1; + } + /* Now, initialize the radar filters */ for (p=0; p<numradars; p++) { ft = NULL; @@ -319,8 +341,109 @@ int dfs_init_radar_filters(struct ieee80211com *ic, } + /* Initialize dc radar filters */ + for (p = 0; p < numradars; p++) { + ft = NULL; + for (n = 0; n < dfs->dfs_rinfo.rn_numradars; n++) { + if ((dfs_radars[p].rp_pulsedur == + dfs->dfs_dc_radarf[n]->ft_filterdur) && + (dfs_radars[p].rp_numpulses == + dfs->dfs_dc_radarf[n]->ft_numpulses) && + (dfs_radars[p].rp_mindur == dfs->dfs_dc_radarf[n]->ft_mindur) && + (dfs_radars[p].rp_maxdur == dfs->dfs_dc_radarf[n]->ft_maxdur)) { + + ft = dfs->dfs_dc_radarf[n]; + break; + } + } + if (ft == NULL) { + /* No filter of the appropriate dur was found */ + if ((dfs->dfs_rinfo.rn_numradars+1) > DFS_MAX_RADAR_TYPES) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Too many filter types", + __func__); + goto bad4; + } + ft = dfs->dfs_dc_radarf[dfs->dfs_rinfo.rn_numradars]; + ft->ft_numfilters = 0; + ft->ft_numpulses = dfs_radars[p].rp_numpulses; + ft->ft_patterntype = dfs_radars[p].rp_patterntype; + ft->ft_mindur = dfs_radars[p].rp_mindur; + ft->ft_maxdur = dfs_radars[p].rp_maxdur; + ft->ft_filterdur = dfs_radars[p].rp_pulsedur; + ft->ft_rssithresh = dfs_radars[p].rp_rssithresh; + ft->ft_rssimargin = dfs_radars[p].rp_rssimargin; + ft->ft_minpri = DFS_FILTER_DEFAULT_PRI; + + if (ft->ft_rssithresh < min_rssithresh) + min_rssithresh = ft->ft_rssithresh; + if (ft->ft_maxdur > max_pulsedur) + max_pulsedur = ft->ft_maxdur; + for (i = ft->ft_mindur; i <= ft->ft_maxdur; i++) { + u_int32_t stop = 0, tableindex = 0; + + while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) { + if ((dfs->dfs_dc_radartable[i])[tableindex] == -1) + stop = 1; + else + tableindex++; + } + if (stop) { + (dfs->dfs_dc_radartable[i])[tableindex] = + (int8_t) (dfs->dfs_rinfo.rn_numradars); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: Too many overlapping dc radar filters", + __func__); + goto bad4; + } + } + dfs->dfs_rinfo.rn_numradars++; + } + rf = ft->ft_filters[ft->ft_numfilters++]; + dfs_reset_delayline(&rf->rf_dl); + numpulses = dfs_radars[p].rp_numpulses; + + rf->rf_numpulses = numpulses; + rf->rf_patterntype = dfs_radars[p].rp_patterntype; + rf->rf_pulseid = dfs_radars[p].rp_pulseid; + rf->rf_mindur = dfs_radars[p].rp_mindur; + rf->rf_maxdur = dfs_radars[p].rp_maxdur; + rf->rf_numpulses = dfs_radars[p].rp_numpulses; + rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window; + T = (100000000/dfs_radars[p].rp_max_pulsefreq) - + 100*(dfs_radars[p].rp_meanoffset); + rf->rf_minpri = + dfs_round((int32_t)T - (100*(dfs_radars[p].rp_pulsevar))); + Tmax = (100000000/dfs_radars[p].rp_pulsefreq) - + 100*(dfs_radars[p].rp_meanoffset); + rf->rf_maxpri = + dfs_round((int32_t)Tmax + (100*(dfs_radars[p].rp_pulsevar))); + + if(rf->rf_minpri < ft->ft_minpri) + ft->ft_minpri = rf->rf_minpri; + + rf->rf_fixed_pri_radar_pulse = + (dfs_radars[p].rp_max_pulsefreq == + dfs_radars[p].rp_pulsefreq) ? 1 : 0; + /* for pulseid 5, increase threshould by 1 */ + if (dfs_radars[p].rp_pulseid == 5) + rf->rf_threshold = dfs_radars[p].rp_threshold + 1; + else + rf->rf_threshold = dfs_radars[p].rp_threshold; + + rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]: minprf = %d maxprf = %d pulsevar = %d thresh=%d", + __func__, __LINE__, dfs_radars[p].rp_pulsefreq, + dfs_radars[p].rp_max_pulsefreq, dfs_radars[p].rp_pulsevar, + rf->rf_threshold); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:minpri = %d maxpri = %d filterlen = %d filterID = %d", + __func__, __LINE__, rf->rf_minpri, rf->rf_maxpri, + rf->rf_filterlen, rf->rf_pulseid); + + } #ifdef DFS_DEBUG - dfs_print_filters(ic); + dfs_print_filters(dfs); #endif dfs->dfs_rinfo.rn_numbin5radars = numb5radars; if (dfs->dfs_b5radars != NULL) diff --git a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c index 156a229dd0cd..45176f5706d0 100644 --- a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c +++ b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c @@ -108,6 +108,175 @@ dfs_process_pulse_dur(struct ath_dfs *dfs, u_int8_t re_dur) } /* + * dfs_process_dc_pulse: process dc pulses + * @dfs: pointer to dfs structure + * @event: dfs event + * @retval: current found status + * @this_ts: event's ts + * + * Return: None + */ +static void dfs_process_dc_pulse(struct ath_dfs *dfs, struct dfs_event *event, + int *retval, int this_ts) +{ + struct dfs_event re; + struct dfs_state *rs=NULL; + struct dfs_filtertype *ft; + struct dfs_filter *rf; + int found, p, empty; + int min_pri, miss_pulse_number = 0, deviation = 0; + u_int32_t tabledepth = 0; + u_int64_t deltaT; + int ext_chan_event_flag = 0; + int i; + + OS_MEMCPY(&re, event, sizeof(*event)); + if (re.re_chanindex < DFS_NUM_RADAR_STATES) + rs = &dfs->dfs_radar[re.re_chanindex]; + + while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && + ((dfs->dfs_dc_radartable[re.re_dur])[tabledepth] != -1) && + (!*retval)) { + ft = dfs->dfs_dc_radarf[((dfs->dfs_dc_radartable + [re.re_dur])[tabledepth])]; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("** RD (%d): ts %x dur %u rssi %u"), + rs->rs_chan.ic_freq, + re.re_ts, re.re_dur, re.re_rssi); + + deltaT = this_ts - ft->ft_last_ts; + if (re.re_rssi < ft->ft_rssithresh && re.re_dur > 4) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("Rejecting on rssi rssi=%u thresh=%u depth=%d"), + re.re_rssi, ft->ft_rssithresh, + tabledepth); + tabledepth++; + dfs_reset_filter_delaylines(ft); + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + if ((deltaT < ft->ft_minpri) && (deltaT !=0)) { + /* This check is for the whole filter type. Individual filters + * will check this again. This is first line of filtering. */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("Rejecting on pri pri=%lld minpri=%u depth=%d"), + (unsigned long long)deltaT, + ft->ft_minpri, tabledepth); + dfs_reset_filter_delaylines(ft); + tabledepth++; + continue; + } + for (p = 0, found = 0; (p < ft->ft_numfilters) && (!found); p++) { + rf = ft->ft_filters[p]; + if ((re.re_dur >= rf->rf_mindur) && + (re.re_dur <= rf->rf_maxdur)) { + deltaT = (this_ts < rf->rf_dl.dl_last_ts) ? + (int64_t) ((DFS_TSF_WRAP - rf->rf_dl.dl_last_ts) + + this_ts + 1) : + this_ts - rf->rf_dl.dl_last_ts; + + if ((deltaT < rf->rf_minpri) && (deltaT != 0)) { + /* Second line of PRI filtering. */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("filterID=%d :: Rejected and cleared individual filter min PRI deltaT=%lld rf->rf_minpri=%u"), + rf->rf_pulseid, + (unsigned long long)deltaT, rf->rf_minpri); + dfs_reset_delayline(&rf->rf_dl); + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + + if (rf->rf_ignore_pri_window > 0) { + if (deltaT < rf->rf_minpri) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("filterID=%d :: Rejected and cleared on individual filter max PRI deltaT=%lld rf->rf_minpri=%u"), + rf->rf_pulseid, + (unsigned long long)deltaT, rf->rf_minpri); + dfs_reset_delayline(&rf->rf_dl); + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + } else { + if (deltaT < rf->rf_minpri) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("filterID=%d :: Rejected and cleared on individual filter max PRI deltaT=%lld rf->rf_minpri=%u"), + rf->rf_pulseid, + (unsigned long long)deltaT, rf->rf_minpri); + dfs_reset_delayline(&rf->rf_dl); + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + } + dfs_add_pulse(dfs, rf, &re, deltaT, this_ts); + + /* extra WAR */ + if ((dfs->dfsdomain == DFS_FCC_DOMAIN && + dfs->dfsdomain == DFS_MKK4_DOMAIN) && + ((rf->rf_pulseid != 31) && (rf->rf_pulseid != 32))) { + + min_pri = 0xffff; + for (i = 0; i < rf->rf_dl.dl_numelems; i++) { + if (rf->rf_dl.dl_elems[i].de_time < min_pri) + min_pri = rf->rf_dl.dl_elems[i].de_time; + } + + for (i=0; i < rf->rf_dl.dl_numelems; i++) { + miss_pulse_number = vos_round_div( + (rf->rf_dl.dl_elems[i].de_time), min_pri); + deviation = __adf_os_abs(min_pri * + miss_pulse_number - + rf->rf_dl.dl_elems[i].de_time); + if (deviation > miss_pulse_number*3) { + dfs_reset_delayline(&rf->rf_dl); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO, + FL("filterID=%d :: cleared individual deleyline min_pri =%d miss_pulse_number =%d deviation =%d"), + rf->rf_pulseid, + min_pri, miss_pulse_number, deviation); + } + } + } + + /* If this is an extension channel event, + * flag it for false alarm reduction */ + if (re.re_chanindex == dfs->dfs_extchan_radindex) + ext_chan_event_flag = 1; + + if (rf->rf_patterntype == 2) + found = dfs_staggered_check(dfs, rf, (uint32_t)deltaT, + re.re_dur); + else + found = dfs_bin_check(dfs, rf, (uint32_t) deltaT, + re.re_dur, ext_chan_event_flag); + + if (dfs->dfs_debug_mask & ATH_DEBUG_DFS2) + dfs_print_delayline(dfs, &rf->rf_dl); + + rf->rf_dl.dl_last_ts = this_ts; + } else { + /* if we are rejecting this, clear the queue */ + dfs_reset_delayline(&rf->rf_dl); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("filterID= %d :: cleared individual deleyline"), + rf->rf_pulseid); + } + } + ft->ft_last_ts = this_ts; + *retval |= found; + if (found) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL(":## Radar Found minDur=%d, filterId=%d ##"), + ft->ft_mindur, + rf != NULL ? rf->rf_pulseid : -1); + } + tabledepth++; + } +} + +/* * Process a radar event. * * If a radar event is found, return 1. Otherwise, return 0. @@ -381,9 +550,11 @@ dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) dfs->radar_log[i].dur = re.re_dur; dfs->dfs_event_log_count++; } - VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:xxxxx ts =%u re.re_dur=%u re.re_rssi =%u diff =%u pl->pl_lastelem.p_time=%llu xxxxx",__func__,__LINE__,(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time); - - + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s[%d]:xxxxx ts =%u re.re_dur=%u re.re_rssi =%u diff =%u sidx = %u flags = %x pl->pl_lastelem.p_time=%llu xxxxx", + __func__, __LINE__, (u_int32_t)this_ts, + re.re_dur, re.re_rssi, diff_ts, re.sidx, re.re_flags, + (unsigned long long)pl->pl_elems[index].p_time); /* If diff_ts is very small, we might be getting false pulse detects * due to heavy interference. We might be getting spectral splatter @@ -527,7 +698,26 @@ dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) DFS_DPRINTK(dfs, ATH_DEBUG_DFS1," *** chan freq (%d): ts %llu dur %u rssi %u", rs->rs_chan.ic_freq, (unsigned long long)this_ts, re.re_dur, re.re_rssi); - while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && + + /* + * DC pulses processing will be done in this seperate block since some + * device may generate pulse which may cause false detection. + * This processing is similar kind as of normal pulse processing with + * some exception such as: + * 1. Clear the queue if pulse doesn't belong to it + * 2. Remove chan load optimization(can cause some valid pulses to drop) + * 3. Drop pulses on basis of mean deviation for some filters + */ + if (((re.sidx == 0) && DFS_EVENT_NOTCHIRP(&re)) && + ((dfs->dfsdomain == DFS_FCC_DOMAIN) || + (dfs->dfsdomain == DFS_MKK4_DOMAIN) || + (dfs->dfsdomain == DFS_ETSI_DOMAIN && re.re_dur < 18))) { + dfs_process_dc_pulse(dfs, &re, &retval, this_ts); + } + + /* Pulse not at DC position */ + else { + while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && ((dfs->dfs_radartable[re.re_dur])[tabledepth] != -1) && (!retval)) { ft = dfs->dfs_radarf[((dfs->dfs_radartable[re.re_dur])[tabledepth])]; @@ -631,6 +821,7 @@ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:filterID= %d :: Rejec rf != NULL ? rf->rf_pulseid : -1); } tabledepth++; + } } ATH_DFSQ_LOCK(dfs); empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.c b/CORE/SERVICES/HIF/PCIe/hif_pci.c index 26c73b5928f9..498f8d6ef69f 100644 --- a/CORE/SERVICES/HIF/PCIe/hif_pci.c +++ b/CORE/SERVICES/HIF/PCIe/hif_pci.c @@ -97,9 +97,6 @@ HIF_ACCESS_LOG pcie_access_log[PCIE_ACCESS_LOG_NUM]; static void HIFTargetDumpAccessLog(void); #endif -/* Forward references */ -static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info); - /* * Host software's Copy Engine configuration. * This table is derived from the CE_PCI TABLE, above. @@ -1590,6 +1587,7 @@ hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) ("%s CE_recv_buf_enqueue error [%d] needed %d\n", __func__, pipe_info->pipe_num, atomic_read(&pipe_info->recv_bufs_needed))); + adf_nbuf_unmap_single(scn->adf_dev, nbuf, ADF_OS_DMA_FROM_DEVICE); atomic_inc(&pipe_info->recv_bufs_needed); adf_nbuf_free(nbuf); adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 2b9131afd8eb..c2b093cdbdb9 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -798,12 +798,12 @@ wlan_tasklet(unsigned long data) * Enable the interrupt only when there is no pending frames in * any of the Copy Engine pipes. */ - adf_os_atomic_set(&sc->ce_suspend, 1); #ifdef CONFIG_SLUB_DEBUG_ON schedule_work(&reschedule_tasklet_work); #else tasklet_schedule(&sc->intr_tq); #endif + adf_os_atomic_set(&sc->ce_suspend, 1); return; } irq_handled: diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c index a177243a8f6d..07f5de1bf91e 100644 --- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c +++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c @@ -1504,39 +1504,6 @@ HIFSetMboxSleep(HIF_DEVICE *device, bool sleep, bool wait, bool cache) } #endif -/* handle HTC startup via thread*/ -static int startup_task(void *param) -{ - HIF_DEVICE *device; - - device = (HIF_DEVICE *)param; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n")); - /* start up inform DRV layer */ - if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); - } - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) -static int enable_task(void *param) -{ - HIF_DEVICE *device; - device = (HIF_DEVICE *)param; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n")); - - /* start up inform DRV layer */ - if (device && - device->claimedContext && - osdrvCallbacks.devicePowerChangeHandler && - osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != A_OK) - { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); - } - - return 0; -} -#endif static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id) { int i; @@ -1995,9 +1962,6 @@ static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func) static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func) { - struct task_struct* pTask; - const char *taskName = NULL; - int (*taskFunc)(void *) = NULL; int ret = A_OK; ENTER("sdio_func 0x%p", func); @@ -2117,23 +2081,28 @@ static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func) } if (!device->claimedContext) { - taskFunc = startup_task; - taskName = "AR6K startup"; - ret = A_OK; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6k: call deviceInsertedHandler\n")); + ret = osdrvCallbacks.deviceInsertedHandler( + osdrvCallbacks.context,device); + /* start up inform DRV layer */ + if (ret != A_OK) + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6k: Device rejected error:%d \n", ret)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) } else { - taskFunc = enable_task; - taskName = "AR6K enable"; - ret = A_PENDING; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6k: call devicePwrChangeApi\n")); + /* start up inform DRV layer */ + if (device && + device->claimedContext && + osdrvCallbacks.devicePowerChangeHandler && + ((ret = osdrvCallbacks.devicePowerChangeHandler( + device->claimedContext, HIF_DEVICE_POWER_UP)) != A_OK)) + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6k: Device rejected error:%d \n", ret)); #endif /* CONFIG_PM */ } - /* create resume thread */ - pTask = kthread_create(taskFunc, (void *)device, taskName); - if (IS_ERR(pTask)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__)); - return A_ERROR; - } - wake_up_process(pTask); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n")); /* task will call the enable func, indicate pending */ @@ -2787,5 +2756,46 @@ static int hif_sdio_device_resume(struct device *dev) { return hifDeviceResume(dev); } + +/** + * hif_reset_target() - Reset target device + * @hif_device: pointer to hif_device structure + * + * Reset the target by invoking power off and power on + * sequence to bring back target into active state. + * This API shall be called only when driver load/unload + * is in progress. + * + * Return: 0 on success, error for failure case. + */ +int hif_reset_target(HIF_DEVICE *hif_device) +{ + int ret; + + if (!hif_device || !hif_device->func|| !hif_device->func->card) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s invalid HIF DEVICE \n", __func__)); + return -ENODEV; + } + /* Disable sdio func->pull down WLAN_EN-->pull down DAT_2 line */ + ret = mmc_power_save_host(hif_device->func->card->host); + if(ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s Failed to save mmc Power host %d\n", + __func__, ret)); + goto done; + } + + /* pull up DAT_2 line->pull up WLAN_EN-->Enable sdio func */ + ret = mmc_power_restore_host(hif_device->func->card->host); + if(ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s Failed to restore mmc Power host %d\n", + __func__, ret)); + } + +done: + return ret; +} #endif #endif diff --git a/CORE/SERVICES/HTC/htc_recv.c b/CORE/SERVICES/HTC/htc_recv.c index d15ddca39a4a..e4c1ffcdb6d5 100644 --- a/CORE/SERVICES/HTC/htc_recv.c +++ b/CORE/SERVICES/HTC/htc_recv.c @@ -582,6 +582,11 @@ A_STATUS HTCWaitRecvCtrlMessage(HTC_TARGET *target) /* Wait for BMI request/response transaction to complete */ if(!adf_os_wait_for_completion_timeout(&target->CtrlResponseValid, adf_os_msecs_to_ticks(HTC_CONTROL_RX_TIMEOUT))) { + /* Reset the target by invoking power off and power on sequence to + * the card to bring back into active state. + */ + if(hif_reset_target(target->hif_dev)) + VOS_BUG(0); return A_ERROR; } diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index b32eb7d8d83f..3930ec242e8a 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -7255,6 +7255,9 @@ static void wma_state_info_dump(char **buf_ptr, uint16_t *size) len += vos_scnprintf(buf + len, *size - len, "\n wow_ipv6_mcast_na_stats %d", wma_handle->wow_ipv6_mcast_na_stats); + len += vos_scnprintf(buf + len, *size - len, + "\n wow_oem_response_wake_up_count %d", + wma_handle->wow_oem_response_wake_up_count); *size -= len; *buf_ptr += len; @@ -20293,6 +20296,8 @@ static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason, tp_wma_handle wma) return "REASSOC_RES_RECV"; case WOW_REASON_ACTION_FRAME_RECV: return "ACTION_FRAME_RECV"; + case WOW_REASON_OEM_RESPONSE_EVENT: + return "WOW_REASON_OEM_RESPONSE_EVENT"; } return "unknown"; } @@ -20803,7 +20808,7 @@ static void wma_extscan_wow_event_callback(void *handle, void *event, */ static void wma_wow_wake_up_stats_display(tp_wma_handle wma) { - WMA_LOGA("uc %d bc %d v4_mc %d v6_mc %d ra %d ns %d na %d pno_match %d pno_complete %d gscan %d low_rssi %d rssi_breach %d icmp %d icmpv6 %d", + WMA_LOGA("uc %d bc %d v4_mc %d v6_mc %d ra %d ns %d na %d pno_match %d pno_complete %d gscan %d low_rssi %d rssi_breach %d icmp %d icmpv6 %d oem %d", wma->wow_ucast_wake_up_count, wma->wow_bcast_wake_up_count, wma->wow_ipv4_mcast_wake_up_count, @@ -20817,7 +20822,8 @@ static void wma_wow_wake_up_stats_display(tp_wma_handle wma) wma->wow_low_rssi_wake_up_count, wma->wow_rssi_breach_wake_up_count, wma->wow_icmpv4_count, - wma->wow_icmpv6_uc_bc_count); + wma->wow_icmpv6_uc_bc_count, + wma->wow_oem_response_wake_up_count); return; } @@ -20934,6 +20940,10 @@ static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data, wma->wow_rssi_breach_wake_up_count++; break; + case WOW_REASON_OEM_RESPONSE_EVENT: + wma->wow_oem_response_wake_up_count++; + break; + default: WMA_LOGE("Unknown wake up reason"); break; @@ -21689,6 +21699,26 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, } break; #endif + + case WOW_REASON_OEM_RESPONSE_EVENT: + wma_wow_wake_up_stats(wma, NULL, 0, + WOW_REASON_OEM_RESPONSE_EVENT); + if (param_buf->wow_packet_buffer) { + WMA_LOGD(FL("Host woken up by OEM Response event")); + wow_buf_pkt_len = + *(uint32_t *)param_buf->wow_packet_buffer; + vos_trace_hex_dump(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer, + wow_buf_pkt_len); + wma_oem_data_response_handler(handle, + (uint8_t*)(param_buf->wow_packet_buffer), + wow_buf_pkt_len); + } else { + WMA_LOGD(FL("No wow_packet_buffer for OEM response")); + } + break; + default: break; } @@ -21778,6 +21808,8 @@ static const u8 *wma_wow_wakeup_event_str(WOW_WAKE_EVENT_TYPE event) return "WOW_NAN_DATA_EVENT"; case WOW_TDLS_CONN_TRACKER_EVENT: return "WOW_TDLS_CONN_TRACKER_EVENT"; + case WOW_OEM_RESPONSE_EVENT: + return "WOW_OEM_RESPONSE_EVENT"; default: return "UNSPECIFIED_EVENT"; } @@ -22995,6 +23027,8 @@ static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma, wma_add_wow_wakeup_event(wma, WOW_TDLS_CONN_TRACKER_EVENT, TRUE); #endif + wma_add_wow_wakeup_event(wma, WOW_OEM_RESPONSE_EVENT, TRUE); + /* Enable wow wakeup events in FW */ ret = wma_send_wakeup_mask(wma, TRUE); if (ret) { @@ -29806,7 +29840,7 @@ static VOS_STATUS wma_set_beacon_filter(tp_wma_handle wma, ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE); for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) { ie_map[i] = filter_params->ie_map[i]; - WMA_LOGA("beacon filter ie map = %u", ie_map[i]); + WMA_LOGD("beacon filter ie map = %u", ie_map[i]); } vos_status = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, @@ -29817,7 +29851,7 @@ static VOS_STATUS wma_set_beacon_filter(tp_wma_handle wma, wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } - WMA_LOGA("added beacon filter = %d", vos_status); + WMA_LOGD("added beacon filter = %d", vos_status); return vos_status; } diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 07029837234a..990ecf5f4259 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -889,6 +889,7 @@ typedef struct wma_handle { uint32_t wow_ipv6_mcast_na_stats; uint32_t wow_icmpv4_count; uint32_t wow_icmpv6_uc_bc_count; + uint32_t wow_oem_response_wake_up_count; uint32_t wow_wakeup_enable_mask; uint32_t wow_wakeup_disable_mask; uint16_t max_mgmt_tx_fail_count; diff --git a/CORE/VOSS/inc/vos_types.h b/CORE/VOSS/inc/vos_types.h index 960226fa75ce..a9198201600a 100644 --- a/CORE/VOSS/inc/vos_types.h +++ b/CORE/VOSS/inc/vos_types.h @@ -58,6 +58,12 @@ // macro to return the floor of an integer division operation #define VOS_FLOOR_DIV( _a, _b ) ( ( (_a) - ( (_a) % (_b) ) ) / (_b) ) +static inline unsigned int vos_round_div(unsigned int dividend, + unsigned int divisor) +{ + return (dividend + (divisor / 2)) / divisor; +} + #define VOS_SWAP_U16(_x) \ ( ( ( (_x) << 8 ) & 0xFF00 ) | ( ( (_x) >> 8 ) & 0x00FF ) ) diff --git a/CORE/VOSS/src/vos_packet.c b/CORE/VOSS/src/vos_packet.c index 3844fbfd0975..9a8179cbdd01 100644 --- a/CORE/VOSS/src/vos_packet.c +++ b/CORE/VOSS/src/vos_packet.c @@ -342,10 +342,10 @@ void vos_pkt_trace_buf_dump unsigned long local_time; spin_lock_bh(&trace_buffer_lock); - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "PACKET TRACE DUMP START Current Timestamp %u", (unsigned int)vos_timer_get_system_time()); - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "ORDER : RTC TIME : EVT"); if (VOS_PKT_TRAC_MAX_TRACE_BUF > trace_buffer_order) @@ -355,7 +355,7 @@ void vos_pkt_trace_buf_dump local_time = (u32)(trace_buffer[slot].event_sec_time - (sys_tz.tz_minuteswest * 60)); rtc_time_to_tm(local_time, &tm); - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "%5d : [%02d:%02d:%02d.%06lu] : %s", trace_buffer[slot].order, tm.tm_hour, tm.tm_min, tm.tm_sec, @@ -371,7 +371,7 @@ void vos_pkt_trace_buf_dump local_time = (u32)(trace_buffer[slot].event_msec_time - (sys_tz.tz_minuteswest * 60)); rtc_time_to_tm(local_time, &tm); - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "%5d : [%02d:%02d:%02d.%06lu] : %s", trace_buffer[slot].order, tm.tm_hour, tm.tm_min, tm.tm_sec, @@ -380,7 +380,7 @@ void vos_pkt_trace_buf_dump } } - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "PACKET TRACE DUMP END"); spin_unlock_bh(&trace_buffer_lock); diff --git a/CORE/VOSS/src/vos_sched.c b/CORE/VOSS/src/vos_sched.c index 03ce10e62e7e..bfe5b3a1f4fe 100644 --- a/CORE/VOSS/src/vos_sched.c +++ b/CORE/VOSS/src/vos_sched.c @@ -76,7 +76,8 @@ #define MAX_SSR_PROTECT_LOG (16) /* Timer value for detecting thread stuck issues */ -#define THREAD_STUCK_TIMER_VAL 5000 /* 5 seconds */ +#define THREAD_STUCK_TIMER_VAL 10000 /* 10 seconds */ +#define THREAD_STUCK_THRESHOLD 1 static atomic_t ssr_protect_entry_count; static atomic_t load_unload_protect_count; @@ -988,12 +989,11 @@ static void vos_wd_detect_thread_stuck(void) spin_lock_irqsave(&gpVosWatchdogContext->thread_stuck_lock, flags); - if (gpVosWatchdogContext->mc_thread_stuck_count) { + if (gpVosWatchdogContext->mc_thread_stuck_count == + THREAD_STUCK_THRESHOLD) { spin_unlock_irqrestore(&gpVosWatchdogContext->thread_stuck_lock, flags); - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: Thread Stuck!!! MC Count %d", __func__, - gpVosWatchdogContext->mc_thread_stuck_count); + hddLog(LOGE, FL("MC Thread Stuck!!!")); vos_dump_stack(gpVosSchedContext->McThread); vos_flush_logs(WLAN_LOG_TYPE_FATAL, @@ -1004,11 +1004,18 @@ static void vos_wd_detect_thread_stuck(void) flags); } + if (!gpVosWatchdogContext->mc_thread_stuck_count) { + spin_unlock_irqrestore(&gpVosWatchdogContext->thread_stuck_lock, + flags); + vos_probe_threads(); + spin_lock_irqsave(&gpVosWatchdogContext->thread_stuck_lock, + flags); + } + /* Increment the thread stuck count for all threads */ gpVosWatchdogContext->mc_thread_stuck_count++; spin_unlock_irqrestore(&gpVosWatchdogContext->thread_stuck_lock, flags); - vos_probe_threads(); /* Restart the timer */ if (VOS_STATUS_SUCCESS != |
